[FIR] Create scope for type parameter as scope for intersection of bounds
Before change we've created composite scope for all bounds, which is incorrect, because intersection of all bounds may be less than all bounds (see test in commit) #KT-39032 Fixed
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// ISSUE: KT-39032
|
||||||
|
|
||||||
|
interface A {
|
||||||
|
fun foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B : A {
|
||||||
|
override fun foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <E> bar(e: E) where E : A, E : B {
|
||||||
|
e.foo()
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
FILE: uselessMultipleBounds.kt
|
||||||
|
public abstract interface A : R|kotlin/Any| {
|
||||||
|
public abstract fun foo(): R|kotlin/Unit|
|
||||||
|
|
||||||
|
}
|
||||||
|
public abstract interface B : R|A| {
|
||||||
|
public abstract override fun foo(): R|kotlin/Unit|
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun <E : R|A|, R|B|> bar(e: R|E|): R|kotlin/Unit| {
|
||||||
|
R|<local>/e|.R|/B.foo|()
|
||||||
|
}
|
||||||
Generated
+5
@@ -653,6 +653,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
|||||||
public void testTypeAliasWithNotNullBound() throws Exception {
|
public void testTypeAliasWithNotNullBound() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/typeAliasWithNotNullBound.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/typeAliasWithNotNullBound.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("uselessMultipleBounds.kt")
|
||||||
|
public void testUselessMultipleBounds() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/uselessMultipleBounds.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/cfg")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/cfg")
|
||||||
|
|||||||
+5
@@ -653,6 +653,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
public void testTypeAliasWithNotNullBound() throws Exception {
|
public void testTypeAliasWithNotNullBound() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/typeAliasWithNotNullBound.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/typeAliasWithNotNullBound.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("uselessMultipleBounds.kt")
|
||||||
|
public void testUselessMultipleBounds() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/uselessMultipleBounds.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/cfg")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/cfg")
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerLiteralTypeScope
|
|||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
|
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.scope
|
import org.jetbrains.kotlin.fir.scopes.scope
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||||
@@ -31,15 +33,14 @@ fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession)
|
|||||||
fir.scope(substitutorByMap(substitution), useSiteSession, scopeSession, skipPrivateMembers = false)
|
fir.scope(substitutorByMap(substitution), useSiteSession, scopeSession, skipPrivateMembers = false)
|
||||||
}
|
}
|
||||||
is ConeTypeParameterType -> {
|
is ConeTypeParameterType -> {
|
||||||
// TODO: support LibraryTypeParameterSymbol or get rid of it
|
val symbol = lookupTag.toSymbol()
|
||||||
val fir = lookupTag.toSymbol().fir
|
scopeSession.getOrBuild(symbol, TYPE_PARAMETER_SCOPE_KEY) {
|
||||||
FirTypeIntersectionScope.prepareIntersectionScope(
|
val intersectionType = ConeTypeIntersector.intersectTypes(
|
||||||
useSiteSession,
|
useSiteSession.typeContext,
|
||||||
FirStandardOverrideChecker(useSiteSession),
|
symbol.fir.bounds.map { it.coneType }
|
||||||
fir.bounds.mapNotNullTo(mutableListOf()) {
|
)
|
||||||
it.coneType.scope(useSiteSession, scopeSession)
|
intersectionType.scope(useSiteSession, scopeSession) ?: FirTypeScope.Empty
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
is ConeRawType -> lowerBound.scope(useSiteSession, scopeSession)
|
is ConeRawType -> lowerBound.scope(useSiteSession, scopeSession)
|
||||||
is ConeFlexibleType -> lowerBound.scope(useSiteSession, scopeSession)
|
is ConeFlexibleType -> lowerBound.scope(useSiteSession, scopeSession)
|
||||||
@@ -87,3 +88,5 @@ fun FirAnonymousObject.defaultType(): ConeClassLikeType {
|
|||||||
isNullable = false
|
isNullable = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val TYPE_PARAMETER_SCOPE_KEY = scopeSessionKey<FirTypeParameterSymbol, FirTypeScope>()
|
||||||
Reference in New Issue
Block a user