KTIJ-20618 FIR IDE: Enforce resolved type bounds in ConeTypeContext.kt
When lazy resolve is involved, type bounds can be in an unresolved state (e.g. `FirUserTypeRef` instead of `FirResolvedTypeRef`). To enforce the resolve, we use `resolvedTypeBounds` where it might be important ^KTIJ-20618 Fixed
This commit is contained in:
+6
@@ -260,6 +260,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("implicitTypeWithTypeBound.kt")
|
||||||
|
public void testImplicitTypeWithTypeBound() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeWithTypeBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("incorrectDataClass.kt")
|
@TestMetadata("incorrectDataClass.kt")
|
||||||
public void testIncorrectDataClass() throws Exception {
|
public void testIncorrectDataClass() throws Exception {
|
||||||
|
|||||||
+5
@@ -224,6 +224,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("implicitTypeWithTypeBound.kt")
|
||||||
|
public void testImplicitTypeWithTypeBound() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeWithTypeBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("incorrectDataClass.kt")
|
@TestMetadata("incorrectDataClass.kt")
|
||||||
public void testIncorrectDataClass() throws Exception {
|
public void testIncorrectDataClass() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt");
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
FILE: main.kt
|
||||||
|
public final fun <T> myRun(action: R|() -> T|): R|T| {
|
||||||
|
^myRun R|<local>/action|.R|SubstitutionOverride<kotlin/Function0.invoke: R|T|>|()
|
||||||
|
}
|
||||||
|
public final fun test(other: R|TypeWithBoundedGeneric<*>|): R|TypeWithBoundedGeneric<*>| {
|
||||||
|
^test R|/myRun|<R|TypeWithBoundedGeneric<*>|>(<L> = myRun@fun <anonymous>(): R|TypeWithBoundedGeneric<*>| <inline=NoInline> {
|
||||||
|
^ R|<local>/other|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public abstract interface SomeType : R|kotlin/Any| {
|
||||||
|
}
|
||||||
|
public abstract class TypeWithBoundedGeneric<T : R|SomeType|> : R|kotlin/Any| {
|
||||||
|
public constructor<T : R|SomeType|>(): R|TypeWithBoundedGeneric<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// FILE: main.kt
|
||||||
|
fun <T> myRun(action: () -> T): T = action()
|
||||||
|
|
||||||
|
fun test(other: TypeWithBoundedGeneric<*>) = myRun { other }
|
||||||
|
|
||||||
|
interface SomeType
|
||||||
|
|
||||||
|
abstract class TypeWithBoundedGeneric<T : SomeType>
|
||||||
+6
@@ -260,6 +260,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("implicitTypeWithTypeBound.kt")
|
||||||
|
public void testImplicitTypeWithTypeBound() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeWithTypeBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("incorrectDataClass.kt")
|
@TestMetadata("incorrectDataClass.kt")
|
||||||
public void testIncorrectDataClass() throws Exception {
|
public void testIncorrectDataClass() throws Exception {
|
||||||
|
|||||||
+6
@@ -260,6 +260,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("implicitTypeWithTypeBound.kt")
|
||||||
|
public void testImplicitTypeWithTypeBound() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeWithTypeBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("incorrectDataClass.kt")
|
@TestMetadata("incorrectDataClass.kt")
|
||||||
public void testIncorrectDataClass() throws Exception {
|
public void testIncorrectDataClass() throws Exception {
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
|||||||
return when (this) {
|
return when (this) {
|
||||||
is ConeStubTypeConstructor -> listOf(session.builtinTypes.nullableAnyType.type)
|
is ConeStubTypeConstructor -> listOf(session.builtinTypes.nullableAnyType.type)
|
||||||
is ConeTypeVariableTypeConstructor -> emptyList()
|
is ConeTypeVariableTypeConstructor -> emptyList()
|
||||||
is ConeTypeParameterLookupTag -> symbol.fir.bounds.map { it.coneType }
|
is ConeTypeParameterLookupTag -> symbol.resolvedBounds.map { it.coneType }
|
||||||
is ConeClassLikeLookupTag -> {
|
is ConeClassLikeLookupTag -> {
|
||||||
when (val symbol = toClassLikeSymbol().also { it?.ensureResolved(FirResolvePhase.TYPES) }) {
|
when (val symbol = toClassLikeSymbol().also { it?.ensureResolved(FirResolvePhase.TYPES) }) {
|
||||||
is FirClassSymbol<*> -> symbol.fir.superConeTypes
|
is FirClassSymbol<*> -> symbol.fir.superConeTypes
|
||||||
@@ -308,17 +308,17 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
|||||||
|
|
||||||
override fun TypeParameterMarker.upperBoundCount(): Int {
|
override fun TypeParameterMarker.upperBoundCount(): Int {
|
||||||
require(this is ConeTypeParameterLookupTag)
|
require(this is ConeTypeParameterLookupTag)
|
||||||
return this.symbol.fir.bounds.size
|
return this.symbol.resolvedBounds.size
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun TypeParameterMarker.getUpperBound(index: Int): KotlinTypeMarker {
|
override fun TypeParameterMarker.getUpperBound(index: Int): KotlinTypeMarker {
|
||||||
require(this is ConeTypeParameterLookupTag)
|
require(this is ConeTypeParameterLookupTag)
|
||||||
return this.symbol.fir.bounds[index].coneType
|
return this.symbol.resolvedBounds[index].coneType
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun TypeParameterMarker.getUpperBounds(): List<KotlinTypeMarker> {
|
override fun TypeParameterMarker.getUpperBounds(): List<KotlinTypeMarker> {
|
||||||
require(this is ConeTypeParameterLookupTag)
|
require(this is ConeTypeParameterLookupTag)
|
||||||
return this.symbol.fir.bounds.map { it.coneType }
|
return this.symbol.resolvedBounds.map { it.coneType }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun TypeParameterMarker.getTypeConstructor(): TypeConstructorMarker {
|
override fun TypeParameterMarker.getTypeConstructor(): TypeConstructorMarker {
|
||||||
@@ -328,7 +328,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
|||||||
|
|
||||||
override fun TypeParameterMarker.hasRecursiveBounds(selfConstructor: TypeConstructorMarker?): Boolean {
|
override fun TypeParameterMarker.hasRecursiveBounds(selfConstructor: TypeConstructorMarker?): Boolean {
|
||||||
require(this is ConeTypeParameterLookupTag)
|
require(this is ConeTypeParameterLookupTag)
|
||||||
return this.typeParameterSymbol.fir.bounds.any { typeRef ->
|
return this.typeParameterSymbol.resolvedBounds.any { typeRef ->
|
||||||
typeRef.coneType.contains { it.typeConstructor() == this.getTypeConstructor() }
|
typeRef.coneType.contains { it.typeConstructor() == this.getTypeConstructor() }
|
||||||
&& (selfConstructor == null || typeRef.coneType.typeConstructor() == selfConstructor)
|
&& (selfConstructor == null || typeRef.coneType.typeConstructor() == selfConstructor)
|
||||||
}
|
}
|
||||||
@@ -484,7 +484,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FirTypeParameterSymbol.allBoundsAreNullable(): Boolean {
|
private fun FirTypeParameterSymbol.allBoundsAreNullable(): Boolean {
|
||||||
return fir.bounds.all { it.coneType.isNullableType() }
|
return resolvedBounds.all { it.coneType.isNullableType() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TypeConstructorMarker.toFirRegularClass(): FirRegularClass? {
|
private fun TypeConstructorMarker.toFirRegularClass(): FirRegularClass? {
|
||||||
@@ -553,7 +553,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
|||||||
|
|
||||||
override fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker {
|
override fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker {
|
||||||
require(this is ConeTypeParameterLookupTag)
|
require(this is ConeTypeParameterLookupTag)
|
||||||
return this.symbol.fir.bounds.getOrNull(0)?.coneType
|
return this.symbol.resolvedBounds.getOrNull(0)?.coneType
|
||||||
?: session.builtinTypes.nullableAnyType.type
|
?: session.builtinTypes.nullableAnyType.type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user