diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index fb1cf78bcd1..cf920c2d04e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -91,6 +91,7 @@ public interface Errors { SimpleDiagnosticFactory REDUNDANT_NULLABLE = SimpleDiagnosticFactory.create(WARNING, NULLABLE_TYPE); DiagnosticFactory1 BASE_WITH_NULLABLE_UPPER_BOUND = DiagnosticFactory1.create(WARNING, NULLABLE_TYPE); DiagnosticFactory1 WRONG_NUMBER_OF_TYPE_ARGUMENTS = DiagnosticFactory1.create(ERROR); + DiagnosticFactory2 NO_TYPE_ARGUMENTS_ON_RHS_OF_IS_EXPRESSION = DiagnosticFactory2.create(ERROR); DiagnosticFactory1 CONFLICTING_PROJECTION = DiagnosticFactory1.create(ERROR, VARIANCE_IN_PROJECTION); DiagnosticFactory1 REDUNDANT_PROJECTION = DiagnosticFactory1.create(WARNING, VARIANCE_IN_PROJECTION); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java index e15efb95187..38200c88395 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java @@ -419,6 +419,8 @@ public class DefaultErrorMessages { MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, "Type inference failed. Expected type mismatch: found: {0} required: {1}", RENDER_TYPE, RENDER_TYPE); MAP.put(WRONG_NUMBER_OF_TYPE_ARGUMENTS, "{0,choice,0#No type arguments|1#Type argument|1<{0,number,integer} type argument} expected", null); + MAP.put(NO_TYPE_ARGUMENTS_ON_RHS_OF_IS_EXPRESSION, "{0,choice,0#No type arguments|1#Type argument|1<{0,number,integer} type argument} expected. " + + "Use ''{1}'' if you don''t want to pass type parameters", null, TO_STRING); MAP.put(DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED, "This expression is treated as an argument to the function call on the previous line. " + diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index cb73f670b83..61a997290a2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.lang.resolve; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.ModuleConfiguration; @@ -142,7 +143,12 @@ public class TypeResolver { else { if (actualArgumentCount != expectedArgumentCount) { if (actualArgumentCount == 0) { - trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type, expectedArgumentCount)); + if (rhsOfIsExpression(type)) { + trace.report(NO_TYPE_ARGUMENTS_ON_RHS_OF_IS_EXPRESSION.on(type, expectedArgumentCount, allStarProjectionsString(typeConstructor))); + } + else { + trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type, expectedArgumentCount)); + } } else { trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type.getTypeArgumentList(), expectedArgumentCount)); @@ -233,6 +239,19 @@ public class TypeResolver { return result[0]; } + private static boolean rhsOfIsExpression(@NotNull JetUserType type) { + // Look for the FIRST expression containing this type + JetExpression outerExpression = PsiTreeUtil.getParentOfType(type, JetExpression.class); + if (outerExpression instanceof JetIsExpression) { + JetIsExpression isExpression = (JetIsExpression) outerExpression; + // If this expression is JetIsExpression, and the type is the outermost on the RHS + if (type.getParent() == isExpression.getTypeRef()) { + return true; + } + } + return false; + } + private JetScope getScopeForTypeParameter(final TypeParameterDescriptor typeParameterDescriptor, boolean checkBounds) { if (checkBounds) { return typeParameterDescriptor.getUpperBoundsAsType().getMemberScope(); @@ -317,4 +336,15 @@ public class TypeResolver { } return null; } + + @NotNull + private static String allStarProjectionsString(@NotNull TypeConstructor constructor) { + int size = constructor.getParameters().size(); + assert size != 0 : "No projections possible for a nilary type constructor" + constructor; + ClassifierDescriptor declarationDescriptor = constructor.getDeclarationDescriptor(); + assert declarationDescriptor != null : "No declaration descriptor for type constructor " + constructor; + String name = declarationDescriptor.getName().getName(); + + return TypeUtils.getTypeNameAndStarProjectionsString(name, size); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java index ed37f91f74b..9bfe8555f3c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -497,4 +497,18 @@ public class TypeUtils { } return false; } + + @NotNull + public static String getTypeNameAndStarProjectionsString(@NotNull String name, int size) { + StringBuilder builder = new StringBuilder(name); + builder.append("<"); + for (int i = 0; i < size; i++) { + builder.append("*"); + if (i == size - 1) break; + builder.append(", "); + } + builder.append(">"); + + return builder.toString(); + } } diff --git a/compiler/testData/diagnostics/tests/generics/RawTypeInIsExpression.kt b/compiler/testData/diagnostics/tests/generics/RawTypeInIsExpression.kt new file mode 100644 index 00000000000..49e5c7e3d88 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/RawTypeInIsExpression.kt @@ -0,0 +1,16 @@ +package p + +public fun foo(a: Any) { + a is Map + a is Map + a is Map + a is Map<*, *> + a is Map<> + a is List<Map> + a is List + a is Int + + (a as Map) is Int +} + + diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 6308fd7d7e1..ba5c319680f 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -15,13 +15,16 @@ */ package org.jetbrains.jet.checkers; +import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestSuite; + +import java.io.File; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.test.InnerTestClasses; import org.jetbrains.jet.test.TestMetadata; -import java.io.File; +import org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve; /** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ @InnerTestClasses({JetDiagnosticsTestGenerated.Tests.class, JetDiagnosticsTestGenerated.Script.class}) @@ -1766,6 +1769,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/generics/Projections.kt"); } + @TestMetadata("RawTypeInIsExpression.kt") + public void testRawTypeInIsExpression() throws Exception { + doTest("compiler/testData/diagnostics/tests/generics/RawTypeInIsExpression.kt"); + } + @TestMetadata("RecursiveUpperBoundCheck.kt") public void testRecursiveUpperBoundCheck() throws Exception { doTest("compiler/testData/diagnostics/tests/generics/RecursiveUpperBoundCheck.kt"); diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java index b63f301a9ad..888e087d8e8 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -15,13 +15,16 @@ */ package org.jetbrains.jet.lang.resolve.lazy; +import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestSuite; + +import java.io.File; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.test.InnerTestClasses; import org.jetbrains.jet.test.TestMetadata; -import java.io.File; +import org.jetbrains.jet.lang.resolve.lazy.AbstractLazyResolveNamespaceComparingTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ @InnerTestClasses({LazyResolveNamespaceComparingTestGenerated.LoadKotlin.class, LazyResolveNamespaceComparingTestGenerated.LoadJava.class, LazyResolveNamespaceComparingTestGenerated.NamespaceComparator.class})