K2: handle type parameter vs nested class conflict in body resolve properly

This commit does two things:
- prioritize type parameter scopes against static scopes in body resolve
(effectively it's a revert of KT-58028 fix)
- consider type parameters as inapplicable callable, so during callable
resolve we can go up the tower and still resolve to static scope

This allows both KT-58028 and KT-63377 to work properly
#KT-63377 Fixed
This commit is contained in:
Mikhail Glukhikh
2023-11-22 18:19:35 +01:00
committed by Space Team
parent 4e938d852c
commit 83cfcc30c6
25 changed files with 86 additions and 73 deletions
@@ -1 +1,3 @@
null
KtErrorCallInfo:
candidateCalls = []
diagnostic = ERROR<null: Type parameter T in qualified access>
@@ -1,4 +1,7 @@
USED DECLARATIONS:
Declaration: dependency.T
By names: [T]
UNRESOLVED NAMES:
println
@@ -12,13 +12,13 @@ Tower Data Context:
Element 5
Scope: FirExplicitSimpleImportingScope
Element 6
Scope: FirMemberTypeParameterScope
Classifiers:
FirTypeParameterSymbol F
Element 7
Scope: FirNestedClassifierScopeImpl
Classifiers:
FirRegularClassSymbol public final inner class Bar<B, Outer(F)> : R|kotlin/Any|
Element 7
Scope: FirMemberTypeParameterScope
Classifiers:
FirTypeParameterSymbol F
Element 8
Implicit receiver:
FirRegularClassSymbol public final class Foo<F> : R|kotlin/Any|
@@ -12,13 +12,13 @@ Tower Data Context:
Element 5
Scope: FirExplicitSimpleImportingScope
Element 6
Scope: FirMemberTypeParameterScope
Classifiers:
FirTypeParameterSymbol MyParam
Element 7
Scope: FirNestedClassifierScopeImpl
Classifiers:
FirRegularClassSymbol public final inner class Inner<T : R|MyParam|, Outer(MyParam)> : R|kotlin/Any|
Element 7
Scope: FirMemberTypeParameterScope
Classifiers:
FirTypeParameterSymbol MyParam
Element 8
Implicit receiver:
FirRegularClassSymbol public final class Outer<MyParam> : R|kotlin/Any|
@@ -12,13 +12,13 @@ Tower Data Context:
Element 5
Scope: FirExplicitSimpleImportingScope
Element 6
Scope: FirMemberTypeParameterScope
Classifiers:
FirTypeParameterSymbol MyParam
Element 7
Scope: FirNestedClassifierScopeImpl
Classifiers:
FirRegularClassSymbol public final inner class Inner<Outer(MyParam)> : R|kotlin/Any|
Element 7
Scope: FirMemberTypeParameterScope
Classifiers:
FirTypeParameterSymbol MyParam
Element 8
Implicit receiver:
FirRegularClassSymbol public final class Outer<MyParam> : R|kotlin/Any|
@@ -12,13 +12,13 @@ Tower Data Context:
Element 5
Scope: FirExplicitSimpleImportingScope
Element 6
Scope: FirMemberTypeParameterScope
Classifiers:
FirTypeParameterSymbol MyParam
Element 7
Scope: FirNestedClassifierScopeImpl
Classifiers:
FirRegularClassSymbol public final class Nested<T : <ERROR TYPE REF: Symbol not found for MyParam>> : R|kotlin/Any|
Element 7
Scope: FirMemberTypeParameterScope
Classifiers:
FirTypeParameterSymbol MyParam
Element 8
Implicit receiver:
FirRegularClassSymbol public final class Outer<MyParam> : R|kotlin/Any|
@@ -53,8 +53,8 @@ FILE: multipleBounds.kt
}
public final fun test(t: R|T|): R|kotlin/Unit| {
R|?|.<Unresolved name: foo>#()
R|?|.<Unresolved name: bar>#()
R|?<Type parameter T in qualified access>#|.<Unresolved name: foo>#()
R|?<Type parameter T in qualified access>#|.<Unresolved name: bar>#()
R|<local>/t|.R|Jet87/A.foo|()
R|<local>/t|.R|Jet87/B.bar|()
}
@@ -96,8 +96,8 @@ FILE: multipleBounds.kt
}
public final fun <T : R|Jet87/A|, R|Jet87/B|> test2(t: R|T|): R|kotlin/Unit| {
R|?|.<Unresolved name: foo>#()
R|?|.<Unresolved name: bar>#()
R|?<Type parameter T in qualified access>#|.<Unresolved name: foo>#()
R|?<Type parameter T in qualified access>#|.<Unresolved name: bar>#()
R|<local>/t|.R|Jet87/A.foo|()
R|<local>/t|.R|Jet87/B.bar|()
}
@@ -362,6 +362,9 @@ private fun mapInapplicableCandidateError(
qualifiedAccessSource
)
// Reported later
is TypeParameterAsExpression -> null
else -> genericDiagnostic
}
}.distinct()
@@ -608,7 +608,13 @@ fun createConeDiagnosticForCandidateWithError(
}
CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER -> ConeInapplicableWrongReceiver(listOf(candidate))
CandidateApplicability.K2_NO_COMPANION_OBJECT -> ConeNoCompanionObject(candidate)
else -> ConeInapplicableCandidateError(applicability, candidate)
else -> {
if (TypeParameterAsExpression in candidate.diagnostics) {
ConeTypeParameterInQualifiedAccess(candidate.symbol as FirTypeParameterSymbol)
} else {
ConeInapplicableCandidateError(applicability, candidate)
}
}
}
}
@@ -24,6 +24,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
LowerPriorityIfDynamic,
ConstraintSystemForks,
CheckIncompatibleTypeVariableUpperBounds,
TypeParameterAsCallable,
)
object SyntheticSelect : CallKind(
@@ -59,6 +60,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
LowerPriorityIfDynamic,
ConstraintSystemForks,
CheckIncompatibleTypeVariableUpperBounds,
TypeParameterAsCallable,
)
object DelegatingConstructorCall : CallKind(
@@ -780,3 +780,11 @@ internal object ConstraintSystemForks : ResolutionStage() {
}
}
}
internal object TypeParameterAsCallable : ResolutionStage() {
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
if (candidate.symbol is FirTypeParameterSymbol) {
sink.yieldDiagnostic(TypeParameterAsExpression)
}
}
}
@@ -471,10 +471,11 @@ class BodyResolveContext(
// Otherwise, reuse staticsAndCompanion.
val forConstructorHeader = if (typeParameterScope != null) {
towerDataContext
.addNonLocalScope(typeParameterScope)
.addNonLocalTowerDataElements(towerElementsForClass.superClassesStaticsAndCompanionReceivers)
.run { towerElementsForClass.companionReceiver?.let { addReceiver(null, it) } ?: this }
.addNonLocalScopesIfNotNull(towerElementsForClass.companionStaticScope, towerElementsForClass.staticScope)
// Note: scopes here are in reverse order, so type parameter scope is the most prioritized
.addNonLocalScope(typeParameterScope)
} else {
staticsAndCompanion
}
@@ -146,4 +146,6 @@ class AmbiguousValuesForContextReceiverParameter(
object ResolutionResultOverridesOtherToPreserveCompatibility : ResolutionDiagnostic(RESOLVED)
object AdaptedCallableReferenceIsUsedWithReflection : ResolutionDiagnostic(RESOLVED_WITH_ERROR)
object AdaptedCallableReferenceIsUsedWithReflection : ResolutionDiagnostic(RESOLVED_WITH_ERROR)
object TypeParameterAsExpression : ResolutionDiagnostic(INAPPLICABLE)
@@ -15,7 +15,7 @@ fun test() {
fun <T> bar() {
val typeParameter_as_val = <!TYPE_PARAMETER_IS_NOT_AN_EXPRESSION!>T<!>
val typeParameter_as_fun = <!UNRESOLVED_REFERENCE!>T<!>()
val typeParameter_as_fun = <!TYPE_PARAMETER_IS_NOT_AN_EXPRESSION!>T<!>()
baz(<!TYPE_PARAMETER_IS_NOT_AN_EXPRESSION!>T<!>)
baz("$<!TYPE_PARAMETER_IS_NOT_AN_EXPRESSION!>T<!>")
@@ -91,11 +91,11 @@ FILE: companionPropertyAndTypeParameter.kt
super<R|kotlin/Any|>()
}
public final val some: <ERROR TYPE REF: Type parameter test in qualified access> = R|?|
public final val some: <ERROR TYPE REF: Type parameter test in qualified access> = R|?<Type parameter test in qualified access>#|
public get(): <ERROR TYPE REF: Type parameter test in qualified access>
public final fun f(): R|kotlin/Unit| {
lval some: <ERROR TYPE REF: Type parameter test in qualified access> = R|?|
lval some: <ERROR TYPE REF: Type parameter test in qualified access> = R|?<Type parameter test in qualified access>#|
}
}
@@ -1,16 +0,0 @@
// ISSUE: KT-58028, KT-63377
// FIR_DUMP
class Owner<test> {
companion object {
val test = 12
}
inner class I<test> {
val some = <!TYPE_PARAMETER_IS_NOT_AN_EXPRESSION!>test<!>
fun foo() {
val some = <!TYPE_PARAMETER_IS_NOT_AN_EXPRESSION!>test<!>
}
}
}
@@ -1,4 +1,4 @@
FILE: companionPropertyAndTypeParameter2.fir.kt
FILE: companionPropertyAndTypeParameter2.kt
public final class Owner<test> : R|kotlin/Any| {
public constructor<test>(): R|Owner<test>| {
super<R|kotlin/Any|>()
@@ -19,11 +19,11 @@ FILE: companionPropertyAndTypeParameter2.fir.kt
super<R|kotlin/Any|>()
}
public final val some: <ERROR TYPE REF: Type parameter test in qualified access> = R|?|
public get(): <ERROR TYPE REF: Type parameter test in qualified access>
public final val some: R|kotlin/Int| = this@R|/Owner.Companion|.R|/Owner.Companion.test|
public get(): R|kotlin/Int|
public final fun foo(): R|kotlin/Unit| {
lval some: <ERROR TYPE REF: Type parameter test in qualified access> = R|?|
lval some: R|kotlin/Int| = this@R|/Owner.Companion|.R|/Owner.Companion.test|
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ISSUE: KT-58028, KT-63377
// FIR_DUMP
@@ -5,8 +5,8 @@ class OuterClass<OuterParam> {
class OuterParam
fun <NestedParam : OuterParam> foo(t: NestedParam) {
val k: OuterParam = <!INITIALIZER_TYPE_MISMATCH!>t<!>
val l: OuterParam = OuterParam()
val k: OuterParam = t
val l: OuterParam = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>OuterParam()<!>
}
inner class Inner<NestedParam : OuterParam>(t: NestedParam) {
@@ -14,8 +14,8 @@ class OuterClass<OuterParam> {
val l: OuterParam = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>OuterParam()<!>
init {
val m: OuterParam = <!INITIALIZER_TYPE_MISMATCH!>t<!>
val n: OuterParam = OuterParam()
val m: OuterParam = t
val n: OuterParam = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>OuterParam()<!>
}
}
}
@@ -12,8 +12,8 @@ FILE: memberTypeParameterVsNestedClass.fir.kt
}
public final fun <NestedParam : R|OuterParam|> foo(t: R|NestedParam|): R|kotlin/Unit| {
lval k: R|OuterClass.OuterParam| = R|<local>/t|
lval l: R|OuterClass.OuterParam| = R|/OuterClass.OuterParam.OuterParam|()
lval k: R|OuterParam| = R|<local>/t|
lval l: R|OuterParam| = R|/OuterClass.OuterParam.OuterParam<CS errors: /OuterClass.OuterParam.OuterParam>#|()
}
public final inner class Inner<NestedParam : R|OuterParam|, Outer(OuterParam)> : R|kotlin/Any| {
@@ -28,8 +28,8 @@ FILE: memberTypeParameterVsNestedClass.fir.kt
public get(): R|OuterParam|
init {
lval m: R|OuterClass.OuterParam| = R|<local>/t|
lval n: R|OuterClass.OuterParam| = R|/OuterClass.OuterParam.OuterParam|()
lval m: R|OuterParam| = R|<local>/t|
lval n: R|OuterParam| = R|/OuterClass.OuterParam.OuterParam<CS errors: /OuterClass.OuterParam.OuterParam>#|()
}
}
@@ -11,7 +11,7 @@ class Outer {
}
fun <T> bar() {
<!TYPE_PARAMETER_AS_REIFIED!>T::class<!>
T::class
val x: T? = null
val y: T? = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>T()<!>
}
@@ -21,8 +21,8 @@ class Owner<T> {
class T
fun baz() {
<!TYPE_PARAMETER_AS_REIFIED!>T::class<!>
T::class
val x: T? = null
val y: T? = T()
val y: T? = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>T()<!>
}
}
@@ -12,13 +12,13 @@ FILE: memberTypeParameterVsNestedClass2.fir.kt
}
public final inline fun <reified T> foo(): R|kotlin/Unit| {
<getClass>(R|T|)
<getClass>(Q|Outer.T|)
lval x: R|T?| = Null(null)
lval y: R|T?| = R|/Outer.T.T<CS errors: /Outer.T.T>#|()
}
public final fun <T> bar(): R|kotlin/Unit| {
<getClass>(R|?|)
<getClass>(Q|Outer.T|)
lval x: R|T?| = Null(null)
lval y: R|T?| = R|/Outer.T.T<CS errors: /Outer.T.T>#|()
}
@@ -37,9 +37,9 @@ FILE: memberTypeParameterVsNestedClass2.fir.kt
}
public final fun baz(): R|kotlin/Unit| {
<getClass>(R|?|)
lval x: R|Owner.T?| = Null(null)
lval y: R|Owner.T?| = R|/Owner.T.T|()
<getClass>(Q|Owner.T|)
lval x: R|T?| = Null(null)
lval y: R|T?| = R|/Owner.T.T<CS errors: /Owner.T.T>#|()
}
}
@@ -31,23 +31,23 @@ class OuterClassWithClass<OuterParam> {
}
val k = ::OuterParam
val l = <!CALLABLE_REFERENCE_LHS_NOT_A_CLASS!>OuterParam::<!UNRESOLVED_REFERENCE!>foo<!><!>
val l = OuterParam::foo
val m = OuterParam()::foo
fun foo() {
val k = ::OuterParam
val l = <!CALLABLE_REFERENCE_LHS_NOT_A_CLASS!>OuterParam::<!UNRESOLVED_REFERENCE!>foo<!><!>
val l = OuterParam::foo
val m = OuterParam()::foo
}
inner class Inner<NestedParam : OuterParam>(t: NestedParam) {
val k = ::OuterParam
val l = <!CALLABLE_REFERENCE_LHS_NOT_A_CLASS!>OuterParam::<!UNRESOLVED_REFERENCE!>foo<!><!>
val l = OuterParam::foo
val m = OuterParam()::foo
init {
val k = ::OuterParam
val l = <!CALLABLE_REFERENCE_LHS_NOT_A_CLASS!>OuterParam::<!UNRESOLVED_REFERENCE!>foo<!><!>
val l = OuterParam::foo
val m = OuterParam()::foo
}
}
@@ -62,15 +62,15 @@ FILE: memberTypeParameterVsNestedClassReference.fir.kt
public final val k: R|kotlin/reflect/KFunction0<OuterClassWithClass.OuterParam>| = ::R|/OuterClassWithClass.OuterParam.OuterParam|
public get(): R|kotlin/reflect/KFunction0<OuterClassWithClass.OuterParam>|
public final val l: <ERROR TYPE REF: Unresolved reference: foo> = R|?|::<Unresolved reference: foo>#
public get(): <ERROR TYPE REF: Unresolved reference: foo>
public final val l: R|kotlin/reflect/KFunction1<OuterClassWithClass.OuterParam, kotlin/Unit>| = Q|OuterClassWithClass.OuterParam|::R|/OuterClassWithClass.OuterParam.foo|
public get(): R|kotlin/reflect/KFunction1<OuterClassWithClass.OuterParam, kotlin/Unit>|
public final val m: R|kotlin/reflect/KFunction0<kotlin/Unit>| = R|/OuterClassWithClass.OuterParam.OuterParam|()::R|/OuterClassWithClass.OuterParam.foo|
public get(): R|kotlin/reflect/KFunction0<kotlin/Unit>|
public final fun foo(): R|kotlin/Unit| {
lval k: R|kotlin/reflect/KFunction0<OuterClassWithClass.OuterParam>| = ::R|/OuterClassWithClass.OuterParam.OuterParam|
lval l: <ERROR TYPE REF: Unresolved reference: foo> = R|?|::<Unresolved reference: foo>#
lval l: R|kotlin/reflect/KFunction1<OuterClassWithClass.OuterParam, kotlin/Unit>| = Q|OuterClassWithClass.OuterParam|::R|/OuterClassWithClass.OuterParam.foo|
lval m: R|kotlin/reflect/KFunction0<kotlin/Unit>| = R|/OuterClassWithClass.OuterParam.OuterParam|()::R|/OuterClassWithClass.OuterParam.foo|
}
@@ -82,15 +82,15 @@ FILE: memberTypeParameterVsNestedClassReference.fir.kt
public final val k: R|kotlin/reflect/KFunction0<OuterClassWithClass.OuterParam>| = ::R|/OuterClassWithClass.OuterParam.OuterParam|
public get(): R|kotlin/reflect/KFunction0<OuterClassWithClass.OuterParam>|
public final val l: <ERROR TYPE REF: Unresolved reference: foo> = R|?|::<Unresolved reference: foo>#
public get(): <ERROR TYPE REF: Unresolved reference: foo>
public final val l: R|kotlin/reflect/KFunction1<OuterClassWithClass.OuterParam, kotlin/Unit>| = Q|OuterClassWithClass.OuterParam|::R|/OuterClassWithClass.OuterParam.foo|
public get(): R|kotlin/reflect/KFunction1<OuterClassWithClass.OuterParam, kotlin/Unit>|
public final val m: R|kotlin/reflect/KFunction0<kotlin/Unit>| = R|/OuterClassWithClass.OuterParam.OuterParam|()::R|/OuterClassWithClass.OuterParam.foo|
public get(): R|kotlin/reflect/KFunction0<kotlin/Unit>|
init {
lval k: R|kotlin/reflect/KFunction0<OuterClassWithClass.OuterParam>| = ::R|/OuterClassWithClass.OuterParam.OuterParam|
lval l: <ERROR TYPE REF: Unresolved reference: foo> = R|?|::<Unresolved reference: foo>#
lval l: R|kotlin/reflect/KFunction1<OuterClassWithClass.OuterParam, kotlin/Unit>| = Q|OuterClassWithClass.OuterParam|::R|/OuterClassWithClass.OuterParam.foo|
lval m: R|kotlin/reflect/KFunction0<kotlin/Unit>| = R|/OuterClassWithClass.OuterParam.OuterParam|()::R|/OuterClassWithClass.OuterParam.foo|
}