Support local return in lambda without explicit return type

This commit is contained in:
Stanislav Erokhin
2015-02-17 15:20:12 +03:00
parent def81d30dc
commit 57fd5cc84c
41 changed files with 340 additions and 40 deletions
@@ -8,10 +8,10 @@ fun unitEmptyReturn() : Unit {return}
fun unitIntReturn() : Unit {return <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>}
fun unitUnitReturn() : Unit {return Unit}
fun test1() : Any = {<!RETURN_NOT_ALLOWED, RETURN_TYPE_MISMATCH!>return<!>}
fun test2() : Any = @a {<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@a 1<!>}
fun test2() : Any = @a {return@a 1}
fun test3() : Any { <!RETURN_TYPE_MISMATCH!>return<!> }
fun test4(): ()-> Unit = { <!RETURN_NOT_ALLOWED, RETURN_TYPE_MISMATCH!>return@test4<!> }
fun test5(): Any = @l{ <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@l<!> }
fun test5(): Any = @l{ return@l }
fun test6(): Any = {<!RETURN_NOT_ALLOWED!>return 1<!>}
fun bbb() {
@@ -0,0 +1,5 @@
val flag = true
val a/*: () -> Comparable<out Any?>*/ = @l {
return@l if (flag) "OK" else 4
}
@@ -0,0 +1,4 @@
package
internal val a: () -> kotlin.Comparable<out kotlin.Any?>
internal val flag: kotlin.Boolean = true
@@ -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) <!UNUSED_EXPRESSION!>4<!>
}
@@ -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
@@ -0,0 +1,22 @@
val flag = true
val a: () -> Int = @l {
<!TYPE_MISMATCH!>if (flag) return@l 4<!>
}
val b: () -> Unit = @l {
if (flag) return@l <!CONSTANT_EXPECTED_TYPE_MISMATCH!>4<!>
}
val c: () -> Any = @l {
if (flag) return@l 4
}
val d: () -> Int = @l {
if (flag) return@l 4
5
}
val e: () -> Int = @l {
<!TYPE_MISMATCH!>if (flag) <!UNUSED_EXPRESSION!>4<!><!>
}
@@ -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
@@ -0,0 +1,17 @@
val flag = true
val a /*: (Int) -> String */ = @l {
(i: Int) ->
if (i == 0) return@l i.toString()
"Ok"
}
fun <T> foo(f: (Int) -> T): T = f(0)
val b /*:String */ = foo {
(i) ->
if (i == 0) return@foo i.toString()
"Ok"
}
@@ -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 </*0*/ T> foo(/*0*/ f: (kotlin.Int) -> T): T
@@ -1,7 +1,7 @@
fun test2(a: Int) {
val x = run @f{
if (a > 0) <!RETURN_NOT_ALLOWED!>return<!>
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>
return@f 1
}
x: Int
}
@@ -1,5 +1,5 @@
fun test2() {
val x = run @f{<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>}
val x = run @f{return@f 1}
x: Int
}
@@ -1,11 +1,11 @@
fun test() {
val x = run(@f{<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>})
val x = run(@f{return@f 1})
x: Int
}
fun test1() {
val x = run(@l{<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@l 1<!>})
val x = run(@l{return@l 1})
x: Int
}
@@ -4,7 +4,7 @@ fun test() {
if (a > 0) return "2"
return@local "3"
}
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>
return@f 1
}
x: Int
}
@@ -1,9 +1,9 @@
fun test() {
val x = run @f{
run @ff {
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@ff "2"<!>
return@ff "2"
}
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>
return@f 1
}
x: Int
}
@@ -1,7 +1,7 @@
fun test(a: Int) {
run @f{
if (a > 0) <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f<!>
else <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f 1<!>
if (a > 0) <!RETURN_TYPE_MISMATCH!>return@f<!>
else return@f 1
}
}
@@ -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()
}
@@ -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
}
@@ -1,9 +1,9 @@
fun test(a: Int) {
val x = run @f{
if (a > 0) <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f<!>
else <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f Unit<!>
if (a > 0) <!RETURN_TYPE_MISMATCH!>return@f<!>
else return@f Unit
}
x: Unit
}
fun run<T>(f: () -> T): T { return f() }
fun run<T>(f: () -> T): T { return f() }
@@ -0,0 +1,9 @@
fun listOf<T>(): List<T> = null!!
fun listOf<T>(vararg <!UNUSED_PARAMETER!>values<!>: T): List<T> = null!!
val flag = true
val a: () -> List<Int> = @l {
if (flag) return@l listOf()
listOf(5)
}
@@ -0,0 +1,6 @@
package
internal val a: () -> kotlin.List<kotlin.Int>
internal val flag: kotlin.Boolean = true
internal fun </*0*/ T> listOf(): kotlin.List<T>
internal fun </*0*/ T> listOf(/*0*/ vararg values: T /*kotlin.Array<out T>*/): kotlin.List<T>
@@ -5,7 +5,7 @@ trait C: A
fun test(a: C, b: B) {
val x = run @f{
if (a != b) <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@f a<!>
if (a != b) return@f a
b
}
x: A
@@ -0,0 +1,18 @@
fun <T, R> Iterable<T>.map(<!UNUSED_PARAMETER!>transform<!>: (T) -> R): List<R> = null!!
fun listOf<T>(): List<T> = null!!
fun listOf<T>(vararg <!UNUSED_PARAMETER!>values<!>: T): List<T> = null!!
fun commonSystemFailed(a: List<Int>) {
a.map {
if (it == 0) return@map listOf(it)
<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>listOf<!>()
}
a.map {
if (it == 0) return@map <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>listOf<!>()
listOf(it)
}
a.map {
if (it == 0) listOf()
else listOf(it)
}
}
@@ -0,0 +1,6 @@
package
internal fun commonSystemFailed(/*0*/ a: kotlin.List<kotlin.Int>): kotlin.Unit
internal fun </*0*/ T> listOf(): kotlin.List<T>
internal fun </*0*/ T> listOf(/*0*/ vararg values: T /*kotlin.Array<out T>*/): kotlin.List<T>
internal fun </*0*/ T, /*1*/ R> kotlin.Iterable<T>.map(/*0*/ transform: (T) -> R): kotlin.List<R>
@@ -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 <R> let(<!UNUSED_PARAMETER!>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) <!DEBUG_INFO_SMARTCAST!>it<!> else 5
}
@@ -0,0 +1,6 @@
package
internal val a: (kotlin.Int?) -> kotlin.Int?
internal val b: kotlin.Int?
internal val c: kotlin.Int
internal fun </*0*/ R> let(/*0*/ f: (kotlin.Int?) -> R): R
@@ -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 <!DEBUG_INFO_SMARTCAST!>it<!>
5
}
fun <R> let(<!UNUSED_PARAMETER!>f<!>: (Int?) -> R): R = null!!
val b: Int = <!TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>let<!> {
if (it != null) return@let it
5
}
val c: Int = let {
if (it != null) <!DEBUG_INFO_SMARTCAST!>it<!> else 5
}
@@ -0,0 +1,6 @@
package
internal val a: (kotlin.Int?) -> kotlin.Int
internal val b: kotlin.Int
internal val c: kotlin.Int
internal fun </*0*/ R> let(/*0*/ f: (kotlin.Int?) -> R): R
@@ -0,0 +1,10 @@
package m
trait Element
fun test(handlers: Map<String, Element.()->Unit>) {
handlers.getOrElse("name", @l { return@l <!NULL_FOR_NONNULL_TYPE!>null<!> })
}
fun <K,V> Map<K,V>.getOrElse(key: K, defaultValue: ()-> V) : V = throw Exception("$key $defaultValue")
@@ -0,0 +1,12 @@
package
package m {
internal fun test(/*0*/ handlers: kotlin.Map<kotlin.String, m.Element.() -> kotlin.Unit>): kotlin.Unit
internal fun </*0*/ K, /*1*/ V> kotlin.Map<K, V>.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
}
}
@@ -0,0 +1,12 @@
package n
//+JDK
import java.util.*
fun expected<T>(t: T, <!UNUSED_PARAMETER!>f<!>: () -> T) : T = t
fun test(arrayList: ArrayList<Int>, list: List<Int>) {
val <!UNUSED_VARIABLE!>t<!> = expected(arrayList, @l {return@l list.reverse() })
}
fun <T> List<T>.reverse() : List<T> = this
@@ -0,0 +1,7 @@
package
package n {
internal fun </*0*/ T> expected(/*0*/ t: T, /*1*/ f: () -> T): T
internal fun test(/*0*/ arrayList: java.util.ArrayList<kotlin.Int>, /*1*/ list: kotlin.List<kotlin.Int>): kotlin.Unit
internal fun </*0*/ T> kotlin.List<T>.reverse(): kotlin.List<T>
}
@@ -1,7 +1,7 @@
fun inlineCallExplicitError(): String {
inlineFun @lamba {
if (true) {
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@lamba 2<!>
return@lamba 2
}
1
}
@@ -6,7 +6,7 @@ public inline fun <reified T> Array(n: Int, block: (Int) -> T): Array<T> = null!
fun test() {
val ints = Array<Int?>(2, { null })
ints.forEach @lit {
if (it == null) <!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return @lit<!>
if (it == null) return @lit
use(<!DEBUG_INFO_SMARTCAST!>it<!> + 5)
}
}
@@ -5,7 +5,7 @@ package kt411
fun f() {
invoker(
@l{
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>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 <!UNUSED_VARIABLE!>g<!> : ()-> Int = @l{
if (true) {
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@l 1<!>
return@l 1
}
<!RETURN_NOT_ALLOWED!>return "s"<!>
}
@@ -37,7 +37,7 @@ fun t3() : String {
else {
<!RETURN_NOT_ALLOWED!>return <!CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!><!>
}
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED, UNREACHABLE_CODE!>return@l 0<!>
<!UNREACHABLE_CODE!>return@l 0<!>
}
)
invoker(
@@ -55,7 +55,7 @@ fun t3() : String {
fun t4() : Int {
val <!UNUSED_VARIABLE!>h<!> : ()-> String = @l{
<!RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED!>return@l "a"<!>
return@l "a"
}
val <!UNUSED_VARIABLE!>g<!> : ()-> String = @l{ () : String ->
return@l "a"