Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 347426

Summary: [1.7][compiler] ecj behavior differs from javac
Product: [Eclipse Project] JDT Reporter: Srikanth Sankaran <srikanth_sankaran>
Component: CoreAssignee: Srikanth Sankaran <srikanth_sankaran>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: markus.kell.r, Olivier_Thomann, satyam.kandula
Version: 3.7Flags: Olivier_Thomann: review+
Target Milestone: 3.7.1   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Bug Depends on:    
Bug Blocks: 348956    
Attachments:
Description Flags
Early version of a fix.
none
Improved patch - under test
none
Proposed patch - under test.
none
Final patch none

Description Srikanth Sankaran CLA 2011-05-27 05:54:12 EDT
The following code used to compile with javac 5, stopped compiling
with javac6 and started compiling again with javac7. Eclipse HEAD
and BETA_JAVA7 refuse to compile it:


public class X {
    class A<T extends B<?>> {  }

    class B<T extends A<?>> {
        D<? extends B<T>> x;
    }
    class D<T extends B<?>> {}

    <E extends B<?>> X(E x, D<B<A<?>>> d) {
        if (x.x == d) {
            return;
        }
    }
}


This behavior difference needs to be understood.

If I change the line with the if to

       if (x.x == 1) 

javac7 spits out this message:

X.java:10: error: incomparable types: X.D<CAP#1> and int
        if (x.x == 1) {
                ^
  where CAP#1,CAP#2 are fresh type-variables:
    CAP#1 extends X.B<CAP#2> from capture of ? extends X.B<CAP#2>
    CAP#2 extends X.A<?> from capture of ?
1 error

which offers some clue as to what javac thinks the type x.x should be.

Eclipse thinks the type of x.x. is 
    X.D<capture#2-of ? extends X.B<capture#1-of ?>>

Notice the fact that the type A is missing in eclipse assessment of the
type.
Comment 1 Srikanth Sankaran CLA 2011-05-27 05:59:34 EDT
I'll investigate this.
Comment 2 Srikanth Sankaran CLA 2011-05-27 06:07:33 EDT
Released disabled junit test org.eclipse.jdt.core.tests.compiler.regression.GenericsRegressionTest._test347426()
into BETA_JAVA7 stream. I am investigating this.
Comment 3 Srikanth Sankaran CLA 2011-05-27 07:33:23 EDT
Reduced test case:


public class X<T> {
    class A<T extends X<?>> {
        B<? extends A<T>> x;
    }
    class B<T extends A<?>> {}
    boolean b = ((A<?>)null).x == ((B<A<X<?>>>)null);   
}


How can there be a A<?> that is also not "? extends X<?>" ?
It does look like a bug in eclipse. javac7 compiles this fine.

Note however that javac fails on this case while it compiles
the comment#0 case alright.
Comment 4 Srikanth Sankaran CLA 2011-05-27 07:34:53 EDT
(In reply to comment #3)

> Note however that javac fails on this case while it compiles
> the comment#0 case alright.

I meant to say javac5. javac6 fails on both.
Comment 5 Srikanth Sankaran CLA 2011-05-27 08:27:04 EDT
See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6450290 for
some interesting discussion on a somewhat similar javac bug.
Comment 6 Srikanth Sankaran CLA 2011-05-27 11:05:20 EDT
Created attachment 196772 [details]
Early version of a fix.
Comment 7 Srikanth Sankaran CLA 2011-05-27 11:55:09 EDT
Created attachment 196780 [details]
Improved patch - under test
Comment 8 Srikanth Sankaran CLA 2011-05-27 14:08:58 EDT
Created attachment 196795 [details]
Proposed patch - under test.

Closer to final version - under test.
Comment 9 Srikanth Sankaran CLA 2011-05-27 18:58:19 EDT
The latest patch fails to handle this variation which is
compiled alright by javac7:

public class X<T> {
    class A<T extends X<? extends String>> {
        B<? extends A<T>> x;
    }
    class B<T extends A<?>> {}
    boolean b = ((A<? extends X<?>>)null).x == ((B<A<X<? extends String>>>)null);       
}
Comment 10 Srikanth Sankaran CLA 2011-05-27 19:23:33 EDT
Created attachment 196817 [details]
Final patch

Augmented to handle the scenario in comment# 9
Comment 11 Srikanth Sankaran CLA 2011-05-27 20:51:54 EDT
Released in BETA_JAVA7 branch.

Olivier, please take a look and let me know if some cases are still
broken - TIA.

Basically, given class A<T extends B<?>>, A<?> cannot be the universe
of all possible parameterizations, but only that subset that conforms
to ? extends B<?> and the compiler was not making allowance for this
constraint during type equivalence checks.
Comment 12 Olivier Thomann CLA 2011-06-29 10:17:14 EDT
Looks good to me.
Comment 13 Satyam Kandula CLA 2011-07-01 07:21:51 EDT
Verified using Eclipse Java 7 Support(Beta) feature patch v20110623-0900.