eclipse-jdt / eclipse.jdt.core

Eclipse Public License 2.0
165 stars 130 forks source link

Type Inference in builder pattern is inconsistent with javac #494

Open testforstephen opened 2 years ago

testforstephen commented 2 years ago
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.function.Function;

public class BuilderTest {
    public static void main(String[] args) {
        // passed.
        Builder<Object> builder1 = builderOfStage(e -> CompletableFuture.completedFuture("test1"));

        // failed. Type mismatch: cannot convert from Builder<String> to Builder<Object>
        Builder<Object> builder2 = builderOfStage(e -> CompletableFuture.completedFuture("test2")).withAsync();
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    static <R> Builder<R> builderOfStage(Function<? extends R, ? extends CompletionStage<R>> fallback) {
        return new Builder(fallback);
    }
}

class Builder<R> {
    boolean async;

    Builder(Function<R, CompletableFuture<R>> fallbackStage) {
    }

    public Builder<R> withAsync() {
        async = true;
        return this;
    }
}

In javac, both "builder1" and "builder2" compile fine. In ecj, "builder1" passed, but "builder2" failed with error message "Type mismatch: cannot convert from Builder\<String> to Builder\<Object>".

testforstephen commented 2 years ago

@stephan-herrmann Any thoughts on this?

stephan-herrmann commented 7 months ago

Sorry this escaped my attention.

At first glance I like the result from ecj better, because: