| Summary: | A Class<? extends RawType> = Impl.class where RawType is a nested interface within a generic class fails compilation | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | David Elliott <dfe+eclipse> |
| Component: | Core | Assignee: | Till Brychcy <register.eclipse> |
| Status: | VERIFIED FIXED | QA Contact: | Stephan Herrmann <stephan.herrmann> |
| Severity: | major | ||
| Priority: | P3 | CC: | abuehler, dfe+eclipse, jarthana, register.eclipse, stephan.herrmann |
| Version: | 4.7 | Flags: | stephan.herrmann:
review?
(stephan.herrmann) |
| Target Milestone: | 4.8 M4 | ||
| Hardware: | Macintosh | ||
| OS: | Mac OS X | ||
| See Also: |
https://git.eclipse.org/r/100969 https://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=30089883a917eade20b36479b5c83c148ec35e5a https://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=143b17c103956858fc3a331c687d4e89e8148cdd https://git.eclipse.org/r/110746 https://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=1eb1eeafeb83314c2c9956f72dab41ada788a34c |
||
| Whiteboard: | |||
| Bug Depends on: | |||
| Bug Blocks: | 526423 | ||
Putting this on our radar, but currently Java 9 work has priority. Meant to mention that the change in behavior was caused by the fix in bug 460491. New Gerrit change created: https://git.eclipse.org/r/100969 ANALYSIS: At the location... RawTypeBinding(TypeBinding).isTypeArgumentContainedBy(TypeBinding) line: 1271 ParameterizedTypeBinding.isEquivalentTo(TypeBinding) line: 837 ParameterizedTypeBinding(ReferenceBinding).isCompatibleWith0(TypeBinding, Scope) line: 1325 ParameterizedTypeBinding(ReferenceBinding).isCompatibleWith(TypeBinding, Scope) line: 1300 FieldDeclaration.resolve(MethodScope) line: 271 TypeDeclaration.resolve() line: 1131 TypeDeclaration.resolve(CompilationUnitScope) line: 1308 CompilationUnitDeclaration.resolve() line: 605 AbstractRegressionTest$4(Compiler).process(CompilationUnitDeclaration, int) line: 867 ...the variable "match" (returned by upperBound.findSuperTypeOriginatingFrom(otherBound)) is: RawClassParameterizationBug.Example#RAW but "otherBound" is: RawClassParameterizationBug#RAW.Example#RAW So in the first case, the (statically) enclosing class is not RAW. This is caused by addition of "&& !originalType.isStatic()" to the if() in line 521 of org.eclipse.jdt.internal.compiler.lookup.Scope.Substitutor.substitute(Substitution, TypeBinding) for bug 460491 PATCH: A possible patch could be in org.eclipse.jdt.internal.compiler.lookup.Scope.Substitutor.substitute so "match" ends up to be "RawClassParameterizationBug#RAW.Example#RAW" (like pre-bug 460491) But I think it is really better, if statically enclosing classes are always the original() type (so "otherBound" will be "RawClassParameterizationBug.Example#RAW"): (In reply to Eclipse Genie from comment #3) > New Gerrit change created: https://git.eclipse.org/r/100969 Stephan (when you have time), do you agree with the solution? As this is a regression in 4.7, this should probably go into 4.7.1, too. But as I understand that the master should better stay untouched until the Java 9 patch is finished, I'm setting 4.8M2 as target. Gerrit change https://git.eclipse.org/r/100969 was merged to [master]. Commit: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=30089883a917eade20b36479b5c83c148ec35e5a (In reply to Eclipse Genie from comment #6) > Gerrit change https://git.eclipse.org/r/100969 was merged to [master]. > Commit: > http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/ > ?id=30089883a917eade20b36479b5c83c148ec35e5a Released for 4.8M3 I have merged this now, so it some time in a milestone build before a possible backport to 4.7.2, for which I'm reopening this. Causes bug 526423, so I'll revert the commit for 4.8M3. Reverted with http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=143b17c103956858fc3a331c687d4e89e8148cdd New Gerrit change created: https://git.eclipse.org/r/110746 (In reply to Eclipse Genie from comment #11) > New Gerrit change created: https://git.eclipse.org/r/110746 The isStatic()-check needed to be done at beginning of getRawType(), before checking for derived types. Released for 4.8M4 It seems the Genie still still doesn't work after the bugzilla upgrade. Resolved with https://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=1eb1eeafeb83314c2c9956f72dab41ada788a34c *** Bug 527632 has been marked as a duplicate of this bug. *** Verified for 4.8 M4 using build I20171205-2000. |
*** Overview This is a new bug in Oxygen; Neon is able to compile this code, as is javac. The problem occurs when a generic interface is nested inside a generic class. If the outer class is not generic then JDT behaves correctly. Unfortunately this is unavoidable in some cases (e.g. Map.Entry is a generic interface nested inside a generic class). *** Steps to reproduce Try to compile this class: package com.example; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Demonstration class * <p> * Bug is that if the class containing a nested generic interface is itself generic then * JDT does not recognize implementations of it as extending it. * @param <Oops> Any gneeric parameter, the mere existence of which causes the bug. */ class RawClassParameterizationBug<Oops> { public interface Example<K,V> { } public static class DefaultExample<K,V> implements Example<K,V> { } public static class SpecializedExample implements Example<Long,String> { } /** * Works when the interface is fully specialized */ static final Class<? extends Example> works = SpecializedExample.class; /** * {@literal Type mismatch: cannot convert from Class<RawClassParameterizationBug.DefaultExample> to Class<? extends RawClassParameterizationBug.Example>} */ static final Class<? extends Example> fails = DefaultExample.class; } /** * Second demonstration, making use of JRE interfaces. */ class AlternateRawClassParameterizationBug { abstract static class MapEntry<K,V> implements Map.Entry<K, V> { } /** * Fails because Entry is a generic interface nested with Map which is also * generic */ static final Class<? extends Map.Entry> mapFails = MapEntry.class; /** * Works because List is a non-nested interface. Although nesting a generic * interface in a non-generic class would also work. */ static final Class<? extends List> listWorks = ArrayList.class; } *** Expected Results All of this code should compile. *** Actual Results It does not compile, failing to understand that raw DefaultExample does in fact extend raw Example and raw MapEntry does in fact extend raw Map.Entry. It does, however, correctly recognize that raw ArrayList extends raw List.