Bug 539732 - [1.8][compiler] "Illegal reference to super method" when overriding default method with generic return
Summary: [1.8][compiler] "Illegal reference to super method" when overriding default m...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.8   Edit
Hardware: PC Windows 10
: P3 normal with 1 vote (vote)
Target Milestone: 4.13 M3   Edit
Assignee: Till Brychcy CLA
QA Contact: Stephan Herrmann CLA
URL:
Whiteboard:
Keywords: regression
Depends on:
Blocks:
 
Reported: 2018-10-02 11:46 EDT by Sean Van Gorder CLA
Modified: 2019-08-21 06:50 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sean Van Gorder CLA 2018-10-02 11:46:21 EDT
When overriding a default method with a generic return type, if a super call is passed directly to any method with a generic parameter type, the compiler gives the error "Illegal reference to super method f() from type Test.Foo, cannot bypass the more specific override from type Test.Foo". Oracle javac (jdk1.8.0_181) compiles this without error.

public class Test {

    interface Foo {
        @SuppressWarnings("unchecked")
        default <T> T f() {
            return (T) new Object();
        }
    }

    static class Bar implements Foo {
        @Override
        public <T> T f() {
            Objects.hashCode(Foo.super.f()); // OK
            Objects.equals(Foo.super.f(), Foo.super.f()); // OK

            Objects.requireNonNull(Foo.super.f()); // bug
            Optional.of(Foo.super.f()); // bug

            T s = Foo.super.f();
            Objects.requireNonNull(s); // OK
            Optional.of(s); // OK

            return Foo.super.f();
        }
    }
}

Passing the call as an Object method parameter compiles fine, but passing it as a generic method parameter fails to compile. A local variable can be used as a simple workaround.

This bug also occurs when the overridden default method has parameters, like "default <T> T f(T x)" (which can avoid the unchecked cast), but this seemed like a better example. The bug does NOT occur if the return type is changed to a non-generic type, like Object.
Comment 1 Sean Van Gorder CLA 2018-10-02 12:04:58 EDT
On a side note, if you add the line "System.out.println(Foo.super.f());" to the example method, it will fail in BOTH compilers with an ambiguous method error, instead of selecting the overload with an Object parameter. Not sure if this is correct behavior, since the local variable workaround works for this as well.

Strangely, this other error does not occur if the default method has a parameter that incorporates the same generic type parameter as the return type. "<T> T f(T x)", "<T> T f(List<T> x)", and "<T, S> T f(Map<T, S> x)" will compile, but "<T, S> T f(S x)" and "<T, S> T f(List<S> x)" will not.
Comment 2 Stephan Herrmann CLA 2018-10-02 14:22:24 EDT
This looks fishy, thanks for the report.

This used to work, but fails starting with 4.8 M3.

On a side note: a method like "<T> T f()" can almost never be implemented to fulfill its own contract, which says: "I'll provide an object of the type which you may freely pick even without telling me".
With this, it is not a big surprise that it makes a difference if you also pass in a parameter of the same type.
Comment 3 Sean Van Gorder CLA 2018-10-02 15:26:48 EDT
True, that kind of method is pointless, but T is still always guaranteed to extend Object, so it's perfectly type-safe to pass it to a method expecting Object. The compiler doesn't complain about ambiguity when given a local variable of type T, so the inconsistency makes me wonder.
Comment 4 Stephan Herrmann CLA 2019-05-21 17:49:53 EDT
(In reply to Stephan Herrmann from comment #2)
> This looks fishy, thanks for the report.
> 
> This used to work, but fails starting with 4.8 M3.

this must have been a typo, fails since 4.8 M4, more specifically since bug 515600.

@Till, can you take a look?
Comment 5 Eclipse Genie CLA 2019-05-22 15:06:47 EDT
New Gerrit change created: https://git.eclipse.org/r/142618
Comment 6 Till Brychcy CLA 2019-05-22 15:17:05 EDT
(In reply to Eclipse Genie from comment #5)
> New Gerrit change created: https://git.eclipse.org/r/142618

Pretty obvious: there can be multiple ParameterizedGenericMethodBinding, so we need to compare their .original()
Comment 7 Stephan Herrmann CLA 2019-05-22 16:56:16 EDT
(In reply to Till Brychcy from comment #6)
> (In reply to Eclipse Genie from comment #5)
> > New Gerrit change created: https://git.eclipse.org/r/142618
> 
> Pretty obvious: there can be multiple ParameterizedGenericMethodBinding, so
> we need to compare their .original()

Great find. And the connection to bug 515600 would be, that previously a PGMB was incorrectly shared for a different target type?
Comment 9 Till Brychcy CLA 2019-07-24 02:01:19 EDT
(In reply to Stephan Herrmann from comment #7)
> Great find. And the connection to bug 515600 would be, that previously a
> PGMB was incorrectly shared for a different target type?

Yes.

(In reply to Eclipse Genie from comment #8)
> Gerrit change https://git.eclipse.org/r/142618 was merged to [master].
> Commit:
> http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/
> ?id=fcf2ea3ee3babc632c8b89d189855cc579edd175

Released for 4.13M3
Comment 10 Jay Arthanareeswaran CLA 2019-08-21 06:50:29 EDT
Verified for 4.13 M3 using build I20190820-1800