diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java index b7869524c77..1f37f9fae74 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java @@ -121,24 +121,31 @@ public class CastDiagnosticsUtil { // Now, let's find a supertype of List that is a Collection of something, // in this case it will be Collection JetType supertypeWithVariables = TypeCheckingProcedure.findCorrespondingSupertype(subtypeWithVariables, supertype); - if (supertypeWithVariables == null) return true; - // Now, let's try to unify Collection and Collection - // solution is a map from T to Foo final List variables = subtypeWithVariables.getConstructor().getParameters(); - TypeUnifier.UnificationResult solution = TypeUnifier.unify( - new TypeProjection(supertype), new TypeProjection(supertypeWithVariables), - new Predicate() { - @Override - public boolean apply(TypeConstructor typeConstructor) { - ClassifierDescriptor descriptor = typeConstructor.getDeclarationDescriptor(); - return descriptor instanceof TypeParameterDescriptor && variables.contains(descriptor); - } - }); + + Map substitution; + if (supertypeWithVariables != null) { + // Now, let's try to unify Collection and Collection solution is a map from T to Foo + TypeUnifier.UnificationResult solution = TypeUnifier.unify( + new TypeProjection(supertype), new TypeProjection(supertypeWithVariables), + new Predicate() { + @Override + public boolean apply(TypeConstructor typeConstructor) { + ClassifierDescriptor descriptor = typeConstructor.getDeclarationDescriptor(); + return descriptor instanceof TypeParameterDescriptor && variables.contains(descriptor); + } + }); + substitution = Maps.newHashMap(solution.getSubstitution()); + } + else { + // If there's no corresponding supertype, no variables are determined + // This may be OK, e.g. in case 'Any as List<*>' + substitution = Maps.newHashMapWithExpectedSize(variables.size()); + } // If some of the parameters are not determined by unification, it means that these parameters are lost, // let's put stars instead, so that we can only cast to something like List<*>, e.g. (a: Any) as List<*> - Map substitution = Maps.newHashMap(solution.getSubstitution()); for (TypeParameterDescriptor variable : variables) { TypeProjection value = substitution.get(variable.getTypeConstructor()); if (value == null) { diff --git a/compiler/testData/diagnostics/tests/cast/isErasedAnyAndStarred.kt b/compiler/testData/diagnostics/tests/cast/isErasedAnyAndStarred.kt new file mode 100644 index 00000000000..61818b7a817 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/isErasedAnyAndStarred.kt @@ -0,0 +1,3 @@ +class G + +fun f(q: Any) = q is G<*> \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cast/isErasedTAndStarred.kt b/compiler/testData/diagnostics/tests/cast/isErasedTAndStarred.kt new file mode 100644 index 00000000000..a2462759ba3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/isErasedTAndStarred.kt @@ -0,0 +1,3 @@ +class G + +fun f(q: Q) = q is G<*> \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cast/isErasedUnrelatedAndStarred.kt b/compiler/testData/diagnostics/tests/cast/isErasedUnrelatedAndStarred.kt new file mode 100644 index 00000000000..4c93d96d241 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/isErasedUnrelatedAndStarred.kt @@ -0,0 +1,4 @@ +class G +trait Tr + +fun f(q: Tr) = q is G<*> \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index ede5e61efcc..1f644b477c0 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -1060,6 +1060,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowSameParameterParameter.kt"); } + @TestMetadata("isErasedAnyAndStarred.kt") + public void testIsErasedAnyAndStarred() throws Exception { + doTest("compiler/testData/diagnostics/tests/cast/isErasedAnyAndStarred.kt"); + } + @TestMetadata("IsErasedDisallowDifferentArgInvariantPosition.kt") public void testIsErasedDisallowDifferentArgInvariantPosition() throws Exception { doTest("compiler/testData/diagnostics/tests/cast/IsErasedDisallowDifferentArgInvariantPosition.kt"); @@ -1120,6 +1125,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/cast/IsErasedStar.kt"); } + @TestMetadata("isErasedTAndStarred.kt") + public void testIsErasedTAndStarred() throws Exception { + doTest("compiler/testData/diagnostics/tests/cast/isErasedTAndStarred.kt"); + } + @TestMetadata("IsErasedTasT.kt") public void testIsErasedTasT() throws Exception { doTest("compiler/testData/diagnostics/tests/cast/IsErasedTasT.kt"); @@ -1130,6 +1140,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/cast/IsErasedToErrorType.kt"); } + @TestMetadata("isErasedUnrelatedAndStarred.kt") + public void testIsErasedUnrelatedAndStarred() throws Exception { + doTest("compiler/testData/diagnostics/tests/cast/isErasedUnrelatedAndStarred.kt"); + } + @TestMetadata("IsRecursionSustainable.kt") public void testIsRecursionSustainable() throws Exception { doTest("compiler/testData/diagnostics/tests/cast/IsRecursionSustainable.kt");