Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected cast compile error for generic type argument #837

Open
trancexpress opened this issue Mar 14, 2023 · 3 comments
Open

Unexpected cast compile error for generic type argument #837

trancexpress opened this issue Mar 14, 2023 · 3 comments
Labels
bug Something isn't working

Comments

@trancexpress
Copy link
Contributor

See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=562230

To reproduce, paste the following snippet in Eclipse:

package test;

import java.util.Collections;
import java.util.List;

public class Test {

	public static <Z extends Comparable<? super Z>> String test(List<Z> in) {
		List<String> x = (List<String>) in;
		return x.get(0);
	}

    public static void main(String[] args) {
        List<String> list = Collections.singletonList("hello");
        String string = Test.<String>test(list);
        System.out.println(string);
    }
}

Compile and run with javac/java (OpenJDK 17), observe no errors:

➜  src /usr/lib/jvm/java-17-openjdk/bin/javac test/Test.java
Note: test/Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
➜  src /usr/lib/jvm/java-17-openjdk/bin/java test.Test      
hello

With ecj/Eclipse though, observe compile error:

Description	Resource	Path	Location	Type
Cannot cast from List<Z> to List<String>	Test.java	/TestBug562230/src/test	line 9	Java Problem

The problem is created here:

"org.eclipse.jdt.internal.ui.text.JavaReconciler" #82 daemon prio=1 os_prio=0 cpu=1512.91ms elapsed=1783.09s tid=0x00007f381e1e6bb0 nid=0x1251 at breakpoint [0x00007f377cae6000]
   java.lang.Thread.State: RUNNABLE
        at org.eclipse.jdt.internal.compiler.problem.ProblemHandler.handle(ProblemHandler.java:130)
        at org.eclipse.jdt.internal.compiler.problem.ProblemHandler.handle(ProblemHandler.java:229)
        at org.eclipse.jdt.internal.compiler.problem.ProblemReporter.handle(ProblemReporter.java:2679)
        at org.eclipse.jdt.internal.compiler.problem.ProblemReporter.typeCastError(ProblemReporter.java:8542)
        at org.eclipse.jdt.internal.compiler.ast.CastExpression.resolveType(CastExpression.java:676)
        at org.eclipse.jdt.internal.compiler.ast.LocalDeclaration.resolve(LocalDeclaration.java:390)
        at org.eclipse.jdt.internal.compiler.ast.LocalDeclaration.resolve(LocalDeclaration.java:259)
        at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:662)
        at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:388)
        at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:571)
        at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1506)
        at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1631)
        at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:668)
        at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:1069)
        at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:1111)
        at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:282)
        at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:348)
        at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.makeConsistent(ReconcileWorkingCopyOperation.java:193)
        at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.executeOperation(ReconcileWorkingCopyOperation.java:94)
        at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:740)
        at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:806)
        at org.eclipse.jdt.internal.core.CompilationUnit.reconcile(CompilationUnit.java:1325)
        at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:132)
        at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy$1.run(JavaReconcilingStrategy.java:94)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:91)
        at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:158)
        at org.eclipse.jdt.internal.ui.text.CompositeReconcilingStrategy.reconcile(CompositeReconcilingStrategy.java:94)
        at org.eclipse.jdt.internal.ui.text.JavaCompositeReconcilingStrategy.reconcile(JavaCompositeReconcilingStrategy.java:107)
        at org.eclipse.jface.text.reconciler.MonoReconciler.process(MonoReconciler.java:78)
        at org.eclipse.jface.text.reconciler.AbstractReconciler$BackgroundThread.run(AbstractReconciler.java:207)

Changing the generics type argument to Z extends Comparable<? extends Z> results in no compile error with ecj.

@trancexpress
Copy link
Contributor Author

trancexpress commented Mar 14, 2023

The cast is determined to be between "provably distinct" types by this stack trace:

