diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 2497943d994..090f9b2d006 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -596,7 +596,6 @@ public interface Errors { DiagnosticFactory0 EXPRESSION_EXPECTED_PACKAGE_FOUND = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 RETURN_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_WITH_BODY); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index e6755906dc5..59681d71b7f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -161,7 +161,6 @@ public class DefaultErrorMessages { MAP.put(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, "Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly"); // TODO: message MAP.put(RETURN_NOT_ALLOWED, "'return' is not allowed here"); - MAP.put(RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED, "'return' is only allowed in function literals that have return types specified explicitly"); MAP.put(PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE, "Projections are not allowed for immediate arguments of a supertype"); MAP.put(LABEL_NAME_CLASH, "There is more than one label with such a name in this scope"); MAP.put(EXPRESSION_EXPECTED_PACKAGE_FOUND, "Expression expected, but a package name found"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index 90baefe025f..e9c3c0fbacd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -84,6 +84,7 @@ public interface BindingContext { WritableSlice TYPE = Slices.createSimpleSlice(); WritableSlice EXPRESSION_TYPE = new BasicWritableSlice(DO_NOTHING); WritableSlice EXPECTED_EXPRESSION_TYPE = new BasicWritableSlice(DO_NOTHING); + WritableSlice EXPECTED_RETURN_TYPE = new BasicWritableSlice(DO_NOTHING); WritableSlice EXPRESSION_DATA_FLOW_INFO = new BasicWritableSlice(DO_NOTHING); WritableSlice EXPRESSION_RESULT_APPROXIMATION = new BasicWritableSlice(DO_NOTHING); WritableSlice DATAFLOW_INFO_AFTER_CONDITION = Slices.createSimpleSlice(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ClosureExpressionsTypingVisitor.java index 4aaf76e951b..6e5cc2a970e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ClosureExpressionsTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ClosureExpressionsTypingVisitor.java @@ -298,10 +298,11 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { } // Type-check the body - ExpressionTypingContext newContext = context.replaceScope(functionInnerScope) - .replaceExpectedType(declaredReturnType != null - ? declaredReturnType - : (expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE)); + JetType expectedType = declaredReturnType != null + ? declaredReturnType + : (expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE); + ExpressionTypingContext newContext = context.replaceScope(functionInnerScope).replaceExpectedType(expectedType); + context.trace.record(EXPECTED_RETURN_TYPE, functionLiteral, expectedType); JetType typeOfBodyExpression = components.expressionTypingServices.getBlockReturnedType(bodyExpression, COERCION_TO_UNIT, newContext).getType(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java index 3f9c4a101b6..4f2c1530131 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java @@ -465,7 +465,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE); } - expectedType = getFunctionExpectedReturnType(containingFunctionDescriptor, (JetElement) containingFunInfo.getSecond()); + expectedType = getFunctionExpectedReturnType(containingFunctionDescriptor, (JetElement) containingFunInfo.getSecond(), context); } else { // Outside a function @@ -476,17 +476,12 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { else if (labelTargetElement != null) { SimpleFunctionDescriptor functionDescriptor = context.trace.get(FUNCTION, labelTargetElement); if (functionDescriptor != null) { - expectedType = getFunctionExpectedReturnType(functionDescriptor, labelTargetElement); + expectedType = getFunctionExpectedReturnType(functionDescriptor, labelTargetElement, context); if (!InlineDescriptorUtils.checkNonLocalReturnUsage(functionDescriptor, expression, context.trace)) { // Qualified, non-local context.trace.report(RETURN_NOT_ALLOWED.on(expression)); resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE); } - else if (expectedType == NO_EXPECTED_TYPE) { - // expectedType is NO_EXPECTED_TYPE iff the return type of the corresponding function descriptor is not computed yet - // our temporary policy is to prohibit returns in this case. It mostly applies to local returns in lambdas - context.trace.report(RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED.on(expression)); - } } else { context.trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName())); @@ -517,15 +512,19 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { } @NotNull - private static JetType getFunctionExpectedReturnType(@NotNull FunctionDescriptor descriptor, @NotNull JetElement function) { + private static JetType getFunctionExpectedReturnType( + @NotNull FunctionDescriptor descriptor, + @NotNull JetElement function, + @NotNull ExpressionTypingContext context + ) { JetType expectedType; if (function instanceof JetFunction) { - if (((JetFunction) function).getTypeReference() != null || ((JetFunction) function).hasBlockBody()) { + JetFunction jetFunction = (JetFunction) function; + expectedType = context.trace.get(EXPECTED_RETURN_TYPE, jetFunction); + + if ((expectedType == null) && (jetFunction.getTypeReference() != null || jetFunction.hasBlockBody())) { expectedType = descriptor.getReturnType(); } - else { - expectedType = TypeUtils.NO_EXPECTED_TYPE; - } } else { expectedType = descriptor.getReturnType(); diff --git a/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt b/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt index 20aa86ef2cf..1ed4f0db02b 100644 --- a/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt +++ b/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt @@ -8,10 +8,10 @@ fun unitEmptyReturn() : Unit {return} fun unitIntReturn() : Unit {return 1} fun unitUnitReturn() : Unit {return Unit} fun test1() : Any = {return} -fun test2() : Any = @a {return@a 1} +fun test2() : Any = @a {return@a 1} fun test3() : Any { return } fun test4(): ()-> Unit = { return@test4 } -fun test5(): Any = @l{ return@l } +fun test5(): Any = @l{ return@l } fun test6(): Any = {return 1} fun bbb() { diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/IfInReturnedExpression.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/IfInReturnedExpression.kt new file mode 100644 index 00000000000..84ad92f265a --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/IfInReturnedExpression.kt @@ -0,0 +1,5 @@ +val flag = true + +val a/*: () -> Comparable*/ = @l { + return@l if (flag) "OK" else 4 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/IfInReturnedExpression.txt b/compiler/testData/diagnostics/tests/functionLiterals/return/IfInReturnedExpression.txt new file mode 100644 index 00000000000..80f607f4515 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/IfInReturnedExpression.txt @@ -0,0 +1,4 @@ +package + +internal val a: () -> kotlin.Comparable +internal val flag: kotlin.Boolean = true diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElse.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElse.kt new file mode 100644 index 00000000000..fbc2e169744 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElse.kt @@ -0,0 +1,15 @@ +val flag = true + +// type of a was checked by txt +val a/*: () -> Any*/ = @l { // commonSupertype(Int, Unit) = Any + if (flag) return@l 4 +} + +val b/*: () -> Int */ = @l { + if (flag) return@l 4 + 5 +} + +val c/*: () -> Unit */ = @l { + if (flag) 4 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElse.txt b/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElse.txt new file mode 100644 index 00000000000..bff23ac83bc --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElse.txt @@ -0,0 +1,6 @@ +package + +internal val a: () -> kotlin.Any +internal val b: () -> kotlin.Int +internal val c: () -> kotlin.Unit +internal val flag: kotlin.Boolean = true diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElseWithExplicitType.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElseWithExplicitType.kt new file mode 100644 index 00000000000..944f04552c7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElseWithExplicitType.kt @@ -0,0 +1,22 @@ +val flag = true + +val a: () -> Int = @l { + if (flag) return@l 4 +} + +val b: () -> Unit = @l { + if (flag) return@l 4 +} + +val c: () -> Any = @l { + if (flag) return@l 4 +} + +val d: () -> Int = @l { + if (flag) return@l 4 + 5 +} + +val e: () -> Int = @l { + if (flag) 4 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElseWithExplicitType.txt b/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElseWithExplicitType.txt new file mode 100644 index 00000000000..9d69ae0afc9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElseWithExplicitType.txt @@ -0,0 +1,8 @@ +package + +internal val a: () -> kotlin.Int +internal val b: () -> kotlin.Unit +internal val c: () -> kotlin.Any +internal val d: () -> kotlin.Int +internal val e: () -> kotlin.Int +internal val flag: kotlin.Boolean = true diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LambdaWithParameter.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/LambdaWithParameter.kt new file mode 100644 index 00000000000..58f7fb03550 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LambdaWithParameter.kt @@ -0,0 +1,17 @@ +val flag = true + +val a /*: (Int) -> String */ = @l { + (i: Int) -> + if (i == 0) return@l i.toString() + + "Ok" +} + +fun foo(f: (Int) -> T): T = f(0) + +val b /*:String */ = foo { + (i) -> + if (i == 0) return@foo i.toString() + + "Ok" +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LambdaWithParameter.txt b/compiler/testData/diagnostics/tests/functionLiterals/return/LambdaWithParameter.txt new file mode 100644 index 00000000000..1a32c0ffc4d --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LambdaWithParameter.txt @@ -0,0 +1,6 @@ +package + +internal val a: (kotlin.Int) -> kotlin.String +internal val b: kotlin.String +internal val flag: kotlin.Boolean = true +internal fun foo(/*0*/ f: (kotlin.Int) -> T): T diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalAndNonLocalReturnInLambda.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalAndNonLocalReturnInLambda.kt index e1983714617..9a25c953d5b 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalAndNonLocalReturnInLambda.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalAndNonLocalReturnInLambda.kt @@ -1,7 +1,7 @@ fun test2(a: Int) { val x = run @f{ if (a > 0) return - return@f 1 + return@f 1 } x: Int } diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnExplicitLabelNoParens.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnExplicitLabelNoParens.kt index f771704f813..b004edf6a89 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnExplicitLabelNoParens.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnExplicitLabelNoParens.kt @@ -1,5 +1,5 @@ fun test2() { - val x = run @f{return@f 1} + val x = run @f{return@f 1} x: Int } diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnExplicitLabelParens.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnExplicitLabelParens.kt index d9396372fc8..cb4443cbf70 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnExplicitLabelParens.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnExplicitLabelParens.kt @@ -1,11 +1,11 @@ fun test() { - val x = run(@f{return@f 1}) + val x = run(@f{return@f 1}) x: Int } fun test1() { - val x = run(@l{return@l 1}) + val x = run(@l{return@l 1}) x: Int } diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnInNestedFunction.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnInNestedFunction.kt index 7f262734dc9..d9add5d633f 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnInNestedFunction.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnInNestedFunction.kt @@ -4,7 +4,7 @@ fun test() { if (a > 0) return "2" return@local "3" } - return@f 1 + return@f 1 } x: Int } diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnInNestedLambda.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnInNestedLambda.kt index ae5a9010b5c..1a7bc1c4507 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnInNestedLambda.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnInNestedLambda.kt @@ -1,9 +1,9 @@ fun test() { val x = run @f{ run @ff { - return@ff "2" + return@ff "2" } - return@f 1 + return@f 1 } x: Int } diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnNoCoercionToUnit.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnNoCoercionToUnit.kt index 510f53196f6..8d2c916db69 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnNoCoercionToUnit.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnNoCoercionToUnit.kt @@ -1,7 +1,7 @@ fun test(a: Int) { run @f{ - if (a > 0) return@f - else return@f 1 + if (a > 0) return@f + else return@f 1 } } diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnNull.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnNull.kt new file mode 100644 index 00000000000..158e5ca0f84 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnNull.kt @@ -0,0 +1,14 @@ +class A +val flag = true + +val a /*: () -> A?*/ = @l { + if (flag) return@l null + + A() +} + +val b /*: () -> A?*/ = @l { + if (flag) return@l null + + return@l A() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnNull.txt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnNull.txt new file mode 100644 index 00000000000..a7b03fddf43 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnNull.txt @@ -0,0 +1,12 @@ +package + +internal val a: () -> A? +internal val b: () -> A? +internal val flag: kotlin.Boolean = true + +internal final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnUnit.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnUnit.kt index fc34f6e0c87..6b1b30c2162 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnUnit.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnUnit.kt @@ -1,9 +1,9 @@ fun test(a: Int) { val x = run @f{ - if (a > 0) return@f - else return@f Unit + if (a > 0) return@f + else return@f Unit } x: Unit } -fun run(f: () -> T): T { return f() } +fun run(f: () -> T): T { return f() } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnWithExpectedType.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnWithExpectedType.kt new file mode 100644 index 00000000000..b07d93ba53c --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnWithExpectedType.kt @@ -0,0 +1,9 @@ +fun listOf(): List = null!! +fun listOf(vararg values: T): List = null!! + +val flag = true + +val a: () -> List = @l { + if (flag) return@l listOf() + listOf(5) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnWithExpectedType.txt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnWithExpectedType.txt new file mode 100644 index 00000000000..1c5e5518e5a --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnWithExpectedType.txt @@ -0,0 +1,6 @@ +package + +internal val a: () -> kotlin.List +internal val flag: kotlin.Boolean = true +internal fun listOf(): kotlin.List +internal fun listOf(/*0*/ vararg values: T /*kotlin.Array*/): kotlin.List diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/MixedReturnsFromLambda.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/MixedReturnsFromLambda.kt index 1cc33e72fb3..ad729ecf83d 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/return/MixedReturnsFromLambda.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/MixedReturnsFromLambda.kt @@ -5,7 +5,7 @@ trait C: A fun test(a: C, b: B) { val x = run @f{ - if (a != b) return@f a + if (a != b) return@f a b } x: A diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/NoCommonSystem.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/NoCommonSystem.kt new file mode 100644 index 00000000000..f211330eef1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/NoCommonSystem.kt @@ -0,0 +1,18 @@ +fun Iterable.map(transform: (T) -> R): List = null!! +fun listOf(): List = null!! +fun listOf(vararg values: T): List = null!! + +fun commonSystemFailed(a: List) { + a.map { + if (it == 0) return@map listOf(it) + listOf() + } + a.map { + if (it == 0) return@map listOf() + listOf(it) + } + a.map { + if (it == 0) listOf() + else listOf(it) + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/NoCommonSystem.txt b/compiler/testData/diagnostics/tests/functionLiterals/return/NoCommonSystem.txt new file mode 100644 index 00000000000..1b1d426d4bd --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/NoCommonSystem.txt @@ -0,0 +1,6 @@ +package + +internal fun commonSystemFailed(/*0*/ a: kotlin.List): kotlin.Unit +internal fun listOf(): kotlin.List +internal fun listOf(/*0*/ vararg values: T /*kotlin.Array*/): kotlin.List +internal fun kotlin.Iterable.map(/*0*/ transform: (T) -> R): kotlin.List diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCast.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCast.kt new file mode 100644 index 00000000000..a3a1dc7ea66 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCast.kt @@ -0,0 +1,17 @@ +// KT-6822 Smart cast doesn't work inside local returned expression in lambda + +val a /* :(Int?) -> Int? */ = @l { (it: Int?) -> // but must be (Int?) -> Int + if (it != null) return@l it + 5 +} + +fun let(f: (Int?) -> R): R = null!! + +val b /*: Int? */ = let { // but must be Int + if (it != null) return@let it + 5 +} + +val c /*: Int*/ = let { + if (it != null) it else 5 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCast.txt b/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCast.txt new file mode 100644 index 00000000000..e6e69673aee --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCast.txt @@ -0,0 +1,6 @@ +package + +internal val a: (kotlin.Int?) -> kotlin.Int? +internal val b: kotlin.Int? +internal val c: kotlin.Int +internal fun let(/*0*/ f: (kotlin.Int?) -> R): R diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCastWithExplicitType.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCastWithExplicitType.kt new file mode 100644 index 00000000000..549ae9ff68d --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCastWithExplicitType.kt @@ -0,0 +1,17 @@ +// KT-6822 Smart cast doesn't work inside local returned expression in lambda + +val a : (Int?) -> Int = @l { + if (it != null) return@l it + 5 +} + +fun let(f: (Int?) -> R): R = null!! + +val b: Int = let { + if (it != null) return@let it + 5 +} + +val c: Int = let { + if (it != null) it else 5 +} diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCastWithExplicitType.txt b/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCastWithExplicitType.txt new file mode 100644 index 00000000000..ea6aa9a7839 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/SmartCastWithExplicitType.txt @@ -0,0 +1,6 @@ +package + +internal val a: (kotlin.Int?) -> kotlin.Int +internal val b: kotlin.Int +internal val c: kotlin.Int +internal fun let(/*0*/ f: (kotlin.Int?) -> R): R diff --git a/compiler/testData/diagnostics/tests/functionLiterals/returnNullWithReturn.kt b/compiler/testData/diagnostics/tests/functionLiterals/returnNullWithReturn.kt new file mode 100644 index 00000000000..c96d91ec709 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/returnNullWithReturn.kt @@ -0,0 +1,10 @@ +package m + +trait Element + +fun test(handlers: MapUnit>) { + + handlers.getOrElse("name", @l { return@l null }) +} + +fun Map.getOrElse(key: K, defaultValue: ()-> V) : V = throw Exception("$key $defaultValue") \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionLiterals/returnNullWithReturn.txt b/compiler/testData/diagnostics/tests/functionLiterals/returnNullWithReturn.txt new file mode 100644 index 00000000000..8c2db7bb5db --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/returnNullWithReturn.txt @@ -0,0 +1,12 @@ +package + +package m { + internal fun test(/*0*/ handlers: kotlin.Map kotlin.Unit>): kotlin.Unit + internal fun kotlin.Map.getOrElse(/*0*/ key: K, /*1*/ defaultValue: () -> V): V + + internal trait Element { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/testData/diagnostics/tests/inference/inferInFunctionLiteralsWithReturn.kt b/compiler/testData/diagnostics/tests/inference/inferInFunctionLiteralsWithReturn.kt new file mode 100644 index 00000000000..28ce4a098af --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/inferInFunctionLiteralsWithReturn.kt @@ -0,0 +1,12 @@ +package n + +//+JDK +import java.util.* + +fun expected(t: T, f: () -> T) : T = t + +fun test(arrayList: ArrayList, list: List) { + val t = expected(arrayList, @l {return@l list.reverse() }) +} + +fun List.reverse() : List = this \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/inferInFunctionLiteralsWithReturn.txt b/compiler/testData/diagnostics/tests/inference/inferInFunctionLiteralsWithReturn.txt new file mode 100644 index 00000000000..4ca53fc323d --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/inferInFunctionLiteralsWithReturn.txt @@ -0,0 +1,7 @@ +package + +package n { + internal fun expected(/*0*/ t: T, /*1*/ f: () -> T): T + internal fun test(/*0*/ arrayList: java.util.ArrayList, /*1*/ list: kotlin.List): kotlin.Unit + internal fun kotlin.List.reverse(): kotlin.List +} diff --git a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/explicitReturnType.kt b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/explicitReturnType.kt index e61c5913247..6bc79671c9b 100644 --- a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/explicitReturnType.kt +++ b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/explicitReturnType.kt @@ -1,7 +1,7 @@ fun inlineCallExplicitError(): String { inlineFun @lamba { if (true) { - return@lamba 2 + return@lamba 2 } 1 } diff --git a/compiler/testData/diagnostics/tests/labels/kt1703.kt b/compiler/testData/diagnostics/tests/labels/kt1703.kt index f83a595356d..bdaf03bb6fd 100644 --- a/compiler/testData/diagnostics/tests/labels/kt1703.kt +++ b/compiler/testData/diagnostics/tests/labels/kt1703.kt @@ -6,7 +6,7 @@ public inline fun Array(n: Int, block: (Int) -> T): Array = null! fun test() { val ints = Array(2, { null }) ints.forEach @lit { - if (it == null) return @lit + if (it == null) return @lit use(it + 5) } } diff --git a/compiler/testData/diagnostics/tests/regressions/kt411.kt b/compiler/testData/diagnostics/tests/regressions/kt411.kt index 2f5c43386f5..268e2d7cd42 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt411.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt411.kt @@ -5,7 +5,7 @@ package kt411 fun f() { invoker( @l{ - return@l 11 // expects Function, but should expect Int + return@l 11 // expects Function, but should expect Int } ) } @@ -21,7 +21,7 @@ fun t1() { fun t2() : String { val g : ()-> Int = @l{ if (true) { - return@l 1 + return@l 1 } return "s" } @@ -37,7 +37,7 @@ fun t3() : String { else { return 2 } - return@l 0 + return@l 0 } ) invoker( @@ -55,7 +55,7 @@ fun t3() : String { fun t4() : Int { val h : ()-> String = @l{ - return@l "a" + return@l "a" } val g : ()-> String = @l{ () : String -> return@l "a" diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 45930f32787..17884fd2185 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -4581,6 +4581,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("returnNullWithReturn.kt") + public void testReturnNullWithReturn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/returnNullWithReturn.kt"); + doTest(fileName); + } + @TestMetadata("unusedLiteral.kt") public void testUnusedLiteral() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/unusedLiteral.kt"); @@ -4619,6 +4625,30 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("IfInReturnedExpression.kt") + public void testIfInReturnedExpression() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/IfInReturnedExpression.kt"); + doTest(fileName); + } + + @TestMetadata("IfWithoutElse.kt") + public void testIfWithoutElse() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElse.kt"); + doTest(fileName); + } + + @TestMetadata("IfWithoutElseWithExplicitType.kt") + public void testIfWithoutElseWithExplicitType() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/IfWithoutElseWithExplicitType.kt"); + doTest(fileName); + } + + @TestMetadata("LambdaWithParameter.kt") + public void testLambdaWithParameter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/LambdaWithParameter.kt"); + doTest(fileName); + } + @TestMetadata("LocalAndNonLocalReturnInLambda.kt") public void testLocalAndNonLocalReturnInLambda() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/LocalAndNonLocalReturnInLambda.kt"); @@ -4661,12 +4691,24 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("LocalReturnNull.kt") + public void testLocalReturnNull() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnNull.kt"); + doTest(fileName); + } + @TestMetadata("LocalReturnUnit.kt") public void testLocalReturnUnit() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnUnit.kt"); doTest(fileName); } + @TestMetadata("LocalReturnWithExpectedType.kt") + public void testLocalReturnWithExpectedType() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnWithExpectedType.kt"); + doTest(fileName); + } + @TestMetadata("LocalReturnsWithExplicitReturnType.kt") public void testLocalReturnsWithExplicitReturnType() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnsWithExplicitReturnType.kt"); @@ -4678,6 +4720,24 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/MixedReturnsFromLambda.kt"); doTest(fileName); } + + @TestMetadata("NoCommonSystem.kt") + public void testNoCommonSystem() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/NoCommonSystem.kt"); + doTest(fileName); + } + + @TestMetadata("SmartCast.kt") + public void testSmartCast() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/SmartCast.kt"); + doTest(fileName); + } + + @TestMetadata("SmartCastWithExplicitType.kt") + public void testSmartCastWithExplicitType() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/return/SmartCastWithExplicitType.kt"); + doTest(fileName); + } } } @@ -5405,6 +5465,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("inferInFunctionLiteralsWithReturn.kt") + public void testInferInFunctionLiteralsWithReturn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/inferInFunctionLiteralsWithReturn.kt"); + doTest(fileName); + } + @TestMetadata("kt1293.kt") public void testKt1293() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/kt1293.kt"); diff --git a/idea/testData/checker/FunctionReturnTypes.kt b/idea/testData/checker/FunctionReturnTypes.kt index a22d9559e38..3d1e868e272 100644 --- a/idea/testData/checker/FunctionReturnTypes.kt +++ b/idea/testData/checker/FunctionReturnTypes.kt @@ -6,7 +6,7 @@ fun unitEmptyReturn() : Unit {return} fun unitIntReturn() : Unit {return 1} fun unitUnitReturn() : Unit {return Unit} fun test1() : Any = { return } -fun test2() : Any = @a {return@a 1} +fun test2() : Any = @a {return@a 1} fun test3() : Any { return } fun bbb() {