From 9f90fd0938eca7cd10929547df7ce893cc73577b Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 16 Aug 2013 18:09:01 +0400 Subject: [PATCH] No "unreachable code" errors when an illegal return expression is the last in a lambda --- .../ControlStructureTypingVisitor.java | 6 +++++- .../return/ForbiddenNonLocalReturnNoType.kt | 18 ++++++++++++++++ .../checkers/JetDiagnosticsTestGenerated.java | 21 ++++++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/functionLiterals/return/ForbiddenNonLocalReturnNoType.kt 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 aa301fb7c97..1a80abbd776 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 @@ -482,6 +482,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { JetExpression returnedExpression = expression.getReturnedExpression(); JetType expectedType = TypeUtils.NO_EXPECTED_TYPE; + JetType resultType = KotlinBuiltIns.getInstance().getNothingType(); JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class); if (parentDeclaration instanceof JetParameter) { @@ -503,6 +504,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { } while (containingFunction instanceof JetFunctionLiteral); // Unqualified, in a function literal context.trace.report(RETURN_NOT_ALLOWED.on(expression)); + resultType = ErrorUtils.createErrorType("Return not allowed"); } if (containingFunctionDescriptor != null) { expectedType = DescriptorUtils.getFunctionExpectedReturnType(containingFunctionDescriptor, (JetElement) containingFunction); @@ -511,6 +513,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { else { // Outside a function context.trace.report(RETURN_NOT_ALLOWED.on(expression)); + resultType = ErrorUtils.createErrorType("Return not allowed"); } } else if (element != null) { @@ -520,6 +523,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { if (functionDescriptor != containingFunctionDescriptor) { // Qualified, non-local context.trace.report(RETURN_NOT_ALLOWED.on(expression)); + resultType = ErrorUtils.createErrorType("Return not allowed"); } } else { @@ -534,7 +538,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType)); } } - return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getNothingType(), expression, context, context.dataFlowInfo); + return DataFlowUtils.checkType(resultType, expression, context, context.dataFlowInfo); } @Override diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/ForbiddenNonLocalReturnNoType.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/ForbiddenNonLocalReturnNoType.kt new file mode 100644 index 00000000000..d5f4a205f66 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/ForbiddenNonLocalReturnNoType.kt @@ -0,0 +1,18 @@ +fun test() { + run {return} + run {} +} + +fun test2() { + run {return@test2} + run {} +} + +fun test3() { + fun test4() { + run {return@test3} + run {} + } +} + +fun run(f: () -> T): T { return f() } diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 4d2108677ba..5a84190e06e 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -2390,6 +2390,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage } @TestMetadata("compiler/testData/diagnostics/tests/functionLiterals") + @InnerTestClasses({FunctionLiterals.Return.class}) public static class FunctionLiterals extends AbstractDiagnosticsTestWithEagerResolve { public void testAllFilesPresentInFunctionLiterals() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/functionLiterals"), Pattern.compile("^(.+)\\.kt$"), true); @@ -2425,6 +2426,24 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/functionLiterals/unusedLiteral.kt"); } + @TestMetadata("compiler/testData/diagnostics/tests/functionLiterals/return") + public static class Return extends AbstractDiagnosticsTestWithEagerResolve { + public void testAllFilesPresentInReturn() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/functionLiterals/return"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("ForbiddenNonLocalReturnNoType.kt") + public void testForbiddenNonLocalReturnNoType() throws Exception { + doTest("compiler/testData/diagnostics/tests/functionLiterals/return/ForbiddenNonLocalReturnNoType.kt"); + } + } + + public static Test innerSuite() { + TestSuite suite = new TestSuite("FunctionLiterals"); + suite.addTestSuite(FunctionLiterals.class); + suite.addTestSuite(Return.class); + return suite; + } } @TestMetadata("compiler/testData/diagnostics/tests/generics") @@ -5204,7 +5223,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage suite.addTestSuite(Deparenthesize.class); suite.addTest(Enum.innerSuite()); suite.addTestSuite(Extensions.class); - suite.addTestSuite(FunctionLiterals.class); + suite.addTest(FunctionLiterals.innerSuite()); suite.addTestSuite(Generics.class); suite.addTest(IncompleteCode.innerSuite()); suite.addTest(Inference.innerSuite());