[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 {
|
||||
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")
|
||||
|
||||
@@ -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 {
|
||||
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
|
||||
|
||||
+6
@@ -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
|
||||
|
||||
+32
-16
@@ -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<ConeKotlinType>()?.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<ConeKotlinType>() ?: 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(
|
||||
|
||||
Reference in New Issue
Block a user