manifold
manifold copied to clipboard
[Bug] Can't define extension method for super class of class with same extension method
Describe the bug When creating the filter and map extension method for Iterable<T>, I get the follwing error:
Compilation failure: Compilation failure:
[ERROR] /java/util/List.java:[5,17] name clash: filter(java.util.function.Predicate<? super E>) in java.util.Collection and filter(java.util.function.Predicate<E>) in java.lang.Iterable have the same erasure, yet neither overrides the other
[ERROR] /java/util/Collection.java:[37,48] name clash: map(java.util.function.Function<? super E,R>) in java.util.Collection and map(java.util.function.Function<E,R>) in java.lang.Iterable have the same erasure, yet neither overrides the other
[ERROR] /java/util/Collection.java:[41,45] name clash: filter(java.util.function.Predicate<? super E>) in java.util.Collection and filter(java.util.function.Predicate<E>) in java.lang.Iterable have the same erasure, yet neither overrides the other
To Reproduce Steps to reproduce the behavior:
- Create a project with manifold-ext and manifold-collections
- Add the following code:
package extensions.java.lang.Iterable;
import manifold.ext.rt.api.Extension;
import manifold.ext.rt.api.This;
import java.util.Collection;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@Extension
public class IterableExt {
public static <T> Stream<T> stream(@This Iterable<T> thiz) {
return thiz instanceof Collection<T> collection
? collection.stream()
: StreamSupport.stream(thiz.spliterator(), false);
}
public static <T> Stream<T> filter(@This Iterable<T> thiz, Predicate<T> predicate) {
return thiz.stream().filter(predicate);
}
public static <T, R> Stream<R> map(@This Iterable<T> thiz, Function<T, R> mapper) {
return thiz.stream().map(mapper);
}
}
- Compile it
Expected behavior I expect to be able to create an extension method for a superclass of a class that already has that same extension method.
Desktop (please complete the following information):
- OS Type & Version: Windows 10
- Java/JDK version: openjdk-20.0.2
- IDE version (IntelliJ IDEA or Android Studio): IntelliJ 2023.1.5
- Manifold version: 2023.1.20
- Manifold IntelliJ plugin version: 23.1.15
Additional context This page makes it look like you should be able to do what I want, but I don't know if the target being interfaces rather than classes has anything to do with the error.
It would also be nice if the IntelliJ plugin showed these method signature conflict issues before compilation.
Overriding method signatures must exactly match, this includes type variable variance. This means the extension methods used in your project, if they are overrides, must have exactly the same parameter definitions.
For instance, the following error is saying after erasing generics from the methods they are an override pair, however the generic signatures don't match.
filter(java.util.function.Predicate<? super E>) in java.util.Collection and
filter(java.util.function.Predicate<E>) in java.lang.Iterable have the same erasure, yet neither overrides the other
You can change your Predicate<E> to Predicate<? super E> to fix that. And as an aside, that's probably what you want anyway.
Repeat for the other two methods.
I'll add a compile error in IJ to reflect this as well.
Ah derp! You're right, I completely forgot the bounded wildcards!
Thanks for taking your time to look at this.