No need to produce error types when RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED is reported

This commit is contained in:
Andrey Breslav
2013-08-21 20:06:06 +04:00
parent 3f3ee378f3
commit a51ea10f55
8 changed files with 27 additions and 21 deletions
@@ -522,18 +522,16 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
SimpleFunctionDescriptor functionDescriptor = context.trace.get(FUNCTION, labelTargetElement); SimpleFunctionDescriptor functionDescriptor = context.trace.get(FUNCTION, labelTargetElement);
if (functionDescriptor != null) { if (functionDescriptor != null) {
expectedType = DescriptorUtils.getFunctionExpectedReturnType(functionDescriptor, labelTargetElement); expectedType = DescriptorUtils.getFunctionExpectedReturnType(functionDescriptor, labelTargetElement);
boolean inLambdaWithNoExplicitType = expectedType == TypeUtils.NO_EXPECTED_TYPE; if (functionDescriptor != containingFunctionDescriptor) {
if (inLambdaWithNoExplicitType) {
// 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));
resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
}
else if (functionDescriptor != containingFunctionDescriptor) {
// Qualified, non-local // Qualified, non-local
context.trace.report(RETURN_NOT_ALLOWED.on(expression)); context.trace.report(RETURN_NOT_ALLOWED.on(expression));
resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE); resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
} }
else if (expectedType == TypeUtils.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 { else {
context.trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName())); context.trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName()));
@@ -1,8 +1,9 @@
fun test2(a: Int) { fun test2(a: Int) {
(run @f{ val x = run @f{
if (a > 0) <!RETURN_NOT_ALLOWED!>return<!> if (a > 0) <!RETURN_NOT_ALLOWED!>return<!>
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!> <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>
}): Int }
x: Int
} }
fun run<T>(f: () -> T): T { return f() } fun run<T>(f: () -> T): T { return f() }
@@ -1,5 +1,6 @@
fun test2() { fun test2() {
(run @f{<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>}): Int val x = run @f{<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>}
x: Int
} }
fun run<T>(f: () -> T): T { return f() } fun run<T>(f: () -> T): T { return f() }
@@ -1,10 +1,12 @@
fun test() { fun test() {
run(@f{<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>}): Int val x = run(@f{<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>})
x: Int
} }
fun test1() { fun test1() {
run(@{<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@ 1<!>}): Int val x = run(@{<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@ 1<!>})
x: Int
} }
fun run<T>(f: () -> T): T { return f() } fun run<T>(f: () -> T): T { return f() }
@@ -1,11 +1,12 @@
fun test() { fun test() {
(run @f{ val x = run @f{
fun local(a: Int): String { fun local(a: Int): String {
if (a > 0) return "2" if (a > 0) return "2"
return@local "3" return@local "3"
} }
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!> <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>
}): Int }
x: Int
} }
fun run<T>(f: () -> T): T { return f() } fun run<T>(f: () -> T): T { return f() }
@@ -1,10 +1,11 @@
fun test() { fun test() {
(run @f{ val x = run @f{
run @ff { run @ff {
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@ff "2"<!> <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@ff "2"<!>
} }
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!> <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>
}): Int }
x: Int
} }
fun run<T>(f: () -> T): T { return f() } fun run<T>(f: () -> T): T { return f() }
@@ -1,8 +1,9 @@
fun test(a: Int) { fun test(a: Int) {
(run @f{ val x = run @f{
if (a > 0) <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f<!> if (a > 0) <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f<!>
else <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f Unit.VALUE<!> else <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f Unit.VALUE<!>
}): Unit }
x: Unit
} }
fun run<T>(f: () -> T): T { return f() } fun run<T>(f: () -> T): T { return f() }
@@ -4,10 +4,11 @@ trait C: A
fun test(a: C, b: B) { fun test(a: C, b: B) {
(run @f{ val x = run @f{
if (a != b) <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f a<!> if (a != b) <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f a<!>
b b
}): A }
x: A
} }
fun run<T>(f: () -> T): T { return f() } fun run<T>(f: () -> T): T { return f() }