From cedd1c133ef6bbfe47fc1bbcf1f5ecd2e5552c05 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 15 Jul 2020 12:17:44 +0300 Subject: [PATCH] [FIR] Match type in `super` access with actual supertypes of class --- ...ifiedSupertypeExtendedByOtherSupertype.txt | 24 ++++++------ .../kotlin/fir/types/ConeTypeUtils.kt | 7 ++++ .../FirExpressionsResolveTransformer.kt | 37 ++++++++++++++++++- .../fromSuperClassesTransitive.fir.kt | 2 +- .../implicitArguments/secondLevelDepth.fir.kt | 18 --------- .../implicitArguments/secondLevelDepth.kt | 1 + .../innerClasses/simpleOutUseSite.fir.kt | 6 +-- .../tests/thisAndSuper/Super.fir.kt | 4 +- .../typeAliasAsSuperQualifier.fir.kt | 4 +- 9 files changed, 63 insertions(+), 40 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/secondLevelDepth.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/qualifiedSupertypeExtendedByOtherSupertype.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/qualifiedSupertypeExtendedByOtherSupertype.txt index b5c7c701130..fb0928ff993 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/qualifiedSupertypeExtendedByOtherSupertype.txt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/qualifiedSupertypeExtendedByOtherSupertype.txt @@ -23,11 +23,11 @@ FILE: qualifiedSupertypeExtendedByOtherSupertype.kt } public final fun test(): R|kotlin/Unit| { - this@R|/Test|.super|>.R|/IBase.foo|() - this@R|/Test|.super|>.R|/IBase.bar|() - this@R|/Test|.super|>.R|/IDerived.foo|() - this@R|/Test|.super|>.R|/IBase.bar|() - this@R|/Test|.super|>.R|/IDerived.qux|() + this@R|/Test|.super|>.R|/IBase.foo|() + this@R|/Test|.super|>.R|/IBase.bar|() + this@R|/Test|.super|>.R|/IDerived.foo|() + this@R|/Test|.super|>.R|/IBase.bar|() + this@R|/Test|.super|>.R|/IDerived.qux|() } } @@ -37,13 +37,13 @@ FILE: qualifiedSupertypeExtendedByOtherSupertype.kt } public final fun test(): R|kotlin/Unit| { - this@R|/Test2|.super|>.R|/IBase.foo|() - this@R|/Test2|.super|>.R|/IBase.bar|() - this@R|/Test2|.super.R|/IBase.foo|() - this@R|/Test2|.super.R|/IBase.bar|() - this@R|/Test2|.super|>.R|/IDerived.foo|() - this@R|/Test2|.super|>.R|/IBase.bar|() - this@R|/Test2|.super|>.R|/IDerived.qux|() + this@R|/Test2|.super|>.R|/IBase.foo|() + this@R|/Test2|.super|>.R|/IBase.bar|() + this@R|/Test2|.super|>.R|/IBase.foo|() + this@R|/Test2|.super|>.R|/IBase.bar|() + this@R|/Test2|.super|>.R|/IDerived.foo|() + this@R|/Test2|.super|>.R|/IBase.bar|() + this@R|/Test2|.super|>.R|/IDerived.qux|() } } diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt index 5f0d909dc58..25b13e92813 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.types +import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -33,4 +34,10 @@ private fun ConeKotlinType.contains(predicate: (ConeKotlinType) -> Boolean, visi is ConeIntersectionType -> intersectedTypes.any { it.contains(predicate, visited) } else -> typeArguments.any { it is ConeKotlinTypeProjection && it.type.contains(predicate, visited) } } +} + +fun ConeClassLikeType.withArguments(typeArguments: Array): ConeClassLikeType = when (this) { + is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, typeArguments, isNullable, attributes) + is ConeClassErrorType -> this + else -> error("Unknown cone type: ${this::class}") } \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 205399c319f..33dc75a28ad 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -139,8 +139,41 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform superReferenceContainer.resultType = superTypeRef } !is FirImplicitTypeRef -> { - superReference.transformChildren(transformer, ResolutionMode.ContextIndependent) - superReferenceContainer.resultType = superReference.superTypeRef + components.typeResolverTransformer.withAllowedBareTypes { + 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()?.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 -> { val superTypeRefs = implicitReceiver?.boundSymbol?.phasedFir?.superTypeRefs diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesTransitive.fir.kt b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesTransitive.fir.kt index 44702eb782f..2cbb09b91cd 100644 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesTransitive.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesTransitive.fir.kt @@ -14,6 +14,6 @@ class Derived : BaseDerived2() { } fun foo() { - Derived().foo() checkType { _.Inner>() } + Derived().foo() checkType { _.Inner>() } Derived().baz() checkType { _>() } } diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/secondLevelDepth.fir.kt b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/secondLevelDepth.fir.kt deleted file mode 100644 index 289136efa64..00000000000 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/secondLevelDepth.fir.kt +++ /dev/null @@ -1,18 +0,0 @@ -// !CHECK_TYPE -open class Outer { - inner open class Inner { - inner class Inner2 { - - } - } -} - -class DerivedOuter : Outer() { - inner class DerivedInner : Inner() { - fun foo(): Inner2 = null!! - } -} - -fun foo() { - DerivedOuter().DerivedInner().foo() checkType { _.Inner.Inner2>() } -} diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/secondLevelDepth.kt b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/secondLevelDepth.kt index 0f232098c81..3c692e5f483 100644 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/secondLevelDepth.kt +++ b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/secondLevelDepth.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !CHECK_TYPE open class Outer { inner open class Inner { diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/simpleOutUseSite.fir.kt b/compiler/testData/diagnostics/tests/generics/innerClasses/simpleOutUseSite.fir.kt index c16e0722bb5..b894c10f9f9 100644 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/simpleOutUseSite.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/innerClasses/simpleOutUseSite.fir.kt @@ -29,9 +29,9 @@ fun main() { checkSubtype.Inner>(outer.bar()) checkSubtype.Inner>(outer.Inner()) - outer.set(outer.bar()) - outer.set(outer.Inner()) + outer.set(outer.bar()) + outer.set(outer.Inner()) val x: Outer.Inner = factoryString() - outer.set(x) + outer.set(x) } diff --git a/compiler/testData/diagnostics/tests/thisAndSuper/Super.fir.kt b/compiler/testData/diagnostics/tests/thisAndSuper/Super.fir.kt index 02e40b4f88d..f4a59c31889 100644 --- a/compiler/testData/diagnostics/tests/thisAndSuper/Super.fir.kt +++ b/compiler/testData/diagnostics/tests/thisAndSuper/Super.fir.kt @@ -17,8 +17,8 @@ class A() : C(), T { super.bar() super@A.foo() super@A.bar() - super.bar() - super@A.bar() + super<E>.bar() + super<E>@A.bar() super.foo() super<>.foo() super<() -> Unit>.foo() diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasAsSuperQualifier.fir.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasAsSuperQualifier.fir.kt index 39534bbba1b..e93c650a22e 100644 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasAsSuperQualifier.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasAsSuperQualifier.fir.kt @@ -23,7 +23,7 @@ class TestSuperForBase : B() { super.foo() super.foo() super.foo() - super.foo() + super.foo() } } @@ -36,6 +36,6 @@ class TestSuperForGenericBase : GB() { super.foo() super.foo() super.foo() // Type arguments don't matter here - super.foo() + super.foo() } } \ No newline at end of file