From d40777c28f1134161d274bf39f2f91f0f9b8c52b Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 19 Feb 2021 14:01:44 +0300 Subject: [PATCH] [FIR] Fix calculating arguments of bare type with intersection type as base --- ...TouchedTilContractsPhaseTestGenerated.java | 5 ++ .../resolve/types/castToBareType.fir.txt | 21 ++++++++ .../testData/resolve/types/castToBareType.kt | 17 +++++++ .../runners/FirDiagnosticTestGenerated.java | 6 +++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 +++ .../FirExpressionsResolveTransformer.kt | 48 ++++++++++++------- 6 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/types/castToBareType.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/types/castToBareType.kt diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index 5bd3d252ab9..641a17bb81e 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -3256,6 +3256,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract public void testCapturedParametersOfInnerClasses() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/types/capturedParametersOfInnerClasses.kt"); } + + @TestMetadata("castToBareType.kt") + public void testCastToBareType() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/types/castToBareType.kt"); + } } @TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility") diff --git a/compiler/fir/analysis-tests/testData/resolve/types/castToBareType.fir.txt b/compiler/fir/analysis-tests/testData/resolve/types/castToBareType.fir.txt new file mode 100644 index 00000000000..4497e5bd014 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/types/castToBareType.fir.txt @@ -0,0 +1,21 @@ +FILE: castToBareType.kt + public abstract interface FirDeclaration : R|kotlin/Any| { + } + public abstract interface FirSymbolOwner|> : R|kotlin/Any| { + public abstract val symbol: R|AbstractFirBasedSymbol| + public get(): R|AbstractFirBasedSymbol| + + } + public abstract interface FirFunction|> : R|FirSymbolOwner|, R|FirDeclaration| { + } + public abstract interface AbstractFirBasedSymbol|, R|FirDeclaration|> : R|kotlin/Any| { + public abstract val fir: R|E| + public get(): R|E| + + } + public final fun foo(firAdaptee: R|FirFunction<*>|): R|kotlin/Unit| { + } + public final fun test(symbol: R|AbstractFirBasedSymbol<*>|): R|kotlin/Unit| { + lval firAdaptee: R|FirFunction & FirDeclaration)> & FirDeclaration)> & FirDeclaration)> & FirDeclaration)>| = (R|/symbol|.R|SubstitutionOverride| as R|FirFunction & FirDeclaration)> & FirDeclaration)> & FirDeclaration)> & FirDeclaration)>|) + R|/foo|(R|/firAdaptee|) + } diff --git a/compiler/fir/analysis-tests/testData/resolve/types/castToBareType.kt b/compiler/fir/analysis-tests/testData/resolve/types/castToBareType.kt new file mode 100644 index 00000000000..eed7c886290 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/types/castToBareType.kt @@ -0,0 +1,17 @@ +interface FirDeclaration + +interface FirSymbolOwner> { + val symbol: AbstractFirBasedSymbol +} +interface FirFunction> : FirSymbolOwner, FirDeclaration + +interface AbstractFirBasedSymbol where E : FirSymbolOwner, E : FirDeclaration { + val fir: E +} + +fun foo(firAdaptee: FirFunction<*>) {} + +fun test(symbol: AbstractFirBasedSymbol<*>) { + val firAdaptee = symbol.fir as FirFunction + foo(firAdaptee) +} diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index e8ed54adf0d..c850c871cd3 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -3630,6 +3630,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { public void testCapturedParametersOfInnerClasses() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/types/capturedParametersOfInnerClasses.kt"); } + + @Test + @TestMetadata("castToBareType.kt") + public void testCastToBareType() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/types/castToBareType.kt"); + } } @Nested diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index dfb0ad3938f..d4bb412ad93 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -3681,6 +3681,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos public void testCapturedParametersOfInnerClasses() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/types/capturedParametersOfInnerClasses.kt"); } + + @Test + @TestMetadata("castToBareType.kt") + public void testCastToBareType() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/types/castToBareType.kt"); + } } @Nested 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 ed23f1d3193..cc802d6b172 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 @@ -499,25 +499,41 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform val firClass = type.lookupTag.toSymbol(session)?.fir ?: return this if (firClass !is FirTypeParameterRefsOwner || firClass.typeParameters.isEmpty()) return this - val baseType = argument.typeRef.coneTypeSafe()?.lowerBoundIfFlexible()?.fullyExpandedType(session) ?: return this - if (baseType !is ConeClassLikeType) return this - val baseFirClass = baseType.lookupTag.toSymbol(session)?.fir ?: return this - - val newArguments = if (AbstractTypeChecker.isSubtypeOfClass( - session.typeContext.newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true), baseType.lookupTag, type.lookupTag)) { - // If actual type of declaration is more specific than bare type then we should just find - // corresponding supertype with proper arguments - with(session.typeContext) { - val superType = baseType.fastCorrespondingSupertypes(type.lookupTag)?.firstOrNull() as? ConeKotlinType? - superType?.typeArguments - } - } else { - type.inheritTypeArguments(baseFirClass, baseType.typeArguments) - } ?: return buildErrorTypeRef { + val originalType = argument.typeRef.coneTypeSafe() ?: return this + val newType = computeRepresentativeTypeForBareType(type, originalType) ?: return buildErrorTypeRef { source = this@withTypeArgumentsForBareType.source diagnostic = ConeWrongNumberOfTypeArgumentsError(firClass.typeParameters.size, firClass.symbol) } - return if (newArguments.isEmpty()) this else withReplacedConeType(type.withArguments(newArguments)) + return if (newType.typeArguments.isEmpty()) this else withReplacedConeType(newType) + } + + private fun computeRepresentativeTypeForBareType(type: ConeClassLikeType, originalType: ConeKotlinType): ConeKotlinType? { + @Suppress("NAME_SHADOWING") + val originalType = originalType.lowerBoundIfFlexible().fullyExpandedType(session) + if (originalType is ConeIntersectionType) { + val candidatesFromIntersectedTypes = originalType.intersectedTypes.mapNotNull { computeRepresentativeTypeForBareType(type, it) } + candidatesFromIntersectedTypes.firstOrNull { it.typeArguments.isNotEmpty() }?.let { return it } + return candidatesFromIntersectedTypes.firstOrNull() + } + if (originalType !is ConeClassLikeType) return type + val baseFirClass = originalType.lookupTag.toSymbol(session)?.fir ?: return type + val isSubtype = AbstractTypeChecker.isSubtypeOfClass( + session.typeContext.newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true), + originalType.lookupTag, + type.lookupTag + ) + val newArguments = if (isSubtype) { + // If actual type of declaration is more specific than bare type then we should just find + // corresponding supertype with proper arguments + with(session.typeContext) { + val superType = originalType.fastCorrespondingSupertypes(type.lookupTag)?.firstOrNull() as? ConeKotlinType? + superType?.typeArguments + } + } else { + type.inheritTypeArguments(baseFirClass, originalType.typeArguments) + } ?: return null + if (newArguments.isEmpty()) return type + return type.withArguments(newArguments) } override fun transformTypeOperatorCall(