K2: Complete property-candidate before starting invoke resolution

Before this commit, for property candidates in K2 their types wasn't
inferred/susbtituted properly.

So, when candidate for fooBar.liveLoaded.invoke() was created,
the type of `fooBar.liveLoaded` was just X type parameter for which
there is no any `bar()` functions in its member scope.

While proposed semantics is a bit different from K1, where
both property and invoke candidates are united into common system,
it doesn't contradict to the specification (https://kotlinlang.org/spec/overload-resolution.html#callables-and-invoke-convention)
which says explicitly that invoke-convention should be desugared as
`r.foo.invoke()`, thus `r.foo` should be completed independently.

Also, this strategy supports some reasonable use-cases like KT-58259
while it's still a breaking change but for more artificial-looking
situations (see KT-58260) and should be passed through
the language committee.

The changes in stubTypeReceiverRestriction* tests looks consistent
because of how `genericLambda` now works
(with full completion of property call).
NB: The code is going to be red once KT-54667 is fixed and also there's
already similar diagnostic in K1 (INFERRED_INTO_DECLARED_UPPER_BOUNDS)

^KT-58142 Fixed
^KT-58259 Fixed
^KT-58260 Related
This commit is contained in:
Denis.Zharkov
2023-04-24 12:27:47 +02:00
committed by Space Team
parent 481becb342
commit 7b46c59d57
17 changed files with 191 additions and 68 deletions
@@ -1,40 +0,0 @@
FILE fqName:<root> fileName:/variableAsFunctionCallWithGenerics.kt
PROPERTY name:gk visibility:public modality:FINAL [val]
FUN name:<get-gk> visibility:public modality:FINAL <T> ($receiver:T of <root>.<get-gk>) returnType:kotlin.Function0<T of <root>.<get-gk>>
correspondingProperty: PROPERTY name:gk visibility:public modality:FINAL [val]
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.CharSequence] reified:false
$receiver: VALUE_PARAMETER name:<this> type:T of <root>.<get-gk>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-gk> <T> (): kotlin.Function0<T of <root>.<get-gk>> declared in <root>'
FUN_EXPR type=kotlin.Function0<T of <root>.<get-gk>> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:T of <root>.<get-gk>
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): T of <root>.<get-gk> declared in <root>.<get-gk>'
GET_VAR '<this>: T of <root>.<get-gk> declared in <root>.<get-gk>' type=T of <root>.<get-gk> origin=null
FUN name:testGeneric1 visibility:public modality:FINAL <> (x:kotlin.String) returnType:T of <root>.<get-gk>
VALUE_PARAMETER name:x index:0 type:kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testGeneric1 (x: kotlin.String): T of <root>.<get-gk> declared in <root>'
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of <root>.<get-gk> origin=INVOKE
$this: CALL 'public final fun <get-gk> <T> (): kotlin.Function0<T of <root>.<get-gk>> declared in <root>' type=kotlin.Function0<kotlin.String> origin=GET_PROPERTY
<T>: kotlin.String
$receiver: GET_VAR 'x: kotlin.String declared in <root>.testGeneric1' type=kotlin.String origin=null
PROPERTY name:kt26531Val visibility:public modality:FINAL [val]
FUN name:<get-kt26531Val> visibility:public modality:FINAL <T> ($receiver:T of <root>.<get-kt26531Val>) returnType:kotlin.Function0<T of <root>.<get-kt26531Val>>
correspondingProperty: PROPERTY name:kt26531Val visibility:public modality:FINAL [val]
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] reified:false
$receiver: VALUE_PARAMETER name:<this> type:T of <root>.<get-kt26531Val>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-kt26531Val> <T> (): kotlin.Function0<T of <root>.<get-kt26531Val>> declared in <root>'
FUN_EXPR type=kotlin.Function0<T of <root>.<get-kt26531Val>> origin=ANONYMOUS_FUNCTION
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:T of <root>.<get-kt26531Val>
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <no name provided> (): T of <root>.<get-kt26531Val> declared in <root>.<get-kt26531Val>'
GET_VAR '<this>: T of <root>.<get-kt26531Val> declared in <root>.<get-kt26531Val>' type=T of <root>.<get-kt26531Val> origin=null
FUN name:kt26531 visibility:public modality:FINAL <> () returnType:T of <root>.<get-kt26531Val>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun kt26531 (): T of <root>.<get-kt26531Val> declared in <root>'
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of <root>.<get-kt26531Val> origin=INVOKE
$this: CALL 'public final fun <get-kt26531Val> <T> (): kotlin.Function0<T of <root>.<get-kt26531Val>> declared in <root>' type=kotlin.Function0<kotlin.Int> origin=GET_PROPERTY
<T>: kotlin.Int
$receiver: CONST Int type=kotlin.Int value=7
@@ -1,23 +0,0 @@
val <T : CharSequence> T.gk: Function0<T>
get(): Function0<T> {
return local fun <anonymous>(): T {
return <this>
}
}
fun testGeneric1(x: String): T {
return x.<get-gk><String>().invoke()
}
val <T : Any?> T.kt26531Val: Function0<T>
get(): Function0<T> {
return local fun <no name provided>(): T {
return <this>
}
}
fun kt26531(): T {
return 7.<get-kt26531Val><Int>().invoke()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
val <T : CharSequence> T.gk: () -> T
get() = { -> this }