"Compiler Processing Task" #286 daemon prio=5 os_prio=0 cpu=553.43ms elapsed=883.26s tid=0x00007f35e416aa00 nid=0x3b31 runnable  [0x00007f36181fd000]
   java.lang.Thread.State: RUNNABLE
        at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.isEquivalentTo(BinaryTypeBinding.java:1746)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isSuperclassOf(ReferenceBinding.java:1739)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith0(ReferenceBinding.java:1556)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith(ReferenceBinding.java:1465)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isCompatibleWith(TypeBinding.java:679)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isTypeArgumentContainedBy(TypeBinding.java:1361)
        at org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding.isEquivalentTo(ParameterizedTypeBinding.java:994)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.implementsInterface(ReferenceBinding.java:1336)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith0(ReferenceBinding.java:1543)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith(ReferenceBinding.java:1465)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isCompatibleWith(TypeBinding.java:679)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isProvableDistinctSubType(TypeBinding.java:875)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isProvablyDistinctTypeArgument(TypeBinding.java:1169)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isProvablyDistinct(TypeBinding.java:942)
        at org.eclipse.jdt.internal.compiler.ast.CastExpression.checkUnsafeCast(CastExpression.java:416)
        at org.eclipse.jdt.internal.compiler.ast.CastExpression.checkUnsafeCast(CastExpression.java:400)
        at org.eclipse.jdt.internal.compiler.ast.Expression.checkCastTypesCompatibility(Expression.java:462)
        at org.eclipse.jdt.internal.compiler.ast.CastExpression.resolveType(CastExpression.java:654)
        at org.eclipse.jdt.internal.compiler.ast.LocalDeclaration.resolve(LocalDeclaration.java:390)
        at org.eclipse.jdt.internal.compiler.ast.LocalDeclaration.resolve(LocalDeclaration.java:259)
        at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:662)
        at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:388)
        at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:571)
        at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1506)
        at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1631)
        at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:668)
        at org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:905)
        at org.eclipse.jdt.internal.compiler.ProcessTaskManager.run(ProcessTaskManager.java:145)
        at java.lang.Thread.run(java.base@17.0.6/Thread.java:833)

For whatever reason WildcardBinding.isCompatibleWith() determines that String is not compatible with ?. (coming from ? super Z)...

When using extends instead of super, the types are not "provably distinct" due to this stack trace:

"org.eclipse.jdt.internal.ui.text.JavaReconciler" #82 daemon prio=1 os_prio=0 cpu=1746.15ms elapsed=4360.63s tid=0x00007f381e1e6bb0 nid=0x1251 runnable  [0x00007f377cae6000]
   java.lang.Thread.State: RUNNABLE
        at org.eclipse.jdt.internal.compiler.lookup.WildcardBinding.boundCheck(WildcardBinding.java:236)
        at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.isEquivalentTo(BinaryTypeBinding.java:1734)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith0(ReferenceBinding.java:1490)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith(ReferenceBinding.java:1465)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isCompatibleWith(TypeBinding.java:679)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isTypeArgumentContainedBy(TypeBinding.java:1343)
        at org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding.isEquivalentTo(ParameterizedTypeBinding.java:994)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.implementsInterface(ReferenceBinding.java:1336)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith0(ReferenceBinding.java:1543)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith(ReferenceBinding.java:1465)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isCompatibleWith(TypeBinding.java:679)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isProvableDistinctSubType(TypeBinding.java:875)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isProvablyDistinctTypeArgument(TypeBinding.java:1169)
        at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.isProvablyDistinct(TypeBinding.java:942)
        at org.eclipse.jdt.internal.compiler.ast.CastExpression.checkUnsafeCast(CastExpression.java:416)
        at org.eclipse.jdt.internal.compiler.ast.CastExpression.checkUnsafeCast(CastExpression.java:400)
        at org.eclipse.jdt.internal.compiler.ast.Expression.checkCastTypesCompatibility(Expression.java:462)
        at org.eclipse.jdt.internal.compiler.ast.CastExpression.resolveType(CastExpression.java:654)
        at org.eclipse.jdt.internal.compiler.ast.LocalDeclaration.resolve(LocalDeclaration.java:390)
        at org.eclipse.jdt.internal.compiler.ast.LocalDeclaration.resolve(LocalDeclaration.java:259)
        at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:662)
        at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:388)
        at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:571)
        at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1506)
        at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1631)
        at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:668)
        at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:1069)
        at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:1111)
        at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:282)
        at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:348)
        at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.makeConsistent(ReconcileWorkingCopyOperation.java:193)
        at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.executeOperation(ReconcileWorkingCopyOperation.java:94)
        at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:740)
        at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:806)
        at org.eclipse.jdt.internal.core.CompilationUnit.reconcile(CompilationUnit.java:1325)
        at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:132)
        at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy$1.run(JavaReconcilingStrategy.java:94)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:91)
        at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:158)
        at org.eclipse.jdt.internal.ui.text.CompositeReconcilingStrategy.reconcile(CompositeReconcilingStrategy.java:94)
        at org.eclipse.jdt.internal.ui.text.JavaCompositeReconcilingStrategy.reconcile(JavaCompositeReconcilingStrategy.java:107)
        at org.eclipse.jface.text.reconciler.MonoReconciler.process(MonoReconciler.java:78)
        at org.eclipse.jface.text.reconciler.AbstractReconciler$BackgroundThread.run(AbstractReconciler.java:207)

