diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 900ddf807b4..ce37fbf18e9 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -24265,6 +24265,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/simple.kt"); } + @Test + @TestMetadata("smartCastToClassWithRawSupertype.kt") + public void testSmartCastToClassWithRawSupertype() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt"); + } + @Test @TestMetadata("starProjectionToRaw.kt") public void testStarProjectionToRaw() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index d30ee9e31ec..947ab20a841 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -24265,6 +24265,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/simple.kt"); } + @Test + @TestMetadata("smartCastToClassWithRawSupertype.kt") + public void testSmartCastToClassWithRawSupertype() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt"); + } + @Test @TestMetadata("starProjectionToRaw.kt") public void testStarProjectionToRaw() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index b760f24eecb..12b70475830 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -24265,6 +24265,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/simple.kt"); } + @Test + @TestMetadata("smartCastToClassWithRawSupertype.kt") + public void testSmartCastToClassWithRawSupertype() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt"); + } + @Test @TestMetadata("starProjectionToRaw.kt") public void testStarProjectionToRaw() throws Exception { diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt index 95463fe39eb..dc1b6f4c50e 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.java.FirJvmDefaultModeComponent import org.jetbrains.kotlin.fir.java.JvmSupertypeUpdater import org.jetbrains.kotlin.fir.java.enhancement.FirAnnotationTypeQualifierResolver import org.jetbrains.kotlin.fir.java.enhancement.FirEnhancedSymbolsStorage +import org.jetbrains.kotlin.fir.java.scopes.JavaOverridabilityRules import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticNamesProvider @@ -35,6 +36,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.PlatformSupertypeUpdater import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClassIndex import org.jetbrains.kotlin.fir.scopes.FirOverrideService import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper +import org.jetbrains.kotlin.fir.scopes.PlatformSpecificOverridabilityRules import org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider import org.jetbrains.kotlin.fir.scopes.impl.FirDynamicMembersStorage import org.jetbrains.kotlin.fir.scopes.impl.FirIntersectionOverrideStorage @@ -88,6 +90,7 @@ fun FirSession.registerCommonJavaComponents(javaModuleResolver: JavaModuleResolv FirJvmDefaultModeComponent(languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)) ) register(PlatformSupertypeUpdater::class, JvmSupertypeUpdater(this)) + register(PlatformSpecificOverridabilityRules::class, JavaOverridabilityRules(this)) } // -------------------------- Resolve components -------------------------- diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverridabilityRules.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverridabilityRules.kt new file mode 100644 index 00000000000..d169bd69ff9 --- /dev/null +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverridabilityRules.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.java.scopes + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack +import org.jetbrains.kotlin.fir.scopes.PlatformSpecificOverridabilityRules +import org.jetbrains.kotlin.fir.unwrapFakeOverrides + +class JavaOverridabilityRules(session: FirSession) : PlatformSpecificOverridabilityRules { + private val javaOverrideChecker = + JavaOverrideChecker(session, JavaTypeParameterStack.EMPTY, baseScopes = null, considerReturnTypeKinds = true) + + override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean? { + if (!overrideCandidate.isFromJava() || !baseDeclaration.isFromJava()) return null + + return javaOverrideChecker.isOverriddenFunction(overrideCandidate, baseDeclaration) + } + + override fun isOverriddenProperty(overrideCandidate: FirCallableDeclaration, baseDeclaration: FirProperty): Boolean? { + if (!overrideCandidate.isFromJava() || !baseDeclaration.isFromJava()) return null + + return javaOverrideChecker.isOverriddenProperty(overrideCandidate, baseDeclaration) + } + + private fun FirCallableDeclaration.isFromJava(): Boolean = unwrapFakeOverrides().origin == FirDeclarationOrigin.Enhancement +} diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt index 0b516c62bf5..01b82519c2e 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt @@ -11,11 +11,11 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression import org.jetbrains.kotlin.fir.resolve.substitution.ConeRawScopeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap -import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator -import org.jetbrains.kotlin.fir.scopes.FirTypeScope -import org.jetbrains.kotlin.fir.scopes.FirUnstableSmartcastTypeScope -import org.jetbrains.kotlin.fir.scopes.impl.* -import org.jetbrains.kotlin.fir.scopes.scopeForClass +import org.jetbrains.kotlin.fir.scopes.* +import org.jetbrains.kotlin.fir.scopes.impl.FirScopeWithFakeOverrideTypeCalculator +import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope +import org.jetbrains.kotlin.fir.scopes.impl.dynamicMembersStorage +import org.jetbrains.kotlin.fir.scopes.impl.getOrBuildScopeForIntegerConstantOperatorType import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol @@ -89,7 +89,7 @@ private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: Scope is ConeFlexibleType -> lowerBound.scope(useSiteSession, scopeSession, requiredPhase) is ConeIntersectionType -> FirTypeIntersectionScope.prepareIntersectionScope( useSiteSession, - FirStandardOverrideChecker(useSiteSession), + FirIntersectionScopeOverrideChecker(useSiteSession), intersectedTypes.mapNotNullTo(mutableListOf()) { it.scope(useSiteSession, scopeSession, requiredPhase) }, diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirIntersectionScopeOverrideChecker.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirIntersectionScopeOverrideChecker.kt new file mode 100644 index 00000000000..d8bf270054b --- /dev/null +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirIntersectionScopeOverrideChecker.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.scopes + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker + +/** + * That class is expected to work just the same as FirStandardOverrideChecker for regular members, + * but when it comes to the platform originated member, it's more correct to use platform specific rules, too + * + * Initial reason for that checker introduction is smart-cast to raw type: + * it makes initial type's member incompatible with raw-type's one when regular overridability rules are used, + * while in Java class they would be treated equally. + */ +class FirIntersectionScopeOverrideChecker(session: FirSession) : FirOverrideChecker { + private val standardOverrideChecker = FirStandardOverrideChecker(session) + private val platformSpecificOverridabilityRules = session.platformSpecificOverridabilityRules + + override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean { + platformSpecificOverridabilityRules?.isOverriddenFunction(overrideCandidate, baseDeclaration)?.let { return it } + return standardOverrideChecker.isOverriddenFunction(overrideCandidate, baseDeclaration) + } + + override fun isOverriddenProperty(overrideCandidate: FirCallableDeclaration, baseDeclaration: FirProperty): Boolean { + platformSpecificOverridabilityRules?.isOverriddenProperty(overrideCandidate, baseDeclaration)?.let { return it } + return standardOverrideChecker.isOverriddenProperty(overrideCandidate, baseDeclaration) + } +} diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/PlatformSpecificOverridabilityRules.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/PlatformSpecificOverridabilityRules.kt new file mode 100644 index 00000000000..465cce4a1c3 --- /dev/null +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/PlatformSpecificOverridabilityRules.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.scopes + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirSessionComponent +import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction + +interface PlatformSpecificOverridabilityRules : FirSessionComponent { + // Thus functions return "null" in case the status should be defined via standard platform-independent rules + fun isOverriddenFunction( + overrideCandidate: FirSimpleFunction, + baseDeclaration: FirSimpleFunction + ): Boolean? + + fun isOverriddenProperty( + overrideCandidate: FirCallableDeclaration, + baseDeclaration: FirProperty + ): Boolean? +} + +val FirSession.platformSpecificOverridabilityRules: PlatformSpecificOverridabilityRules? by FirSession.nullableSessionComponentAccessor() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt index f7d34402efe..146471d151f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.scopes.impl.FirDefaultStarImportingScope -import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectData import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.* @@ -153,7 +152,7 @@ class MemberScopeTowerLevel( val overridableGroups = session.overrideService.createOverridableGroups( candidatesFromOriginalType + candidatesFromSmartcast, - FirStandardOverrideChecker(session) + FirIntersectionScopeOverrideChecker(session) ) val candidates = mutableListOf>() diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt new file mode 100644 index 00000000000..b5f72f96377 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt @@ -0,0 +1,24 @@ +// FIR_IDENTICAL +// SKIP_TXT +// !DIAGNOSTICS: -UNUSED_VARIABLE +// FILE: Key.java +public interface Key {} +// FILE: UserDataHolder.java +public interface UserDataHolder { + T getUserData(@NotNull Key key); +} + +// FILE: GenericInterface.java +public abstract class GenericClass extends UserDataHolder {} + +// FILE: NonGenericClassWithRawSuperType.java +public abstract class NonGenericClassWithRawSuperType extends GenericClass {} + +// FILE: main.kt +fun foo(k: Key, a: NonGenericClassWithRawSuperType, b: GenericClass<*>) { + b.getUserData(k) + + if (b is NonGenericClassWithRawSuperType) { + b.getUserData(k) + } +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 2c13a959e54..1ee89d8c6f7 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -24271,6 +24271,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/simple.kt"); } + @Test + @TestMetadata("smartCastToClassWithRawSupertype.kt") + public void testSmartCastToClassWithRawSupertype() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt"); + } + @Test @TestMetadata("starProjectionToRaw.kt") public void testStarProjectionToRaw() throws Exception {