[FIR] Match type in super<type> access with actual supertypes of class
This commit is contained in:
+12
-12
@@ -23,11 +23,11 @@ FILE: qualifiedSupertypeExtendedByOtherSupertype.kt
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final fun test(): R|kotlin/Unit| {
|
public final fun test(): R|kotlin/Unit| {
|
||||||
this@R|/Test|.super<R|IBase<T>|>.R|/IBase.foo|()
|
this@R|/Test|.super<R|IBase<kotlin/String>|>.R|/IBase.foo|()
|
||||||
this@R|/Test|.super<R|IBase<T>|>.R|/IBase.bar|()
|
this@R|/Test|.super<R|IBase<kotlin/String>|>.R|/IBase.bar|()
|
||||||
this@R|/Test|.super<R|IDerived<T>|>.R|/IDerived.foo|()
|
this@R|/Test|.super<R|IDerived<kotlin/String>|>.R|/IDerived.foo|()
|
||||||
this@R|/Test|.super<R|IDerived<T>|>.R|/IBase.bar|()
|
this@R|/Test|.super<R|IDerived<kotlin/String>|>.R|/IBase.bar|()
|
||||||
this@R|/Test|.super<R|IDerived<T>|>.R|/IDerived.qux|()
|
this@R|/Test|.super<R|IDerived<kotlin/String>|>.R|/IDerived.qux|()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -37,13 +37,13 @@ FILE: qualifiedSupertypeExtendedByOtherSupertype.kt
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final fun test(): R|kotlin/Unit| {
|
public final fun test(): R|kotlin/Unit| {
|
||||||
this@R|/Test2|.super<R|IBase<T>|>.R|/IBase.foo|()
|
this@R|/Test2|.super<R|IBase<kotlin/String>|>.R|/IBase.foo|()
|
||||||
this@R|/Test2|.super<R|IBase<T>|>.R|/IBase.bar|()
|
this@R|/Test2|.super<R|IBase<kotlin/String>|>.R|/IBase.bar|()
|
||||||
this@R|/Test2|.super<R|AliasedIBase|>.R|/IBase.foo|()
|
this@R|/Test2|.super<R|IBase<kotlin/String>|>.R|/IBase.foo|()
|
||||||
this@R|/Test2|.super<R|AliasedIBase|>.R|/IBase.bar|()
|
this@R|/Test2|.super<R|IBase<kotlin/String>|>.R|/IBase.bar|()
|
||||||
this@R|/Test2|.super<R|IDerived<T>|>.R|/IDerived.foo|()
|
this@R|/Test2|.super<R|IDerived<kotlin/String>|>.R|/IDerived.foo|()
|
||||||
this@R|/Test2|.super<R|IDerived<T>|>.R|/IBase.bar|()
|
this@R|/Test2|.super<R|IDerived<kotlin/String>|>.R|/IBase.bar|()
|
||||||
this@R|/Test2|.super<R|IDerived<T>|>.R|/IDerived.qux|()
|
this@R|/Test2|.super<R|IDerived<kotlin/String>|>.R|/IDerived.qux|()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.types
|
package org.jetbrains.kotlin.fir.types
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
import org.jetbrains.kotlin.utils.SmartSet
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
@@ -34,3 +35,9 @@ private fun ConeKotlinType.contains(predicate: (ConeKotlinType) -> Boolean, visi
|
|||||||
else -> typeArguments.any { it is ConeKotlinTypeProjection && it.type.contains(predicate, visited) }
|
else -> typeArguments.any { it is ConeKotlinTypeProjection && it.type.contains(predicate, visited) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ConeClassLikeType.withArguments(typeArguments: Array<out ConeTypeProjection>): ConeClassLikeType = when (this) {
|
||||||
|
is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, typeArguments, isNullable, attributes)
|
||||||
|
is ConeClassErrorType -> this
|
||||||
|
else -> error("Unknown cone type: ${this::class}")
|
||||||
|
}
|
||||||
+35
-2
@@ -139,8 +139,41 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
|||||||
superReferenceContainer.resultType = superTypeRef
|
superReferenceContainer.resultType = superTypeRef
|
||||||
}
|
}
|
||||||
!is FirImplicitTypeRef -> {
|
!is FirImplicitTypeRef -> {
|
||||||
superReference.transformChildren(transformer, ResolutionMode.ContextIndependent)
|
components.typeResolverTransformer.withAllowedBareTypes {
|
||||||
superReferenceContainer.resultType = superReference.superTypeRef
|
superReference.transformChildren(transformer, ResolutionMode.ContextIndependent)
|
||||||
|
}
|
||||||
|
|
||||||
|
val actualSuperType = (superReference.superTypeRef.coneType as? ConeClassLikeType)
|
||||||
|
?.fullyExpandedType(session)?.let { superType ->
|
||||||
|
val classId = superType.lookupTag.classId
|
||||||
|
val superTypeRefs = implicitReceiver?.boundSymbol?.phasedFir?.superTypeRefs
|
||||||
|
val correspondingDeclaredSuperType = superTypeRefs?.firstOrNull {
|
||||||
|
it.coneType.fullyExpandedType(session).classId == classId
|
||||||
|
}?.coneTypeSafe<ConeClassLikeType>()?.fullyExpandedType(session) ?: return@let superType
|
||||||
|
|
||||||
|
if (superType.typeArguments.isEmpty() && correspondingDeclaredSuperType.typeArguments.isNotEmpty()) {
|
||||||
|
superType.withArguments(correspondingDeclaredSuperType.typeArguments)
|
||||||
|
} else {
|
||||||
|
superType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* See tests:
|
||||||
|
* DiagnosticsTestGenerated$Tests$ThisAndSuper.testGenericQualifiedSuperOverridden
|
||||||
|
* DiagnosticsTestGenerated$Tests$ThisAndSuper.testQualifiedSuperOverridden
|
||||||
|
*/
|
||||||
|
val actualSuperTypeRef = actualSuperType?.let {
|
||||||
|
buildResolvedTypeRef {
|
||||||
|
source = superTypeRef.source
|
||||||
|
type = it
|
||||||
|
}
|
||||||
|
} ?: buildErrorTypeRef {
|
||||||
|
source = superTypeRef.source
|
||||||
|
diagnostic = ConeSimpleDiagnostic("Not a super type", DiagnosticKind.Other)
|
||||||
|
}
|
||||||
|
superReference.replaceSuperTypeRef(actualSuperTypeRef)
|
||||||
|
|
||||||
|
superReferenceContainer.resultType = actualSuperTypeRef
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val superTypeRefs = implicitReceiver?.boundSymbol?.phasedFir?.superTypeRefs
|
val superTypeRefs = implicitReceiver?.boundSymbol?.phasedFir?.superTypeRefs
|
||||||
|
|||||||
+1
-1
@@ -14,6 +14,6 @@ class Derived : BaseDerived2<Int>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
Derived().foo() checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Outer<Int, String>.Inner<Char>>() }
|
Derived().foo() checkType { _<Outer<Int, String>.Inner<Char>>() }
|
||||||
Derived().baz() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Map<Char, Int>>() }
|
Derived().baz() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Map<Char, Int>>() }
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-18
@@ -1,18 +0,0 @@
|
|||||||
// !CHECK_TYPE
|
|
||||||
open class Outer<E> {
|
|
||||||
inner open class Inner<F> {
|
|
||||||
inner class Inner2<D> {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DerivedOuter : Outer<String>() {
|
|
||||||
inner class DerivedInner : Inner<Int>() {
|
|
||||||
fun foo(): Inner2<Char> = null!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun foo() {
|
|
||||||
DerivedOuter().DerivedInner().foo() checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Outer<String>.Inner<Int>.Inner2<Char>>() }
|
|
||||||
}
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !CHECK_TYPE
|
// !CHECK_TYPE
|
||||||
open class Outer<E> {
|
open class Outer<E> {
|
||||||
inner open class Inner<F> {
|
inner open class Inner<F> {
|
||||||
|
|||||||
+3
-3
@@ -29,9 +29,9 @@ fun main() {
|
|||||||
checkSubtype<Outer<out CharSequence>.Inner>(outer.bar())
|
checkSubtype<Outer<out CharSequence>.Inner>(outer.bar())
|
||||||
checkSubtype<Outer<out CharSequence>.Inner>(outer.Inner())
|
checkSubtype<Outer<out CharSequence>.Inner>(outer.Inner())
|
||||||
|
|
||||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(outer.bar())
|
outer.set(outer.bar())
|
||||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(outer.Inner())
|
outer.set(outer.Inner())
|
||||||
|
|
||||||
val x: Outer<String>.Inner = factoryString()
|
val x: Outer<String>.Inner = factoryString()
|
||||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(x)
|
outer.set(x)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ class A<E>() : C(), T {
|
|||||||
super<C>.bar()
|
super<C>.bar()
|
||||||
super<T>@A.foo()
|
super<T>@A.foo()
|
||||||
super<C>@A.bar()
|
super<C>@A.bar()
|
||||||
super<E>.<!UNRESOLVED_REFERENCE!>bar<!>()
|
super<<!OTHER_ERROR, OTHER_ERROR!>E<!>>.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||||
super<E>@A.<!UNRESOLVED_REFERENCE!>bar<!>()
|
super<<!OTHER_ERROR, OTHER_ERROR!>E<!>>@A.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||||
<!NOT_A_SUPERTYPE!>super<Int><!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
<!NOT_A_SUPERTYPE!>super<Int><!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||||
super<<!SYNTAX!><!>>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
super<<!SYNTAX!><!>>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||||
<!NOT_A_SUPERTYPE!>super<() -> Unit><!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
<!NOT_A_SUPERTYPE!>super<() -> Unit><!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||||
|
|||||||
+2
-2
@@ -23,7 +23,7 @@ class TestSuperForBase : B() {
|
|||||||
super<Base>.foo()
|
super<Base>.foo()
|
||||||
super<B>.foo()
|
super<B>.foo()
|
||||||
super<MyBase>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
super<MyBase>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||||
super<U>.foo()
|
<!NOT_A_SUPERTYPE!>super<U><!>.foo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +36,6 @@ class TestSuperForGenericBase<T> : GB<T>() {
|
|||||||
super<GB>.foo()
|
super<GB>.foo()
|
||||||
super<MyBase>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
super<MyBase>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||||
super<MyBaseInt>.<!UNRESOLVED_REFERENCE!>foo<!>() // Type arguments don't matter here
|
super<MyBaseInt>.<!UNRESOLVED_REFERENCE!>foo<!>() // Type arguments don't matter here
|
||||||
super<U>.foo()
|
<!NOT_A_SUPERTYPE!>super<U><!>.foo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user