From a882a9dff5fb19af47cc634f247b7301d76f0a24 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 2 Jul 2020 14:52:56 +0300 Subject: [PATCH] [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 --- .../callResolution/uselessMultipleBounds.kt | 13 ++++++++++++ .../callResolution/uselessMultipleBounds.txt | 12 +++++++++++ .../fir/FirDiagnosticsTestGenerated.java | 5 +++++ ...DiagnosticsWithLightTreeTestGenerated.java | 5 +++++ .../kotlin/fir/resolve/ScopeUtils.kt | 21 +++++++++++-------- 5 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/callResolution/uselessMultipleBounds.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/callResolution/uselessMultipleBounds.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/uselessMultipleBounds.kt b/compiler/fir/analysis-tests/testData/resolve/callResolution/uselessMultipleBounds.kt new file mode 100644 index 00000000000..e30c4816e0c --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/uselessMultipleBounds.kt @@ -0,0 +1,13 @@ +// ISSUE: KT-39032 + +interface A { + fun foo() +} + +interface B : A { + override fun foo() +} + +fun bar(e: E) where E : A, E : B { + e.foo() +} diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/uselessMultipleBounds.txt b/compiler/fir/analysis-tests/testData/resolve/callResolution/uselessMultipleBounds.txt new file mode 100644 index 00000000000..b5b8f28183d --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/uselessMultipleBounds.txt @@ -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 bar(e: R|E|): R|kotlin/Unit| { + R|/e|.R|/B.foo|() + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 1ef7ea8023a..399b7db3ffd 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -653,6 +653,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { public void testTypeAliasWithNotNullBound() throws Exception { 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") diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 670d34c5a50..33a1422d506 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -653,6 +653,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos public void testTypeAliasWithNotNullBound() throws Exception { 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") diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt index c4d97cd3f28..baa4557dd09 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt @@ -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.FirTypeIntersectionScope 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.impl.ConeClassLikeTypeImpl 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) } is ConeTypeParameterType -> { - // TODO: support LibraryTypeParameterSymbol or get rid of it - val fir = lookupTag.toSymbol().fir - FirTypeIntersectionScope.prepareIntersectionScope( - useSiteSession, - FirStandardOverrideChecker(useSiteSession), - fir.bounds.mapNotNullTo(mutableListOf()) { - it.coneType.scope(useSiteSession, scopeSession) - } - ) + val symbol = lookupTag.toSymbol() + scopeSession.getOrBuild(symbol, TYPE_PARAMETER_SCOPE_KEY) { + val intersectionType = ConeTypeIntersector.intersectTypes( + useSiteSession.typeContext, + symbol.fir.bounds.map { it.coneType } + ) + intersectionType.scope(useSiteSession, scopeSession) ?: FirTypeScope.Empty + } } is ConeRawType -> lowerBound.scope(useSiteSession, scopeSession) is ConeFlexibleType -> lowerBound.scope(useSiteSession, scopeSession) @@ -87,3 +88,5 @@ fun FirAnonymousObject.defaultType(): ConeClassLikeType { isNullable = false ) } + +val TYPE_PARAMETER_SCOPE_KEY = scopeSessionKey() \ No newline at end of file