Bug 434118 - [1.8][compiler] Compilation error on generic capture/type inference
Summary: [1.8][compiler] Compilation error on generic capture/type inference
Status: VERIFIED DUPLICATE of bug 444334
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.4   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 4.5 M3   Edit
Assignee: Srikanth Sankaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 428061 434115
  Show dependency tree
 
Reported: 2014-05-05 09:35 EDT by Frank Pavageau CLA
Modified: 2014-10-28 04:49 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 Frank Pavageau CLA 2014-05-05 09:35:34 EDT
I ran into this problem using AspectJ 1.8, but it can also be reproduced by calling ECJ directly, so it's not introduced by AspectJ's usage of ECJ.

Consider the following class:
public class WildcardCapture {
    public Object convertFails(Class<?> clazz, String value) {
        return Enum.valueOf(clazz.asSubclass(Enum.class), value);
    }

    public Object convertCompiles(Class<?> clazz, String value) {
        return Enum.valueOf(clazz.<Enum>asSubclass(Enum.class), value);
    }

    public Object convertCompiles2(Class<?> clazz, String value) {
        Class<? extends Enum> enumType = clazz.asSubclass(Enum.class);
        return Enum.valueOf(enumType, value);
    }
}

The first method fails to compile, the other two have no problem (by either specifying a second type the generic type, or extracting the variable).

Using the most recent deployment of ECJ in Maven Central, I get:
$ java -jar ~/.m2/repository/org/eclipse/jdt/core/compiler/ecj/P20140317-1600/ecj-P20140317-1600.jar -1.8 -deprecation WildcardCapture.java 
----------
1. ERROR in /home/pavageau/devs/aspectj/wildcard-capture/src/main/java/WildcardCapture.java (at line 3)
	return Enum.valueOf(clazz.asSubclass(Enum.class), value);
	            ^^^^^^^
The method valueOf(Class<T>, String) in the type Enum is not applicable for the arguments (Class<capture#2-of ? extends Enum>, String)
----------
2. WARNING in /home/pavageau/devs/aspectj/wildcard-capture/src/main/java/WildcardCapture.java (at line 7)
	return Enum.valueOf(clazz.<Enum>asSubclass(Enum.class), value);
	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Type safety: Unchecked invocation valueOf(Class<capture#4-of ? extends Enum>, String) of the generic method valueOf(Class<T>, String) of type Enum
----------
3. WARNING in /home/pavageau/devs/aspectj/wildcard-capture/src/main/java/WildcardCapture.java (at line 7)
	return Enum.valueOf(clazz.<Enum>asSubclass(Enum.class), value);
	                           ^^^^
Enum is a raw type. References to generic type Enum<E> should be parameterized
----------
4. WARNING in /home/pavageau/devs/aspectj/wildcard-capture/src/main/java/WildcardCapture.java (at line 11)
	Class<? extends Enum> enumType = clazz.asSubclass(Enum.class);
	                ^^^^
Enum is a raw type. References to generic type Enum<E> should be parameterized
----------
5. WARNING in /home/pavageau/devs/aspectj/wildcard-capture/src/main/java/WildcardCapture.java (at line 12)
	return Enum.valueOf(enumType, value);
	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Type safety: Unchecked invocation valueOf(Class<capture#7-of ? extends Enum>, String) of the generic method valueOf(Class<T>, String) of type Enum
----------
5 problems (1 error, 4 warnings)


Note that this compiles fine using javac from Oracle JDK 6, 7 or 8, and AspectJ 1.6 and 1.7 also compile it (with matching versions of ECJ embeded).
Comment 1 Srikanth Sankaran CLA 2014-05-06 21:50:34 EDT
Thanks for taking a look Stephan,
Comment 2 Stephan Herrmann CLA 2014-07-31 16:36:41 EDT
In fact, it's type inference that correctly fails due to this constraint:

  ⟨java.lang.Enum <: java.lang.Enum<T#0>⟩

Next, if I disable our javac bug-compatibility flag SIMULATE_BUG_JDK_8026527 all three variants are rejected (as per JLS).

If instead, I flip the detail of the former, ARGUMENT_CONSTRAINTS_ARE_SOFT, all three variants are accepted.

Ergo: we could resolve either way, but each of these bug compatibility flags has already been fine tuned for best similarity with buggy javac.

I have no hope that we can improve here, before javac has cleaned up that cluster of known bugs.


Note, that at -1.7 all compilers are known to illegally admit constraints like the above. Hence, it comes to no surprise that ecj -1.7, too, accepts the program -- erroneously.
Comment 3 Srikanth Sankaran CLA 2014-09-18 00:06:30 EDT
Targetting for 4.5 M3. While ATM ownership is left unchanged, Stephan is under
time constraint during this window, so I will likely take this over or assign to someone else to load balance later on.
Comment 4 Srikanth Sankaran CLA 2014-10-20 08:33:53 EDT
This is simply a variant of the issue discussed at https://bugs.eclipse.org/bugs/show_bug.cgi?id=430987#c13

Is Class<? extends Enum#RAW> asSubclass(Class<Enum#RAW>) a poly expression ?

I think not since it does not mention in its return type any type variables.

But to reach past the jlO substitutions, we reach into the generic method and
get misled.

But the fix at that bug does not cover this case as I am just checking
for return type being raw and Class<? extends Enum#RAW> is not raw in itself.

I'll see how I can extend that.
Comment 5 Srikanth Sankaran CLA 2014-10-20 09:03:46 EDT
(In reply to Srikanth Sankaran from comment #4)
> This is simply a variant of the issue discussed at
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=430987#c13
> 
> Is Class<? extends Enum#RAW> asSubclass(Class<Enum#RAW>) a poly expression ?
> 
> I think not since it does not mention in its return type any type variables.
> 
> But to reach past the jlO substitutions, we reach into the generic method and
> get misled.

Rereading the definition:

The method to be invoked, as determined by the following subsections, is 
generic (§8.4.4) and has a return type that mentions at least one of the 
method's type parameters

looks straightforward enough that we should reach into the generic method
(not just because we could find jlO instantiations in the PGMB that would
mask type variable mention) by definition.

But javac must either be making exceptions when type arguments are seen to
be raw types or using some form of unofficial soft constraints.
Comment 6 Srikanth Sankaran CLA 2014-10-27 18:35:33 EDT
Bug went away with the fix for bug 444334.

Released a junit here: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=736a3352edee05c04aa96eb4323328cfa8fdbdd5

*** This bug has been marked as a duplicate of bug 444334 ***
Comment 7 Jay Arthanareeswaran CLA 2014-10-28 04:49:42 EDT
Verified for 4.5 M3 using I20141027-2000 build