FIR: allow fun (x: T) ... as an instance of T.() -> ...
and disallow > 1 implicit parameters in lambdas.
This commit is contained in:
+7
-6
@@ -252,7 +252,6 @@ fun extractLambdaInfoFromFunctionalType(
|
||||
}
|
||||
if (!expectedType.isBuiltinFunctionalType(session)) return null
|
||||
|
||||
val receiverType = argument.receiverType ?: expectedType.receiverType(session)
|
||||
val lastStatement = argument.body?.statements?.singleOrNull()
|
||||
val returnType =
|
||||
// Simply { }, i.e., function literals without body. Raw FIR added an implicit return with an implicit unit type ref.
|
||||
@@ -262,14 +261,16 @@ fun extractLambdaInfoFromFunctionalType(
|
||||
session.builtinTypes.unitType.type
|
||||
else
|
||||
argument.returnType ?: expectedType.returnType(session)
|
||||
// `fun (x: T) = ...` and `fun T.() = ...` are both instances of `T.() -> V`; `fun () = ...` is not.
|
||||
// For lambdas, the existence of the receiver is always implied by the expected type, and a value parameter
|
||||
// can never fill its role.
|
||||
val receiverType = if (argument.isLambda) expectedType.receiverType(session) else argument.receiverType
|
||||
val expectedParameters = expectedType.valueParameterTypesIncludingReceiver(session).let {
|
||||
if (expectedType.isExtensionFunctionType(session)) it.drop(1) else it
|
||||
if (receiverType != null && expectedType.isExtensionFunctionType(session)) it.drop(1) else it
|
||||
}
|
||||
val parameters = if (argument.valueParameters.isEmpty()) {
|
||||
expectedParameters
|
||||
val parameters = if (argument.isLambda && argument.valueParameters.isEmpty() && expectedParameters.size < 2) {
|
||||
expectedParameters // Infer existence of a parameter named `it` of an appropriate type.
|
||||
} else {
|
||||
// TODO: `(A) -> B` is permitted as `A.() -> B` if it's an anonymous function, not a lambda;
|
||||
// e.g. `fun (x: Any?) = x` can be used as `Any?.() -> Any?`, but `{ it -> it }` cannot.
|
||||
argument.valueParameters.mapIndexed { index, parameter ->
|
||||
parameter.returnTypeRef.coneTypeSafe() ?: expectedParameters.getOrNull(index) ?: session.builtinTypes.nothingType.type
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ fun text() {
|
||||
"direct:a" to "mock:a"
|
||||
"direct:a" on {it.body == "<hello/>"} to "mock:a"
|
||||
"direct:a" on {it -> it.body == "<hello/>"} to "mock:a"
|
||||
bar {1}
|
||||
bar {<!UNRESOLVED_REFERENCE!>it<!> + 1}
|
||||
bar {<!ARGUMENT_TYPE_MISMATCH!>1<!>}
|
||||
bar {<!ARGUMENT_TYPE_MISMATCH!><!UNRESOLVED_REFERENCE!>it<!> + 1<!>}
|
||||
bar {it, it1 -> it}
|
||||
|
||||
bar1 {1}
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
fun foo(f: String.() -> Int) {}
|
||||
val test = foo(fun () = <!UNRESOLVED_REFERENCE!>length<!>)
|
||||
val test = foo(fun () = <!ARGUMENT_TYPE_MISMATCH, UNRESOLVED_REFERENCE!>length<!>)
|
||||
|
||||
Vendored
+2
-2
@@ -31,7 +31,7 @@ fun test1() {
|
||||
|
||||
|
||||
foo2 {
|
||||
""
|
||||
<!ARGUMENT_TYPE_MISMATCH!>""<!>
|
||||
}
|
||||
foo2 {
|
||||
s: String -> <!ARGUMENT_TYPE_MISMATCH!>""<!>
|
||||
@@ -40,6 +40,6 @@ fun test1() {
|
||||
x -> <!ARGUMENT_TYPE_MISMATCH!>""<!>
|
||||
}
|
||||
foo2 {
|
||||
-> 42
|
||||
-> <!ARGUMENT_TYPE_MISMATCH!>42<!>
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,5 +20,5 @@ fun testFunctions() {
|
||||
fun testNestedCalls() {
|
||||
id<String>(inferFromLambda { materialize() })
|
||||
id<String>(inferFromLambda(fun() = materialize()))
|
||||
id<String>(inferFromLambda2(fun() = materialize()))
|
||||
id<String>(<!ARGUMENT_TYPE_MISMATCH!>inferFromLambda2(fun() = <!ARGUMENT_TYPE_MISMATCH!>materialize()<!>)<!>)
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -228,7 +228,7 @@ fun main() {
|
||||
val x70: (Int) -> Unit = selectNumber(id(fun (it) { }), id {}, id {})
|
||||
val x71: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun String.() { })<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun(x: String) {})<!>)
|
||||
val x72: String.() -> Unit = select(fun String.() { }, fun(x: String) {}) // must be error
|
||||
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), fun (x, y) { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>y<!> })
|
||||
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), fun (x, y) { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>y<!> })
|
||||
select(id<Int.(String) -> Unit>(fun (x, y) {}), { x: Int, y: String -> x }) // receiver of anonymous function must be specified explicitly
|
||||
select(id<Int.(String) -> Unit>(fun Int.(y) {}), { x: Int, y: String -> x })
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Number, java.io.Serializable>")!>select(A3(), fun (x) = "", { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>a<!> })<!>
|
||||
|
||||
@@ -111,7 +111,7 @@ fun test3() { // to non-extension lambda 1
|
||||
// val i32: L1 = id { this } // this or it: oi- ni-
|
||||
// val j32 = id<L1> { this } // this or it: oi- ni-
|
||||
|
||||
val w33 = W3(fun Int.(): Int = <!ARGUMENT_TYPE_MISMATCH!>this<!>) // oi- ni+
|
||||
val w33 = W3(fun Int.(): Int = this) // oi- ni+
|
||||
val i33: L1 = id(fun Int.(): Int = this) // oi+ ni+
|
||||
|
||||
// yet unsupported cases with ambiguity for the lambda conversion (commented constructors in wrappers above)
|
||||
|
||||
Reference in New Issue
Block a user