[FIR] Fix calculating arguments of bare type with intersection type as base
This commit is contained in:
committed by
TeamCityServer
parent
56f9e3360f
commit
d40777c28f
+5
@@ -3256,6 +3256,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
|||||||
public void testCapturedParametersOfInnerClasses() throws Exception {
|
public void testCapturedParametersOfInnerClasses() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/types/capturedParametersOfInnerClasses.kt");
|
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")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
FILE: castToBareType.kt
|
||||||
|
public abstract interface FirDeclaration : R|kotlin/Any| {
|
||||||
|
}
|
||||||
|
public abstract interface FirSymbolOwner<E : R|FirSymbolOwner<E>|> : R|kotlin/Any| {
|
||||||
|
public abstract val symbol: R|AbstractFirBasedSymbol<E>|
|
||||||
|
public get(): R|AbstractFirBasedSymbol<E>|
|
||||||
|
|
||||||
|
}
|
||||||
|
public abstract interface FirFunction<F : R|FirFunction<F>|> : R|FirSymbolOwner<F>|, R|FirDeclaration| {
|
||||||
|
}
|
||||||
|
public abstract interface AbstractFirBasedSymbol<E : R|FirSymbolOwner<E>|, 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<out it(FirSymbolOwner<out it(FirSymbolOwner<out it(FirSymbolOwner<out it(FirSymbolOwner<out kotlin/Any?> & FirDeclaration)> & FirDeclaration)> & FirDeclaration)> & FirDeclaration)>| = (R|<local>/symbol|.R|SubstitutionOverride</AbstractFirBasedSymbol.fir: R|CapturedType(*)|>| as R|FirFunction<out it(FirSymbolOwner<out it(FirSymbolOwner<out it(FirSymbolOwner<out it(FirSymbolOwner<out kotlin/Any?> & FirDeclaration)> & FirDeclaration)> & FirDeclaration)> & FirDeclaration)>|)
|
||||||
|
R|/foo|(R|<local>/firAdaptee|)
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
interface FirDeclaration
|
||||||
|
|
||||||
|
interface FirSymbolOwner<E : FirSymbolOwner<E>> {
|
||||||
|
val symbol: AbstractFirBasedSymbol<E>
|
||||||
|
}
|
||||||
|
interface FirFunction<F : FirFunction<F>> : FirSymbolOwner<F>, FirDeclaration
|
||||||
|
|
||||||
|
interface AbstractFirBasedSymbol<E> where E : FirSymbolOwner<E>, E : FirDeclaration {
|
||||||
|
val fir: E
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(firAdaptee: FirFunction<*>) {}
|
||||||
|
|
||||||
|
fun test(symbol: AbstractFirBasedSymbol<*>) {
|
||||||
|
val firAdaptee = symbol.fir as FirFunction
|
||||||
|
foo(firAdaptee)
|
||||||
|
}
|
||||||
+6
@@ -3630,6 +3630,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
|||||||
public void testCapturedParametersOfInnerClasses() throws Exception {
|
public void testCapturedParametersOfInnerClasses() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/types/capturedParametersOfInnerClasses.kt");
|
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
|
@Nested
|
||||||
|
|||||||
+6
@@ -3681,6 +3681,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
public void testCapturedParametersOfInnerClasses() throws Exception {
|
public void testCapturedParametersOfInnerClasses() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/types/capturedParametersOfInnerClasses.kt");
|
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
|
@Nested
|
||||||
|
|||||||
+32
-16
@@ -499,25 +499,41 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
|||||||
val firClass = type.lookupTag.toSymbol(session)?.fir ?: return this
|
val firClass = type.lookupTag.toSymbol(session)?.fir ?: return this
|
||||||
if (firClass !is FirTypeParameterRefsOwner || firClass.typeParameters.isEmpty()) return this
|
if (firClass !is FirTypeParameterRefsOwner || firClass.typeParameters.isEmpty()) return this
|
||||||
|
|
||||||
val baseType = argument.typeRef.coneTypeSafe<ConeKotlinType>()?.lowerBoundIfFlexible()?.fullyExpandedType(session) ?: return this
|
val originalType = argument.typeRef.coneTypeSafe<ConeKotlinType>() ?: return this
|
||||||
if (baseType !is ConeClassLikeType) return this
|
val newType = computeRepresentativeTypeForBareType(type, originalType) ?: return buildErrorTypeRef {
|
||||||
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 {
|
|
||||||
source = this@withTypeArgumentsForBareType.source
|
source = this@withTypeArgumentsForBareType.source
|
||||||
diagnostic = ConeWrongNumberOfTypeArgumentsError(firClass.typeParameters.size, firClass.symbol)
|
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(
|
override fun transformTypeOperatorCall(
|
||||||
|
|||||||
Reference in New Issue
Block a user