I.e. this code exits for the ? extends Z case, :

private boolean isCompatibleWith0(TypeBinding otherType, /*@Nullable*/ Scope captureScope) {
	if (TypeBinding.equalsEquals(otherType, this))
		return true;
	if (otherType.id == TypeIds.T_JavaLangObject)
		return true;
	// equivalence may allow compatibility with array type through wildcard
	// bound
	if (isEquivalentTo(otherType))
		return true; // code exists here, i.e. "early"

For the ? super Z case, this code is asking whether the type binding for ? is equivalent to String. I.e. in this code, otherType is String and so no bound check is done...:

public boolean isEquivalentTo(TypeBinding otherType) {
	if (equalsEquals(this, otherType))
		return true;
	if (otherType == null)
		return false;
	switch (otherType.kind()) {
		case Binding.WILDCARD_TYPE :
		case Binding.INTERSECTION_TYPE :
			return ((WildcardBinding) otherType).boundCheck(this);
	}
	return false;
}

When using ? extends Z, otherType is always ? and not String.

I.e. this change "fixes" the bug:

diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index c2504a7f98..72be5f8110 100644
--- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -1486,7 +1486,7 @@ private boolean isCompatibleWith0(TypeBinding otherType, /*@Nullable*/ Scope cap
                return true;
        // equivalence may allow compatibility with array type through wildcard
        // bound
-       if (isEquivalentTo(otherType))
+       if (isEquivalentTo(otherType) || otherType.isEquivalentTo(this))
                return true;
        switch (otherType.kind()) {
                case Binding.WILDCARD_TYPE :

Will have to check why the parameters are turned around for the ? super Z case... Seems to be due to this code in TypeBinding.isTypeArgumentContainedBy(TypeBinding):

				case Wildcard.EXTENDS:
					...
					return upperBound.isCompatibleWith(otherBound);

				case Wildcard.SUPER:
					...
					return otherBound.isCompatibleWith(lowerBound);

The method comment explaining this:

/* Answer true if the receiver type can be assigned to the argument type (right)
 */
public boolean isCompatibleWith(TypeBinding right) {

I'm not sure how much sense it makes to check whether String can be assigned a ?. Code was added for: https://bugs.eclipse.org/bugs/show_bug.cgi?id=216686

TypeBinding.isProvablyDistinctTypeArgument() does a call to Scope.convertEliminatingTypeVariables() which seems to be the reason for seeing the ?... The upper bound for the check becomes Comparable<? super ?> (where originally its Comparable<? super Z> and for this comparison, its in reality Comparable<? super String>). Looks like important information that is lost before the actual check for distinct types...

@trancexpress
Copy link
Contributor Author

trancexpress commented Mar 14, 2023

Makes me wonder what ecj does for the method invocation. It must be something else since it allows the method invocation with String (but according to the cast expression, String is not an allowed type... which is wrong).

The compile of the method invocation seems to be comparing different things (different to what the cast check compares):

"Compiler Processing Task" #130 daemon prio=5 os_prio=0 cpu=73.75ms elapsed=117.13s tid=0x00007f7888057bb0 nid=0xc58b runnable  [0x00007f7aa81d2000]
   java.lang.Thread.State: RUNNABLE
        at org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding.isEquivalentTo(ParameterizedTypeBinding.java:998)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.implementsInterface(ReferenceBinding.java:1336)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith0(ReferenceBinding.java:1542)
        at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith(ReferenceBinding.java:1464)
        at org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding.internalBoundCheck(TypeVariableBinding.java:272)
        at org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding.boundCheck(TypeVariableBinding.java:125)
        at org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding.boundCheck18(ParameterizedGenericMethodBinding.java:332)
        at org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding.computeCompatibleMethod18(ParameterizedGenericMethodBinding.java:294)
        at org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding.computeCompatibleMethod(ParameterizedGenericMethodBinding.java:92)
        at org.eclipse.jdt.internal.compiler.lookup.Scope.computeCompatibleMethod(Scope.java:841)
        at org.eclipse.jdt.internal.compiler.lookup.Scope.computeCompatibleMethod(Scope.java:798)
        at org.eclipse.jdt.internal.compiler.lookup.Scope.findMethod0(Scope.java:1755)
        at org.eclipse.jdt.internal.compiler.lookup.Scope.findMethod(Scope.java:1656)
        at org.eclipse.jdt.internal.compiler.lookup.Scope.getImplicitMethod(Scope.java:2622)
        at org.eclipse.jdt.internal.compiler.ast.MessageSend.findMethodBinding(MessageSend.java:1019)
        at org.eclipse.jdt.internal.compiler.ast.MessageSend.resolveType(MessageSend.java:835)
        at org.eclipse.jdt.internal.compiler.ast.Expression.resolve(Expression.java:1113)
        at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:662)
        at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:388)
        at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:571)
        at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1506)
        at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1631)
        at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:668)
        at org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:905)
        at org.eclipse.jdt.internal.compiler.ProcessTaskManager.run(ProcessTaskManager.java:145)
        at java.lang.Thread.run(java.base@17.0.6/Thread.java:833)

