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 5a19ea35035..8272ea262e2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -210,11 +210,15 @@ public interface Errors { DiagnosticFactory1 NO_CLASS_OBJECT = DiagnosticFactory1.create(ERROR); SimpleDiagnosticFactory NO_GENERICS_IN_SUPERTYPE_SPECIFIER = SimpleDiagnosticFactory.create(ERROR); - SimpleDiagnosticFactory HAS_NEXT_MISSING = SimpleDiagnosticFactory.create(ERROR); - SimpleDiagnosticFactory HAS_NEXT_FUNCTION_AMBIGUITY = SimpleDiagnosticFactory.create(ERROR); + DiagnosticFactory1 HAS_NEXT_MISSING = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 HAS_NEXT_FUNCTION_AMBIGUITY = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 HAS_NEXT_FUNCTION_NONE_APPLICABLE = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 HAS_NEXT_FUNCTION_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR); - SimpleDiagnosticFactory NEXT_AMBIGUITY = SimpleDiagnosticFactory.create(ERROR); - SimpleDiagnosticFactory NEXT_MISSING = SimpleDiagnosticFactory.create(ERROR); + + DiagnosticFactory1 NEXT_AMBIGUITY = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 NEXT_MISSING = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 NEXT_NONE_APPLICABLE = DiagnosticFactory1.create(ERROR); + SimpleDiagnosticFactory ITERATOR_MISSING = SimpleDiagnosticFactory.create(ERROR); AmbiguousDescriptorDiagnosticFactory ITERATOR_AMBIGUITY = AmbiguousDescriptorDiagnosticFactory.create(); 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 bdc850084f8..e198eb19fc0 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 @@ -226,12 +226,16 @@ public class DefaultErrorMessages { MAP.put(NO_CLASS_OBJECT, "Please specify constructor invocation; classifier ''{0}'' does not have a class object", NAME); MAP.put(NO_GENERICS_IN_SUPERTYPE_SPECIFIER, "Generic arguments of the base type must be specified"); - MAP.put(HAS_NEXT_MISSING, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property"); - MAP.put(HAS_NEXT_FUNCTION_AMBIGUITY, "Function 'iterator().hasNext()' is ambiguous for this expression"); + MAP.put(HAS_NEXT_MISSING, "hasNext() cannot be called on iterator() of type ''{0}''", RENDER_TYPE); + MAP.put(HAS_NEXT_FUNCTION_AMBIGUITY, "hasNext() is ambiguous for iterator() of type ''{0}''", RENDER_TYPE); + MAP.put(HAS_NEXT_FUNCTION_NONE_APPLICABLE, "None of the hasNext() functions is applicable for iterator() of type ''{0}''", RENDER_TYPE); MAP.put(HAS_NEXT_FUNCTION_TYPE_MISMATCH, "The ''iterator().hasNext()'' function of the loop range must return jet.Boolean, but returns {0}", RENDER_TYPE); - MAP.put(NEXT_AMBIGUITY, "Function 'iterator().next()' is ambiguous for this expression"); - MAP.put(NEXT_MISSING, "Loop range must have an 'iterator().next()' function"); + + MAP.put(NEXT_MISSING, "next() cannot be called on iterator() of type ''{0}''", RENDER_TYPE); + MAP.put(NEXT_AMBIGUITY, "next() is ambiguous for iterator() of type ''{0}''", RENDER_TYPE); + MAP.put(NEXT_NONE_APPLICABLE, "None of the next() functions is applicable for iterator() of type ''{0}''", RENDER_TYPE); + MAP.put(ITERATOR_MISSING, "For-loop range must have an iterator() method"); MAP.put(ITERATOR_AMBIGUITY, "Method ''iterator()'' is ambiguous for this expression: {0}", AMBIGUOUS_CALLS); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index ce6428f7ee3..a6ff90c604d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -25,8 +25,8 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory1; import org.jetbrains.jet.lang.diagnostics.Errors; -import org.jetbrains.jet.lang.diagnostics.SimpleDiagnosticFactory; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; @@ -340,12 +340,13 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { FunctionDescriptor iteratorFunction = iteratorResolvedCall.getResultingDescriptor(); JetType iteratorType = iteratorFunction.getReturnType(); JetType hasNextType = checkConventionForIterator(context, loopRangeExpression, iteratorType, "hasNext", - HAS_NEXT_FUNCTION_AMBIGUITY, HAS_NEXT_MISSING, + HAS_NEXT_FUNCTION_AMBIGUITY, HAS_NEXT_MISSING, HAS_NEXT_FUNCTION_NONE_APPLICABLE, LOOP_RANGE_HAS_NEXT_RESOLVED_CALL); if (hasNextType != null && !isBoolean(hasNextType)) { context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRangeExpression, hasNextType)); } - return checkConventionForIterator(context, loopRangeExpression, iteratorType, "next", NEXT_AMBIGUITY, NEXT_MISSING, + return checkConventionForIterator(context, loopRangeExpression, iteratorType, "next", + NEXT_AMBIGUITY, NEXT_MISSING, NEXT_NONE_APPLICABLE, LOOP_RANGE_NEXT_RESOLVED_CALL); } else { @@ -370,19 +371,24 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { @NotNull JetExpression loopRangeExpression, @NotNull JetType iteratorType, @NotNull String name, - @NotNull SimpleDiagnosticFactory ambiguity, - @NotNull SimpleDiagnosticFactory missing, + @NotNull DiagnosticFactory1 ambiguity, + @NotNull DiagnosticFactory1 missing, + @NotNull DiagnosticFactory1 noneApplicable, @NotNull WritableSlice> resolvedCallKey ) { OverloadResolutionResults nextResolutionResults = resolveFakeCall( new TransientReceiver(iteratorType), context, Name.identifier(name)); if (nextResolutionResults.isAmbiguity()) { - context.trace.report(ambiguity.on(loopRangeExpression)); + context.trace.report(ambiguity.on(loopRangeExpression, iteratorType)); } else if (nextResolutionResults.isNothing()) { - context.trace.report(missing.on(loopRangeExpression)); + context.trace.report(missing.on(loopRangeExpression, iteratorType)); + } + else if (!nextResolutionResults.isSuccess()) { + context.trace.report(noneApplicable.on(loopRangeExpression, iteratorType)); } else { + assert nextResolutionResults.isSuccess(); ResolvedCall resolvedCall = nextResolutionResults.getResultingCall(); context.trace.record(resolvedCallKey, loopRangeExpression, resolvedCall); return resolvedCall.getResultingDescriptor().getReturnType(); diff --git a/compiler/testData/codegen/controlStructures/forUserType.jet b/compiler/testData/codegen/controlStructures/forUserType.jet index 6e0638d9d99..4284211a9e4 100644 --- a/compiler/testData/codegen/controlStructures/forUserType.jet +++ b/compiler/testData/codegen/controlStructures/forUserType.jet @@ -66,14 +66,6 @@ fun box() : String { System.out?.println(sum) if(sum != 10) return "b failed" - val c7 = MyCollection5() - sum = 0 - for (el in c7) { - sum = sum + el!! - } - if(sum != 0) return "c7 failed" - - return "OK" } @@ -120,14 +112,3 @@ class MyCollection4() { fun hasNext() = k > 0 } } - -class MyCollection5() { - fun iterator() : MyIterator? = null - - class MyIterator() { - var k : Int = 5 - - fun next() : Int = k-- - fun hasNext() = k > 0 - } -} diff --git a/compiler/testData/diagnostics/tests/controlStructures/forWithNullableIterator.kt b/compiler/testData/diagnostics/tests/controlStructures/forWithNullableIterator.kt new file mode 100644 index 00000000000..f5f46c8baf3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlStructures/forWithNullableIterator.kt @@ -0,0 +1,12 @@ +class Coll { + fun iterator(): It? = null +} + +class It { + fun next() = 1 + fun hasNext() = false +} + +fun test() { + for (x in Coll()) {} +} \ 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 ae878e22f1b..fd97ecf5065 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -15,15 +15,12 @@ */ 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.TestMetadata; -import org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve; +import java.io.File; /** This class is generated by {@link org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve}. DO NOT MODIFY MANUALLY */ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEagerResolve { @@ -879,6 +876,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/controlStructures/forLoopWithNullableRange.kt"); } + @TestMetadata("forWithNullableIterator.kt") + public void testForWithNullableIterator() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlStructures/forWithNullableIterator.kt"); + } + @TestMetadata("ForWithoutBraces.kt") public void testForWithoutBraces() throws Exception { doTest("compiler/testData/diagnostics/tests/controlStructures/ForWithoutBraces.kt"); diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java index bde0cace45d..b0829a009b4 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -312,7 +312,7 @@ public class ClassGenTest extends CodegenTestCase { } public void testKt903() throws Exception { - createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS); blackBoxFile("regressions/kt903.jet"); } @@ -403,7 +403,7 @@ public class ClassGenTest extends CodegenTestCase { } public void testKt1980() { - createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS); blackBoxFile("regressions/kt1980.kt"); } diff --git a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java index 81f86edd0e7..5e71dbbe369 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java @@ -108,7 +108,7 @@ public class ControlStructuresTest extends CodegenTestCase { } public void testFor() throws Exception { - createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS); loadFile(); // System.out.println(generateToText()); final Method main = generateFunction(); @@ -117,7 +117,7 @@ public class ControlStructuresTest extends CodegenTestCase { } public void testIfBlock() throws Exception { - createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS); loadFile(); // System.out.println(generateToText()); final Method main = generateFunction(); diff --git a/compiler/tests/org/jetbrains/jet/codegen/SafeRefTest.java b/compiler/tests/org/jetbrains/jet/codegen/SafeRefTest.java index 077cf470f0e..0d05d8bf10a 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/SafeRefTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/SafeRefTest.java @@ -22,7 +22,7 @@ public class SafeRefTest extends CodegenTestCase { @Override protected void setUp() throws Exception { super.setUp(); - createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS); } public void test247 () throws Exception { diff --git a/idea/tests/org/jetbrains/jet/plugin/codeInsight/LiveTemplatesTest.java b/idea/tests/org/jetbrains/jet/plugin/codeInsight/LiveTemplatesTest.java index a543ef091c7..14c8e6469f3 100644 --- a/idea/tests/org/jetbrains/jet/plugin/codeInsight/LiveTemplatesTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/codeInsight/LiveTemplatesTest.java @@ -165,7 +165,7 @@ public class LiveTemplatesTest extends LightCodeInsightFixtureTestCase { public void testIter() { start(); - assertStringItems("args", "collection", "myList", "str", "stream"); + assertStringItems("args", "myList", "str", "stream"); type("args"); nextTab(2); diff --git a/libraries/stdlib/src/kotlin/test/TestJVM.kt b/libraries/stdlib/src/kotlin/test/TestJVM.kt index b960c8ba865..23c99e83077 100644 --- a/libraries/stdlib/src/kotlin/test/TestJVM.kt +++ b/libraries/stdlib/src/kotlin/test/TestJVM.kt @@ -17,7 +17,7 @@ public var asserter: Asserter if (_asserter == null) { val klass = javaClass() val loader = ServiceLoader.load(klass)!! - for (a in loader) { + for (a in loader.iterator()!!) { if (a != null) { _asserter = a break