K2: Fix false-positive on delegated constructor call of outer class
See callingOuterGenericClassConstructorWithSelfTypes.kt
Previously, for A<B>(""), we used substituted constructor
where `X` was substituted with `B` (or `A<X>.B`).
But when resolving the call for constructor, we use `X`
as a type variable of the call, thus in some positions
we used `X` as TV (Xv in the comments) and somewhere `X` as a type
parameter, thus leading to contradictions (see clarifying comment).
The idea of the fix is simply repeating of the regular (not delegated)
constructor call resolution:
- We substitute only type parameters of outer class
- All the declared parameters of the callee are being checked
through regular resolution & inference mechanisms.
NB: Diagnostic only being reported on arguments because there
when we add `String <: Any` constraint it fails due to existing
contradiction in the CS.
Without the argument/parameter the error is just being lost, but that's
a different story (seeKT-65224).
^KT-64841 Fixed
This commit is contained in:
committed by
Space Team
parent
81d559ad7f
commit
7b82ca8b6f
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeRawScopeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.scopes.*
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirScopeWithCallableCopyReturnTypeUpdater
|
||||
@@ -57,9 +58,23 @@ fun FirSmartCastExpression.smartcastScope(
|
||||
fun ConeClassLikeType.delegatingConstructorScope(
|
||||
useSiteSession: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
derivedClassLookupTag: ConeClassLikeLookupTag
|
||||
derivedClassLookupTag: ConeClassLikeLookupTag,
|
||||
outerType: ConeClassLikeType?
|
||||
): FirTypeScope? {
|
||||
return classScope(useSiteSession, scopeSession, FirResolvePhase.DECLARATIONS, derivedClassLookupTag)
|
||||
val fir = fullyExpandedType(useSiteSession).lookupTag.toSymbol(useSiteSession)?.fir as? FirClass ?: return null
|
||||
|
||||
val substitutor = when {
|
||||
outerType != null -> {
|
||||
val outerFir = outerType.lookupTag.toSymbol(useSiteSession)?.fir as? FirClass ?: return null
|
||||
substitutorByMap(
|
||||
createSubstitutionForScope(outerFir.typeParameters, outerType, useSiteSession),
|
||||
useSiteSession,
|
||||
)
|
||||
}
|
||||
else -> ConeSubstitutor.Empty
|
||||
}
|
||||
|
||||
return fir.scopeForClass(substitutor, useSiteSession, scopeSession, derivedClassLookupTag, FirResolvePhase.DECLARATIONS)
|
||||
}
|
||||
|
||||
fun ConeKotlinType.scope(
|
||||
|
||||
+3
-2
@@ -95,8 +95,9 @@ class FirTowerResolver(
|
||||
context: ResolutionContext
|
||||
): CandidateCollector {
|
||||
val outerType = components.outerClassManager.outerType(constructedType)
|
||||
val scope = constructedType.delegatingConstructorScope(components.session, components.scopeSession, derivedClassLookupTag)
|
||||
?: return collector
|
||||
val scope =
|
||||
constructedType.delegatingConstructorScope(components.session, components.scopeSession, derivedClassLookupTag, outerType)
|
||||
?: return collector
|
||||
|
||||
val dispatchReceiver =
|
||||
if (outerType != null)
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
open class Test<T1, T2>(val map1 : Map<T1, T2>, val map2 : Map<T2, T1>) {
|
||||
open val inverse: Test<T2, T1> = object : Test<T2, T1>(<!ARGUMENT_TYPE_MISMATCH!>map2<!>, <!ARGUMENT_TYPE_MISMATCH!>map1<!>) {
|
||||
override val inverse: Test<T1, T2>
|
||||
get() = this@Test
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
open class Test<T1, T2>(val map1 : Map<T1, T2>, val map2 : Map<T2, T1>) {
|
||||
open val inverse: Test<T2, T1> = object : Test<T2, T1>(map2, map1) {
|
||||
override val inverse: Test<T1, T2>
|
||||
|
||||
Vendored
-21
@@ -1,21 +0,0 @@
|
||||
// ISSUE: KT-64841
|
||||
|
||||
open class A<X : A<X>>(a: Any?) {
|
||||
// Constraints while resolving super constructor call
|
||||
//
|
||||
// The signature of constructor comes substituted
|
||||
// constructor<X : R|A<A.B<X>>|>(a: R|kotlin/Any?|): R|A<A.B<X>>|
|
||||
//
|
||||
// Xv <: A<A<Xv>.B> (from type parameter bounds, actually it's the incorrect place)
|
||||
//
|
||||
// Xv := A<X>.B (from explicit type argument of constructor call)
|
||||
// A<X>.B> <: A<A<Xv>.B>
|
||||
// A<A<X>.B> <: A<A<Xv>.B>
|
||||
// Xv := X
|
||||
// X != A<X>.B -> FAIL
|
||||
inner class B : A<B>(<!ARGUMENT_TYPE_MISMATCH!>""<!>) {
|
||||
fun foo() {
|
||||
A<B>("")
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// ISSUE: KT-64841
|
||||
|
||||
open class A<X : A<X>>(a: Any?) {
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
// ISSUE: KT-64841
|
||||
abstract class A<X, Y : A<X, Y>>
|
||||
|
||||
abstract class B<X, T, Y : B<X, T, Y>>(delegate: A<X, *>) : A<X, Y>() {
|
||||
inner class C<R> : B<X, R, C<R>>(<!ARGUMENT_TYPE_MISMATCH!>this<!>)
|
||||
}
|
||||
compiler/testData/diagnostics/tests/inner/callingOuterGenericClassConstructorWithSelfTypesInitial.kt
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// ISSUE: KT-64841
|
||||
abstract class A<X, Y : A<X, Y>>
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -11,10 +11,10 @@ public class A<E> {
|
||||
// TODO: It's effectively impossible to perform super call to such constructor
|
||||
// if there is not enough information to infer corresponding arguments
|
||||
// May be we could add some special syntax for such arguments
|
||||
class B1(x: List<String>) : <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>A<CharSequence><!>("", x)
|
||||
class B1(x: List<String>) : <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>A<CharSequence><!>("", x)
|
||||
class B2(x: List<Int>) : A<CharSequence>("", <!ARGUMENT_TYPE_MISMATCH!>x<!>)
|
||||
|
||||
class C : A<CharSequence> {
|
||||
constructor(x: List<String>) : <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>super<!>("", x)
|
||||
constructor(x: List<String>) : <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>super<!>("", x)
|
||||
constructor(x: List<Int>, y: Int) : super("", <!ARGUMENT_TYPE_MISMATCH!>x<!>)
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
open class Foo<T>(val item: T)
|
||||
|
||||
class Bar(str: String) : <!DEBUG_INFO_CALLABLE_OWNER("Foo.Foo in Bar")!>Foo<String>(str)<!>
|
||||
class Bar(str: String) : <!DEBUG_INFO_CALLABLE_OWNER("Foo.Foo in Foo")!>Foo<String>(str)<!>
|
||||
|
||||
Reference in New Issue
Block a user