[NI] Fix resolve of lambdas with expected function type with receiver
#KT-30245
This commit is contained in:
+10
-5
@@ -130,27 +130,32 @@ private fun extractLambdaInfoFromFunctionalType(
|
||||
|
||||
// Extracting parameters and receiver type, taking into account the actual lambda definition and expected lambda type
|
||||
val (parameters, receiver) = when {
|
||||
argumentAsFunctionExpression != null ->
|
||||
argumentAsFunctionExpression != null -> {
|
||||
// lambda has explicit functional type - use types from it if available
|
||||
(parametersTypes?.mapIndexed { index, type ->
|
||||
type.orExpected(index)
|
||||
} ?: emptyList()) to argumentAsFunctionExpression.receiverType
|
||||
(parametersTypes?.size ?: 0) == expectedParameters.size && receiverFromExpected ->
|
||||
}
|
||||
|
||||
(parametersTypes?.size ?: 0) == expectedParameters.size && receiverFromExpected -> {
|
||||
// expected type has receiver, but arguments sizes are the same in actual and expected, so assuming missing (maybe unused) receiver in lambda
|
||||
// TODO: in case of implicit parameters in lambda ("this" and "it") this case assumes "this", probably we should generate two possible overloads and choose among them later
|
||||
(parametersTypes?.mapIndexed { index, type ->
|
||||
type.orExpected(index)
|
||||
} ?: expectedParameters.map { it.type.unwrap() }) to expectedReceiver
|
||||
}
|
||||
|
||||
(parametersTypes?.size ?: 0) - expectedParameters.size == 1 && receiverFromExpected -> {
|
||||
// one "missing" parameter in the expected parameters - first lambda parameter should be mapped to expected receiver
|
||||
// TODO: same "this" or "it" case from above could be applicable here as well
|
||||
|
||||
(parametersTypes?.mapIndexed { index, type ->
|
||||
type ?: run {
|
||||
if (index == 0) expectedReceiver?.unwrap()
|
||||
else expectedParameters.getOrNull(index - 1)?.type?.unwrap()
|
||||
expectedParameters.getOrNull(index)?.type?.unwrap()
|
||||
} ?: expectedType.builtIns.nullableAnyType
|
||||
} ?: expectedParameters.map { it.type.unwrap() }) to null
|
||||
} ?: expectedParameters.map { it.type.unwrap() }) to expectedReceiver?.unwrap()
|
||||
}
|
||||
|
||||
else ->
|
||||
(parametersTypes?.mapIndexed { index, type ->
|
||||
type.orExpected(index)
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
fun foo(<!UNUSED_PARAMETER!>f<!>: String.() -> Int) {}
|
||||
val test = foo(<!OI;TYPE_MISMATCH!>fun () = <!UNRESOLVED_REFERENCE!>length<!><!>)
|
||||
val test = foo(<!TYPE_MISMATCH!>fun <!NI;EXPECTED_PARAMETERS_NUMBER_MISMATCH!>()<!> = <!UNRESOLVED_REFERENCE!>length<!><!>)
|
||||
@@ -42,11 +42,11 @@ fun test1() { // to extension lambda 0
|
||||
val f10 = W1(fun Int.(): Int = this) // oi+ ni+
|
||||
val g10: E0 = id(fun Int.(): Int = this) // oi+ ni+
|
||||
|
||||
val w11 = W1 { i: Int -> i } // oi- ni+
|
||||
val w11 = W1 { i: Int -> i } // oi- ni-
|
||||
val i11: E0 = id { i: Int -> i } // o1+ ni+
|
||||
val w12 = <!INAPPLICABLE_CANDIDATE!>W1<!> { i -> i } // oi- ni+
|
||||
val i12: E0 = id { i -> i } // oi- ni+
|
||||
val j12 = <!INAPPLICABLE_CANDIDATE!>id<!><E0> { i -> i } // oi- ni+
|
||||
val w12 = <!INAPPLICABLE_CANDIDATE!>W1<!> { i -> i } // oi- ni-
|
||||
val i12: E0 = id { i -> i } // oi- ni-
|
||||
val j12 = <!INAPPLICABLE_CANDIDATE!>id<!><E0> { i -> i } // oi- ni-
|
||||
|
||||
// yet unsupported cases - considering lambdas as extension ones unconditionally
|
||||
// val w13 = W1 { it } // this or it: oi- ni-
|
||||
@@ -78,9 +78,9 @@ fun test2() { // to extension lambda 1
|
||||
// val w27 = W2 { i, s: String -> i + s.length } // overload oi- ni-
|
||||
// val i27: E1 = id { i, s: String -> i + s.length } // overload oi- ni-
|
||||
|
||||
val w28 = <!INAPPLICABLE_CANDIDATE!>W2<!> { i: Int, s -> i <!AMBIGUITY!>+<!> s.<!UNRESOLVED_REFERENCE!>length<!> } // oi- ni+
|
||||
val i28: E1 = id { i: Int, s -> i <!AMBIGUITY!>+<!> s.<!UNRESOLVED_REFERENCE!>length<!> } // oi- ni+
|
||||
val w29 = W2 { i: Int, s: String -> i + s.length } // oi- ni+
|
||||
val w28 = <!INAPPLICABLE_CANDIDATE!>W2<!> { i: Int, s -> i <!AMBIGUITY!>+<!> s.<!UNRESOLVED_REFERENCE!>length<!> } // oi- ni-
|
||||
val i28: E1 = id { i: Int, s -> i <!AMBIGUITY!>+<!> s.<!UNRESOLVED_REFERENCE!>length<!> } // oi- ni-
|
||||
val w29 = W2 { i: Int, s: String -> i + s.length } // oi- ni-
|
||||
val i29: E1 = id { i: Int, s: String -> i + s.length } // oi+ ni+
|
||||
|
||||
// yet unsupported cases with ambiguity for the lambda conversion (commented constructors in wrappers above)
|
||||
|
||||
@@ -42,11 +42,11 @@ fun test1() { // to extension lambda 0
|
||||
val f10 = W1(fun Int.(): Int = this) // oi+ ni+
|
||||
val g10: E0 = id(fun Int.(): Int = this) // oi+ ni+
|
||||
|
||||
val w11 = W1 { i: Int -> i } // oi- ni+
|
||||
val w11 = W1 <!TYPE_MISMATCH!>{ <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!>i: Int<!> -> i }<!> // oi- ni-
|
||||
val i11: E0 = id { i: Int -> i } // o1+ ni+
|
||||
val w12 = W1 { i -> i } // oi- ni+
|
||||
val i12: E0 = id { i -> i } // oi- ni+
|
||||
val j12 = id<E0> { i -> i } // oi- ni+
|
||||
val w12 = W1 <!TYPE_MISMATCH!>{ <!CANNOT_INFER_PARAMETER_TYPE, EXPECTED_PARAMETERS_NUMBER_MISMATCH!>i<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>i<!> }<!> // oi- ni-
|
||||
val i12: E0 = id <!TYPE_MISMATCH!>{ <!CANNOT_INFER_PARAMETER_TYPE, EXPECTED_PARAMETERS_NUMBER_MISMATCH!>i<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>i<!> }<!> // oi- ni-
|
||||
val j12 = id<E0> <!TYPE_MISMATCH!>{ <!CANNOT_INFER_PARAMETER_TYPE, EXPECTED_PARAMETERS_NUMBER_MISMATCH!>i<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>i<!> }<!> // oi- ni-
|
||||
|
||||
// yet unsupported cases - considering lambdas as extension ones unconditionally
|
||||
// val w13 = W1 { it } // this or it: oi- ni-
|
||||
@@ -78,9 +78,9 @@ fun test2() { // to extension lambda 1
|
||||
// val w27 = W2 { i, s: String -> i + s.length } // overload oi- ni-
|
||||
// val i27: E1 = id { i, s: String -> i + s.length } // overload oi- ni-
|
||||
|
||||
val w28 = W2 { i: Int, s -> i + s.length } // oi- ni+
|
||||
val i28: E1 = id { i: Int, s -> i + s.length } // oi- ni+
|
||||
val w29 = W2 { i: Int, s: String -> i + s.length } // oi- ni+
|
||||
val w28 = W2 <!TYPE_MISMATCH!>{ <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!><!EXPECTED_PARAMETER_TYPE_MISMATCH!>i: Int<!>, <!CANNOT_INFER_PARAMETER_TYPE!>s<!><!> -> i <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>s<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>length<!> }<!> // oi- ni-
|
||||
val i28: E1 = <!TYPE_MISMATCH!>id <!TYPE_MISMATCH!>{ <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!><!EXPECTED_PARAMETER_TYPE_MISMATCH!>i: Int<!>, <!CANNOT_INFER_PARAMETER_TYPE!>s<!><!> -> i <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>s<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>length<!> }<!><!> // oi- ni-
|
||||
val w29 = W2 <!TYPE_MISMATCH!>{ <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!><!EXPECTED_PARAMETER_TYPE_MISMATCH!>i: Int<!>, s: String<!> -> i + s.length }<!> // oi- ni-
|
||||
val i29: E1 = id { i: Int, s: String -> i + s.length } // oi+ ni+
|
||||
|
||||
// yet unsupported cases with ambiguity for the lambda conversion (commented constructors in wrappers above)
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package
|
||||
|
||||
public fun bar1(/*0*/ a: Array2D<kotlin.Int> /* = kotlin.Array<kotlin.Array<kotlin.Int>> */): Array2D<out kotlin.Number> /* = kotlin.Array<kotlin.Array<out kotlin.Number>> */
|
||||
public fun bar2(/*0*/ m: TMap<*> /* = kotlin.collections.Map<*, *> */): kotlin.collections.Map<*, *>
|
||||
public fun bar2(/*0*/ m: TMap<*> /* = kotlin.collections.Map<*, *> */): kotlin.collections.Map<*, kotlin.Any?>
|
||||
public fun foo1(/*0*/ a: Array2D<out kotlin.Number> /* = kotlin.Array<kotlin.Array<out kotlin.Number>> */): Array2D<out kotlin.Number> /* = kotlin.Array<kotlin.Array<out kotlin.Number>> */
|
||||
public fun </*0*/ T> foo2(/*0*/ m: TMap<T> /* = kotlin.collections.Map<T, T> */): TMap<T> /* = kotlin.collections.Map<T, T> */
|
||||
public typealias Array2D</*0*/ T> = kotlin.Array<kotlin.Array<T>>
|
||||
|
||||
Reference in New Issue
Block a user