At the deepest stack frame, this is:

public interface Comparable<java.lang.String>
	extends java.lang.ObjectNULL FIELDSNULL METHODS

And otherType is:

public interface Comparable<? super java.lang.String>
	extends NULL TYPENULL SUPERINTERFACESNULL FIELDSNULL METHODS

Whereas the cast check ends up comparing this (thanks to Scope.convertEliminatingTypeVariables()):

public interface Comparable<java.lang.String>
	extends java.lang.ObjectNULL FIELDSNULL METHODS

And otherType:

public interface Comparable<? super ?>
	extends NULL TYPENULL SUPERINTERFACESNULL FIELDSNULL METHODS

trancexpress added a commit to trancexpress/eclipse.jdt.core that referenced this issue Mar 14, 2023
Given a generic type defined as "<Z extends Comparable<? super Z>>", the
compiler fails to cast List<Z> to e.g. List<String>. Despite String
fulfilling the bound requirements for Z (String implements
Comparable<String>).

For this particular case, the bug occurs due to:

For the "? super Z" bound, TypeBinding.isTypeArgumentContainedBy() calls
isCompatibleWith() on String, with argument the lower bound "?". Then in
ReferenceBinding.isCompatibleWith0() the equivalence check fails, since
String doesn't evaluate to being equivalent to "?" - String is not a
parameterized type.

This change adds an extra equivalence check, ensuring "?" is tested for
equivalence to String (or any other type that would fit the generic
argument bounds).

Fixes: eclipse-jdt#837
Signed-off-by: Simeon Andreev <simeon.danailov.andreev@gmail.com>
@trancexpress trancexpress added the bug Something isn't working label Mar 16, 2023
@stephan-herrmann
Copy link
Contributor

FYI, cast compatibility is specified in JLS 5.1.6.1 which refers to the definition of "provably distinct" inside JLS 4.5.

Here's a group of bugs that motivated our existing code:

Apparently, Philipe was struggling with a fuzzy spec and worked from additional information about intended spec changes.

To find out the intended semantics it should be worth looking into https://bugs.openjdk.org/browse/JDK-6790039 and children. E.g., Mauricio mentions replacing captures with wildcards as essential in javac's implementation, which is absent from the spec as far as I can see.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants