[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:
Dmitriy Novozhilov
2020-07-02 14:52:56 +03:00
parent 44d0af8597
commit a882a9dff5
5 changed files with 47 additions and 9 deletions
@@ -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()
}
@@ -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|()
}
@@ -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")
@@ -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>()