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 38ba8662223..d1e8782ec2c 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 @@ -25212,6 +25212,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/resolve/resolveWithoutGenerics.kt"); } + @Test + @TestMetadata("smartcastToMoreSpecificProperty.kt") + public void testSmartcastToMoreSpecificProperty() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.kt"); + } + @Test @TestMetadata("superInvoke.kt") public void testSuperInvoke() throws Exception { @@ -28076,6 +28082,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/smartCasts/kt3993.kt"); } + @Test + @TestMetadata("kt51460.kt") + public void testKt51460() throws Exception { + runTest("compiler/testData/diagnostics/tests/smartCasts/kt51460.kt"); + } + @Test @TestMetadata("kt5427.kt") public void testKt5427() throws Exception { @@ -32901,6 +32913,30 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag public void testProtectedInternal() throws Exception { runTest("compiler/testData/diagnostics/tests/visibility/protectedInternal.kt"); } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_fakeOverride.kt") + public void testProtectedVisibilityAndSmartcast_fakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_fakeOverride.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_noOverride.kt") + public void testProtectedVisibilityAndSmartcast_noOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_noOverride.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_overrideChangesType.kt") + public void testProtectedVisibilityAndSmartcast_overrideChangesType() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_overrideSameType.kt") + public void testProtectedVisibilityAndSmartcast_overrideSameType() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideSameType.kt"); + } } @Nested 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 b1a518cd119..fe40de0346f 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 @@ -25212,6 +25212,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/resolve/resolveWithoutGenerics.kt"); } + @Test + @TestMetadata("smartcastToMoreSpecificProperty.kt") + public void testSmartcastToMoreSpecificProperty() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.kt"); + } + @Test @TestMetadata("superInvoke.kt") public void testSuperInvoke() throws Exception { @@ -28076,6 +28082,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/smartCasts/kt3993.kt"); } + @Test + @TestMetadata("kt51460.kt") + public void testKt51460() throws Exception { + runTest("compiler/testData/diagnostics/tests/smartCasts/kt51460.kt"); + } + @Test @TestMetadata("kt5427.kt") public void testKt5427() throws Exception { @@ -32901,6 +32913,30 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti public void testProtectedInternal() throws Exception { runTest("compiler/testData/diagnostics/tests/visibility/protectedInternal.kt"); } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_fakeOverride.kt") + public void testProtectedVisibilityAndSmartcast_fakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_fakeOverride.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_noOverride.kt") + public void testProtectedVisibilityAndSmartcast_noOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_noOverride.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_overrideChangesType.kt") + public void testProtectedVisibilityAndSmartcast_overrideChangesType() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_overrideSameType.kt") + public void testProtectedVisibilityAndSmartcast_overrideSameType() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideSameType.kt"); + } } @Nested 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 4b0a4691b38..497cfb2dfa9 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 @@ -25212,6 +25212,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/resolve/resolveWithoutGenerics.kt"); } + @Test + @TestMetadata("smartcastToMoreSpecificProperty.kt") + public void testSmartcastToMoreSpecificProperty() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.kt"); + } + @Test @TestMetadata("superInvoke.kt") public void testSuperInvoke() throws Exception { @@ -28076,6 +28082,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/smartCasts/kt3993.kt"); } + @Test + @TestMetadata("kt51460.kt") + public void testKt51460() throws Exception { + runTest("compiler/testData/diagnostics/tests/smartCasts/kt51460.kt"); + } + @Test @TestMetadata("kt5427.kt") public void testKt5427() throws Exception { @@ -32901,6 +32913,30 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac public void testProtectedInternal() throws Exception { runTest("compiler/testData/diagnostics/tests/visibility/protectedInternal.kt"); } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_fakeOverride.kt") + public void testProtectedVisibilityAndSmartcast_fakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_fakeOverride.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_noOverride.kt") + public void testProtectedVisibilityAndSmartcast_noOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_noOverride.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_overrideChangesType.kt") + public void testProtectedVisibilityAndSmartcast_overrideChangesType() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_overrideSameType.kt") + public void testProtectedVisibilityAndSmartcast_overrideSameType() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideSameType.kt"); + } } @Nested diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 07c9a3fbde3..3e083dc47b6 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -1242,7 +1242,7 @@ class Fir2IrDeclarationStorage( ) as IrFunctionSymbol if (unmatchedReceiver && dispatchReceiverLookupTag is ConeClassLookupTagWithFixedSymbol) { val originalFunction = originalSymbol.owner as IrSimpleFunction - dispatchReceiverLookupTag.findIrFakeOverride(fir.name, originalFunction) as IrFunctionSymbol + dispatchReceiverLookupTag.findIrFakeOverride(fir.name, originalFunction) as IrFunctionSymbol? ?: originalSymbol } else { originalSymbol } diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index ba0f91ec56b..cf5e1191e1e 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -16961,6 +16961,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/fakeOverride/diamondFunction.kt"); } + @Test + @TestMetadata("fakeOverrideInAnonymousObject.kt") + public void testFakeOverrideInAnonymousObject() throws Exception { + runTest("compiler/testData/codegen/box/fakeOverride/fakeOverrideInAnonymousObject.kt"); + } + @Test @TestMetadata("function.kt") public void testFunction() throws Exception { @@ -45635,12 +45641,30 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/smartCasts/nullSmartCast.kt"); } + @Test + @TestMetadata("resolveToMemberOfSuperclass_overrideWithDifferentType.kt") + public void testResolveToMemberOfSuperclass_overrideWithDifferentType() throws Exception { + runTest("compiler/testData/codegen/box/smartCasts/resolveToMemberOfSuperclass_overrideWithDifferentType.kt"); + } + + @Test + @TestMetadata("resolveToMemberOfSuperclass_overrideWithSameType.kt") + public void testResolveToMemberOfSuperclass_overrideWithSameType() throws Exception { + runTest("compiler/testData/codegen/box/smartCasts/resolveToMemberOfSuperclass_overrideWithSameType.kt"); + } + @Test @TestMetadata("smartCastInsideIf.kt") public void testSmartCastInsideIf() throws Exception { runTest("compiler/testData/codegen/box/smartCasts/smartCastInsideIf.kt"); } + @Test + @TestMetadata("toStringOnReceiverWIthSmartcast.kt") + public void testToStringOnReceiverWIthSmartcast() throws Exception { + runTest("compiler/testData/codegen/box/smartCasts/toStringOnReceiverWIthSmartcast.kt"); + } + @Test @TestMetadata("whenSmartCast.kt") public void testWhenSmartCast() throws Exception { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirOverrideService.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirOverrideService.kt index fa3d7bfad3d..80608ccff0a 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirOverrideService.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirOverrideService.kt @@ -63,10 +63,25 @@ class FirOverrideService(val session: FirSession) : FirSessionComponent { return result } + fun > createOverridableGroups( + members: Collection>, + overrideChecker: FirOverrideChecker + ): List>> { + if (members.size <= 1) return listOf(members.toList()) + val queue = LinkedList(members) + val result = mutableListOf>>() + while (queue.isNotEmpty()) { + val nextHandle = queue.first() + val overridableGroup = extractBothWaysOverridable(nextHandle, queue, overrideChecker) + result += overridableGroup + } + return result + } + fun > extractBothWaysOverridable( overrider: MemberWithBaseScope, members: MutableCollection>, - overrideChecker: FirOverrideChecker + overrideChecker: FirOverrideChecker, ): MutableList> { val result = mutableListOf>().apply { add(overrider) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/VisibilityUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/VisibilityUtils.kt index d5758bb2605..d89f05ca014 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/VisibilityUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/VisibilityUtils.kt @@ -20,11 +20,12 @@ import org.jetbrains.kotlin.fir.originalIfFakeOverride fun FirVisibilityChecker.isVisible( declaration: FirMemberDeclaration, - candidate: Candidate + callInfo: CallInfo, + dispatchReceiverValue: ReceiverValue? ): Boolean { if (declaration is FirCallableDeclaration && (declaration.isIntersectionOverride || declaration.isSubstitutionOverride)) { @Suppress("UNCHECKED_CAST") - return isVisible(declaration.originalIfFakeOverride() as FirMemberDeclaration, candidate) + return isVisible(declaration.originalIfFakeOverride() as FirMemberDeclaration, callInfo, dispatchReceiverValue) } // We won't resolve into the backing field @@ -33,18 +34,31 @@ fun FirVisibilityChecker.isVisible( return true } - val callInfo = candidate.callInfo val useSiteFile = callInfo.containingFile val containingDeclarations = callInfo.containingDeclarations val session = callInfo.session - val visible = isVisible( + return isVisible( declaration, session, useSiteFile, containingDeclarations, - candidate.dispatchReceiverValue, - candidate.callInfo.callSite is FirVariableAssignment + dispatchReceiverValue, + callInfo.callSite is FirVariableAssignment + ) + +} + +fun FirVisibilityChecker.isVisible( + declaration: FirMemberDeclaration, + candidate: Candidate +): Boolean { + val callInfo = candidate.callInfo + + val visible = isVisible( + declaration, + callInfo, + candidate.dispatchReceiverValue ) if (visible) { @@ -52,9 +66,9 @@ fun FirVisibilityChecker.isVisible( if (backingField != null) { candidate.hasVisibleBackingField = isVisible( backingField, - session, - useSiteFile, - containingDeclarations, + callInfo.session, + callInfo.containingFile, + callInfo.containingDeclarations, candidate.dispatchReceiverValue, candidate.callInfo.callSite is FirVariableAssignment, ) 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 93c42686f5b..6caa8caea92 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 @@ -10,19 +10,16 @@ import org.jetbrains.kotlin.fir.declarations.ContextReceiverGroup import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId import org.jetbrains.kotlin.fir.declarations.utils.isInner +import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier -import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents -import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.* -import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType -import org.jetbrains.kotlin.fir.resolve.typeForQualifier -import org.jetbrains.kotlin.fir.scopes.FirScope -import org.jetbrains.kotlin.fir.scopes.FirTypeScope +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.scopes.processClassifiersByName import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* @@ -79,13 +76,33 @@ class MemberScopeTowerLevel( private val scopeSession: ScopeSession get() = bodyResolveComponents.scopeSession private val session: FirSession get() = bodyResolveComponents.session - private fun > processMembers( + private fun > processMembers( + callInfo: CallInfo, output: TowerScopeLevelProcessor, processScopeMembers: FirScope.(processor: (T) -> Unit) -> Unit ): ProcessResult { val scope = dispatchReceiverValue.scope(session, scopeSession) ?: return ProcessResult.SCOPE_EMPTY var (empty, candidates) = scope.collectCandidates(processScopeMembers) - consumeCandidates(output, candidates.map { scope to it }) + + val scopeWithoutSmartcast = (dispatchReceiverValue.receiverExpression as? FirExpressionWithSmartcast) + ?.takeIf { it.isStable } + ?.originalType + ?.coneType + ?.scope(session, scopeSession, bodyResolveComponents.returnTypeCalculator.fakeOverrideTypeCalculator) + if (scopeWithoutSmartcast == null) { + consumeCandidates(output, candidates) + } else { + val candidatesFromOriginalType = mutableListOf>() + scopeWithoutSmartcast.collectCandidates(processScopeMembers).let { (isEmpty, originalCandidates) -> + empty = empty && isEmpty + candidatesFromOriginalType += originalCandidates + } + if (candidatesFromOriginalType.isNotEmpty()) { + processMembersFromSmartcastedType(callInfo, candidatesFromOriginalType, candidates, output) + } else { + consumeCandidates(output, candidates) + } + } if (givenExtensionReceiverOptions.isEmpty()) { val withSynthetic = FirSyntheticPropertiesScope(session, scope) @@ -97,32 +114,65 @@ class MemberScopeTowerLevel( return if (empty) ProcessResult.SCOPE_EMPTY else ProcessResult.FOUND } - private fun > FirTypeScope.collectCandidates( + private fun > processMembersFromSmartcastedType( + callInfo: CallInfo, + candidatesFromOriginalType: Collection>, + candidatesFromSmartcast: Collection>, + output: TowerScopeLevelProcessor, + ) { + val visibilityChecker = session.visibilityChecker + val candidatesMapping = buildMap { + candidatesFromOriginalType.forEach { put(it, false) } + candidatesFromSmartcast.forEach { put(it, true) } + } + + val overridableGroups = session.overrideService.createOverridableGroups( + candidatesFromOriginalType + candidatesFromSmartcast, + FirStandardOverrideChecker(session) + ) + + val candidates = mutableListOf>() + for (group in overridableGroups) { + val visibleCandidates = group.filter { + visibilityChecker.isVisible(it.member.fir, callInfo, dispatchReceiverValue) + } + + val visibleCandidatesFromSmartcast = visibleCandidates.filter { candidatesMapping.getValue(it) } + if (visibleCandidatesFromSmartcast.isNotEmpty()) { + candidates += visibleCandidatesFromSmartcast + } else { + group.filterNotTo(candidates) { candidatesMapping.getValue(it) } + } + } + consumeCandidates(output, candidates) + } + + private fun > FirTypeScope.collectCandidates( processScopeMembers: FirScope.(processor: (T) -> Unit) -> Unit - ): Pair> { + ): Pair>> { var empty = true - val result = mutableListOf() + val result = mutableListOf>() processScopeMembers { candidate -> empty = false - if (candidate is FirCallableSymbol<*> && candidate.hasConsistentExtensionReceiver(givenExtensionReceiverOptions)) { + if (candidate.hasConsistentExtensionReceiver(givenExtensionReceiverOptions)) { val fir = candidate.fir if ((fir as? FirConstructor)?.isInner == false) { return@processScopeMembers } - result += candidate + result += MemberWithBaseScope(candidate, this) } else if (candidate is FirClassLikeSymbol<*>) { - result += candidate + result += MemberWithBaseScope(candidate, this) } } return empty to result } - private fun > consumeCandidates( + private fun > consumeCandidates( output: TowerScopeLevelProcessor, - candidatesWithScope: List> + candidatesWithScope: List> ) { - for ((scope, candidate) in candidatesWithScope) { - if (candidate is FirCallableSymbol<*> && candidate.hasConsistentExtensionReceiver(givenExtensionReceiverOptions)) { + for ((candidate, scope) in candidatesWithScope) { + if (candidate.hasConsistentExtensionReceiver(givenExtensionReceiverOptions)) { output.consumeCandidate( candidate, dispatchReceiverValue, givenExtensionReceiverOptions, @@ -139,7 +189,7 @@ class MemberScopeTowerLevel( processor: TowerScopeLevelProcessor> ): ProcessResult { val lookupTracker = session.lookupTracker - return processMembers(processor) { consumer -> + return processMembers(info, processor) { consumer -> withMemberCallLookup(lookupTracker, info) { lookupCtx -> this.processFunctionsAndConstructorsByName( info, session, bodyResolveComponents, @@ -160,13 +210,11 @@ class MemberScopeTowerLevel( processor: TowerScopeLevelProcessor> ): ProcessResult { val lookupTracker = session.lookupTracker - return processMembers(processor) { consumer -> + return processMembers(info, processor) { consumer -> withMemberCallLookup(lookupTracker, info) { lookupCtx -> lookupTracker?.recordCallLookup(info, dispatchReceiverValue.type) this.processPropertiesByName(info.name) { lookupCtx.recordCallableMemberLookup(it) - // WARNING, DO NOT CAST FUNCTIONAL TYPE ITSELF - @Suppress("UNCHECKED_CAST") consumer(it) } } diff --git a/compiler/testData/codegen/box/fakeOverride/fakeOverrideInAnonymousObject.kt b/compiler/testData/codegen/box/fakeOverride/fakeOverrideInAnonymousObject.kt new file mode 100644 index 00000000000..a536979732e --- /dev/null +++ b/compiler/testData/codegen/box/fakeOverride/fakeOverrideInAnonymousObject.kt @@ -0,0 +1,26 @@ +// TARGET_BACKEND: JVM_IR +interface JPanel { + val result: String +} + +open class ActivePanel : JPanel { + override var result: String = "" + + fun fire(event: String) { + result = event + } +} + +class Test { + val panel: JPanel + + init { + panel = object : ActivePanel() {} + + panel.fire("OK") + } +} + +fun box(): String { + return Test().panel.result +} diff --git a/compiler/testData/codegen/box/smartCasts/resolveToMemberOfSuperclass_overrideWithDifferentType.kt b/compiler/testData/codegen/box/smartCasts/resolveToMemberOfSuperclass_overrideWithDifferentType.kt new file mode 100644 index 00000000000..ec592a08cd7 --- /dev/null +++ b/compiler/testData/codegen/box/smartCasts/resolveToMemberOfSuperclass_overrideWithDifferentType.kt @@ -0,0 +1,32 @@ +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND: JVM_IR +// ISSUE: KT-51460, KT-51827 + +open class Base { + protected open val a: CharSequence + get() = "Fail: Base" + + + fun test(other: Base): String { + return when (other) { + is Derived_1 -> other.a.toString() + is Derived_2 -> other.a.toString() + else -> "Fail: not Derived" + } + } +} + +class Derived_1: Base() { + override val a: String + get() = "Fail: Derived_1" +} + +class Derived_2: Base() { + override val a: String + get() = "OK" +} + +fun box(): String { + val x = Derived_2() + return x.test(x) +} diff --git a/compiler/testData/codegen/box/smartCasts/resolveToMemberOfSuperclass_overrideWithSameType.kt b/compiler/testData/codegen/box/smartCasts/resolveToMemberOfSuperclass_overrideWithSameType.kt new file mode 100644 index 00000000000..54f5c5f40b4 --- /dev/null +++ b/compiler/testData/codegen/box/smartCasts/resolveToMemberOfSuperclass_overrideWithSameType.kt @@ -0,0 +1,31 @@ +// TARGET_BACKEND: JVM_IR +// ISSUE: KT-51460 + +open class Base { + protected open val a: CharSequence + get() = "Fail: Base" + + + fun test(other: Base): String { + return when (other) { + is Derived_1 -> other.a.toString() + is Derived_2 -> other.a.toString() + else -> "Fail: not Derived" + } + } +} + +class Derived_1: Base() { + override val a: CharSequence + get() = "Fail: Derived_1" +} + +class Derived_2: Base() { + override val a: CharSequence + get() = "OK" +} + +fun box(): String { + val x = Derived_2() + return x.test(x) +} diff --git a/compiler/testData/codegen/box/smartCasts/toStringOnReceiverWIthSmartcast.kt b/compiler/testData/codegen/box/smartCasts/toStringOnReceiverWIthSmartcast.kt new file mode 100644 index 00000000000..213155d1f53 --- /dev/null +++ b/compiler/testData/codegen/box/smartCasts/toStringOnReceiverWIthSmartcast.kt @@ -0,0 +1,29 @@ +// TARGET_BACKEND: JVM_IR +// FILE: A.java +public class A { + @Override + public String toString() { + return "O"; + } +} + +// FILE: B.java +public class B { + @Override + public String toString() { + return "K"; + } +} + +// FILE: main.kt +fun test(x: Any): String { + return when (x) { + is A -> x.toString() + is B -> x.toString() + else -> "fail" + } +} + +fun box(): String { + return test(A()) + test(B()) +} diff --git a/compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.fir.kt b/compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.fir.kt new file mode 100644 index 00000000000..6f3cfe5f696 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.fir.kt @@ -0,0 +1,41 @@ +interface A> { + val symbol: ASymbol +} + +interface B> : A { + override val symbol: BSymbol +} + +interface C : B { + fun foo() + + override val symbol: CSymbol +} + +interface ASymbol> { + var value: T +} + +interface BSymbol> : ASymbol + +interface CSymbol : BSymbol { + fun bar() +} + +fun test_1(symbol: BSymbol<*>) { + if (symbol is CSymbol) { + symbol.value.foo() + } +} + +fun test_2(b: B<*>) { + if (b is C) { + b.symbol.bar() + } +} + +fun > test_3(b: B) { + if (b is C) { + b.symbol.bar() + } +} diff --git a/compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.kt b/compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.kt new file mode 100644 index 00000000000..fd08be0121d --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.kt @@ -0,0 +1,41 @@ +interface A> { + val symbol: ASymbol +} + +interface B> : A { + override val symbol: BSymbol +} + +interface C : B { + fun foo() + + override val symbol: CSymbol +} + +interface ASymbol> { + var value: T +} + +interface BSymbol> : ASymbol + +interface CSymbol : BSymbol { + fun bar() +} + +fun test_1(symbol: BSymbol<*>) { + if (symbol is CSymbol) { + symbol.value.foo() + } +} + +fun test_2(b: B<*>) { + if (b is C) { + b.symbol.bar() + } +} + +fun > test_3(b: B) { + if (b is C) { + b.symbol.bar() + } +} diff --git a/compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.txt b/compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.txt new file mode 100644 index 00000000000..270ddaa19df --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.txt @@ -0,0 +1,50 @@ +package + +public fun test_1(/*0*/ symbol: BSymbol<*>): kotlin.Unit +public fun test_2(/*0*/ b: B<*>): kotlin.Unit +public fun > test_3(/*0*/ b: B): kotlin.Unit + +public interface A> { + public abstract val symbol: ASymbol + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface ASymbol> { + public abstract var value: T + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface B> : A { + public abstract override /*1*/ val symbol: BSymbol + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface BSymbol> : ASymbol { + public abstract override /*1*/ /*fake_override*/ var value: T + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface C : B { + public abstract override /*1*/ val symbol: CSymbol + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface CSymbol : BSymbol { + public abstract override /*1*/ /*fake_override*/ var value: C + public abstract fun bar(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt51460.kt b/compiler/testData/diagnostics/tests/smartCasts/kt51460.kt new file mode 100644 index 00000000000..57c3f343170 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/kt51460.kt @@ -0,0 +1,18 @@ +// FIR_IDENTICAL +// ISSUE: KT-51460 + +abstract class A { + abstract protected val a: A? + + class B(override val a: A?) : A() { + fun f(other: A) { + val x = if (other is C) { + other.a + } else { + null + } + } + } + + class C(override val a: A?): A() +} diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt51460.txt b/compiler/testData/diagnostics/tests/smartCasts/kt51460.txt new file mode 100644 index 00000000000..783a76bd632 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/kt51460.txt @@ -0,0 +1,26 @@ +package + +public abstract class A { + public constructor A() + protected abstract val a: A? + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final class B : A { + public constructor B(/*0*/ a: A?) + protected open override /*1*/ val a: A? + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun f(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class C : A { + public constructor C(/*0*/ a: A?) + protected open override /*1*/ val a: A? + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_fakeOverride.kt b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_fakeOverride.kt new file mode 100644 index 00000000000..acf1e0e4292 --- /dev/null +++ b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_fakeOverride.kt @@ -0,0 +1,84 @@ +// FIR_IDENTICAL +interface Base { + fun baseFun() +} + +interface Derived : Base { + fun derivedFun() +} + +abstract class A { + protected val a: T = null!! + + fun fest_1(other: A<*>) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + + open class B : A() { + class Nested { + fun fest_3(other: A<*>) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + } + } + + class C : B() { + fun fest_4(other: A<*>) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + } + + class D : A() { + fun fest_5(other: A<*>) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + } +} diff --git a/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_fakeOverride.txt b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_fakeOverride.txt new file mode 100644 index 00000000000..fa2266f0dab --- /dev/null +++ b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_fakeOverride.txt @@ -0,0 +1,63 @@ +package + +public abstract class A { + public constructor A() + protected final val a: T + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun fest_1(/*0*/ other: A<*>): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public open class B : A { + public constructor B() + protected final override /*1*/ /*fake_override*/ val a: Derived + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A<*>): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final class Nested { + public constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun fest_3(/*0*/ other: A<*>): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } + + public final class C : A.B { + public constructor C() + protected final override /*1*/ /*fake_override*/ val a: Derived + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A<*>): kotlin.Unit + public final fun fest_4(/*0*/ other: A<*>): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class D : A { + public constructor D() + protected final override /*1*/ /*fake_override*/ val a: Derived + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A<*>): kotlin.Unit + public final fun fest_5(/*0*/ other: A<*>): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public interface Base { + public abstract fun baseFun(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Derived : Base { + public abstract override /*1*/ /*fake_override*/ fun baseFun(): kotlin.Unit + public abstract fun derivedFun(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + diff --git a/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_noOverride.kt b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_noOverride.kt new file mode 100644 index 00000000000..92408f197cc --- /dev/null +++ b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_noOverride.kt @@ -0,0 +1,68 @@ +// FIR_IDENTICAL +interface Base { + fun baseFun() +} + +abstract class A { + protected val a: Base = null!! + + fun fest_1(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + } + if (other is C) { + other.a.baseFun() + } + if (other is D) { + other.a.baseFun() + } + } + + open class B : A() { + class Nested { + fun fest_3(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + } + if (other is C) { + other.a.baseFun() + } + if (other is D) { + other.a.baseFun() + } + } + } + } + + class C : B() { + fun fest_4(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + } + if (other is C) { + other.a.baseFun() + } + if (other is D) { + other.a.baseFun() + } + } + } + + class D : A() { + fun fest_5(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + } + if (other is C) { + other.a.baseFun() + } + if (other is D) { + other.a.baseFun() + } + } + } +} diff --git a/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_noOverride.txt b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_noOverride.txt new file mode 100644 index 00000000000..6539c3414e1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_noOverride.txt @@ -0,0 +1,55 @@ +package + +public abstract class A { + public constructor A() + protected final val a: Base + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun fest_1(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public open class B : A { + public constructor B() + protected final override /*1*/ /*fake_override*/ val a: Base + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final class Nested { + public constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun fest_3(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } + + public final class C : A.B { + public constructor C() + protected final override /*1*/ /*fake_override*/ val a: Base + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A): kotlin.Unit + public final fun fest_4(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class D : A { + public constructor D() + protected final override /*1*/ /*fake_override*/ val a: Base + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A): kotlin.Unit + public final fun fest_5(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public interface Base { + public abstract fun baseFun(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + diff --git a/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.fir.kt b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.fir.kt new file mode 100644 index 00000000000..0521cdbd077 --- /dev/null +++ b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.fir.kt @@ -0,0 +1,85 @@ +// FIR_DUMP + +interface Base { + fun baseFun() +} + +interface Derived : Base { + fun derivedFun() +} + +abstract class A { + abstract protected val a: Base + + fun fest_1(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + + open class B(override val a: Derived) : A() { + class Nested { + fun fest_3(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + } + } + + class C(override val a: Derived) : B(a) { + fun fest_4(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + } + + class D(override val a: Derived) : A() { + fun fest_5(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + } +} diff --git a/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.fir.txt b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.fir.txt new file mode 100644 index 00000000000..cb07c97a5be --- /dev/null +++ b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.fir.txt @@ -0,0 +1,155 @@ +FILE: protectedVisibilityAndSmartcast_overrideChangesType.fir.kt + public abstract interface Base : R|kotlin/Any| { + public abstract fun baseFun(): R|kotlin/Unit| + + } + public abstract interface Derived : R|Base| { + public abstract fun derivedFun(): R|kotlin/Unit| + + } + public abstract class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + protected abstract val a: R|Base| + protected get(): R|Base| + + public final fun fest_1(other: R|A|): R|kotlin/Unit| { + R|/other|.R|/A.a|.R|/Base.baseFun|() + when () { + (R|/other| is R|A.B|) -> { + R|/other|.R|/A.a|.R|/Base.baseFun|() + R|/other|.R|/A.a|.#() + } + } + + when () { + (R|/other| is R|A.C|) -> { + R|/other|.R|/A.a|.R|/Base.baseFun|() + R|/other|.R|/A.a|.#() + } + } + + when () { + (R|/other| is R|A.D|) -> { + R|/other|.R|/A.a|.R|/Base.baseFun|() + R|/other|.R|/A.a|.#() + } + } + + } + + public open class B : R|A| { + public constructor(a: R|Derived|): R|A.B| { + super() + } + + protected open override val a: R|Derived| = R|/a| + protected get(): R|Derived| + + public final class Nested : R|kotlin/Any| { + public constructor(): R|A.B.Nested| { + super() + } + + public final fun fest_3(other: R|A|): R|kotlin/Unit| { + R|/other|.R|/A.a|.R|/Base.baseFun|() + when () { + (R|/other| is R|A.B|) -> { + R|/other|.R|/A.B.a|.R|/Base.baseFun|() + R|/other|.R|/A.B.a|.R|/Derived.derivedFun|() + } + } + + when () { + (R|/other| is R|A.C|) -> { + R|/other|.R|/A.a|.R|/Base.baseFun|() + R|/other|.R|/A.a|.#() + } + } + + when () { + (R|/other| is R|A.D|) -> { + R|/other|.R|/A.a|.R|/Base.baseFun|() + R|/other|.R|/A.a|.#() + } + } + + } + + } + + } + + public final class C : R|A.B| { + public constructor(a: R|Derived|): R|A.C| { + super(R|/a|) + } + + protected final override val a: R|Derived| = R|/a| + protected get(): R|Derived| + + public final fun fest_4(other: R|A|): R|kotlin/Unit| { + R|/other|.R|/A.a|.R|/Base.baseFun|() + when () { + (R|/other| is R|A.B|) -> { + R|/other|.R|/A.a|.R|/Base.baseFun|() + R|/other|.R|/A.a|.#() + } + } + + when () { + (R|/other| is R|A.C|) -> { + R|/other|.R|/A.C.a|.R|/Base.baseFun|() + R|/other|.R|/A.C.a|.R|/Derived.derivedFun|() + } + } + + when () { + (R|/other| is R|A.D|) -> { + R|/other|.R|/A.a|.R|/Base.baseFun|() + R|/other|.R|/A.a|.#() + } + } + + } + + } + + public final class D : R|A| { + public constructor(a: R|Derived|): R|A.D| { + super() + } + + protected final override val a: R|Derived| = R|/a| + protected get(): R|Derived| + + public final fun fest_5(other: R|A|): R|kotlin/Unit| { + R|/other|.R|/A.a|.R|/Base.baseFun|() + when () { + (R|/other| is R|A.B|) -> { + R|/other|.R|/A.a|.R|/Base.baseFun|() + R|/other|.R|/A.a|.#() + } + } + + when () { + (R|/other| is R|A.C|) -> { + R|/other|.R|/A.a|.R|/Base.baseFun|() + R|/other|.R|/A.a|.#() + } + } + + when () { + (R|/other| is R|A.D|) -> { + R|/other|.R|/A.D.a|.R|/Base.baseFun|() + R|/other|.R|/A.D.a|.R|/Derived.derivedFun|() + } + } + + } + + } + + } diff --git a/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.kt b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.kt new file mode 100644 index 00000000000..f01ea2f7bba --- /dev/null +++ b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.kt @@ -0,0 +1,85 @@ +// FIR_DUMP + +interface Base { + fun baseFun() +} + +interface Derived : Base { + fun derivedFun() +} + +abstract class A { + abstract protected val a: Base + + fun fest_1(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + + open class B(override val a: Derived) : A() { + class Nested { + fun fest_3(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + } + } + + class C(override val a: Derived) : B(a) { + fun fest_4(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + } + + class D(override val a: Derived) : A() { + fun fest_5(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is C) { + other.a.baseFun() + other.a.derivedFun() + } + if (other is D) { + other.a.baseFun() + other.a.derivedFun() + } + } + } +} diff --git a/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.txt b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.txt new file mode 100644 index 00000000000..2d0cd2821dd --- /dev/null +++ b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.txt @@ -0,0 +1,63 @@ +package + +public abstract class A { + public constructor A() + protected abstract val a: Base + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun fest_1(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public open class B : A { + public constructor B(/*0*/ a: Derived) + protected open override /*1*/ val a: Derived + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final class Nested { + public constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun fest_3(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } + + public final class C : A.B { + public constructor C(/*0*/ a: Derived) + protected open override /*1*/ val a: Derived + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A): kotlin.Unit + public final fun fest_4(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class D : A { + public constructor D(/*0*/ a: Derived) + protected open override /*1*/ val a: Derived + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A): kotlin.Unit + public final fun fest_5(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public interface Base { + public abstract fun baseFun(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Derived : Base { + public abstract override /*1*/ /*fake_override*/ fun baseFun(): kotlin.Unit + public abstract fun derivedFun(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + diff --git a/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideSameType.kt b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideSameType.kt new file mode 100644 index 00000000000..963e28840b4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideSameType.kt @@ -0,0 +1,68 @@ +// FIR_IDENTICAL +interface Base { + fun baseFun() +} + +abstract class A { + abstract protected val a: Base + + fun fest_1(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + } + if (other is C) { + other.a.baseFun() + } + if (other is D) { + other.a.baseFun() + } + } + + open class B(override val a: Base) : A() { + class Nested { + fun fest_3(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + } + if (other is C) { + other.a.baseFun() + } + if (other is D) { + other.a.baseFun() + } + } + } + } + + class C(override val a: Base) : B(a) { + fun fest_4(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + } + if (other is C) { + other.a.baseFun() + } + if (other is D) { + other.a.baseFun() + } + } + } + + class D(override val a: Base) : A() { + fun fest_5(other: A) { + other.a.baseFun() // OK + if (other is B) { + other.a.baseFun() + } + if (other is C) { + other.a.baseFun() + } + if (other is D) { + other.a.baseFun() + } + } + } +} diff --git a/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideSameType.txt b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideSameType.txt new file mode 100644 index 00000000000..fa1dbf55324 --- /dev/null +++ b/compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideSameType.txt @@ -0,0 +1,55 @@ +package + +public abstract class A { + public constructor A() + protected abstract val a: Base + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun fest_1(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public open class B : A { + public constructor B(/*0*/ a: Base) + protected open override /*1*/ val a: Base + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final class Nested { + public constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun fest_3(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } + + public final class C : A.B { + public constructor C(/*0*/ a: Base) + protected open override /*1*/ val a: Base + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A): kotlin.Unit + public final fun fest_4(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class D : A { + public constructor D(/*0*/ a: Base) + protected open override /*1*/ val a: Base + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun fest_1(/*0*/ other: A): kotlin.Unit + public final fun fest_5(/*0*/ other: A): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public interface Base { + public abstract fun baseFun(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + 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 19e6abe616b..9728cf0eaa7 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 @@ -25224,6 +25224,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/resolve/resolveWithoutGenerics.kt"); } + @Test + @TestMetadata("smartcastToMoreSpecificProperty.kt") + public void testSmartcastToMoreSpecificProperty() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/smartcastToMoreSpecificProperty.kt"); + } + @Test @TestMetadata("superInvoke.kt") public void testSuperInvoke() throws Exception { @@ -28166,6 +28172,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/smartCasts/kt3993.kt"); } + @Test + @TestMetadata("kt51460.kt") + public void testKt51460() throws Exception { + runTest("compiler/testData/diagnostics/tests/smartCasts/kt51460.kt"); + } + @Test @TestMetadata("kt5427.kt") public void testKt5427() throws Exception { @@ -32991,6 +33003,30 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { public void testProtectedInternal() throws Exception { runTest("compiler/testData/diagnostics/tests/visibility/protectedInternal.kt"); } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_fakeOverride.kt") + public void testProtectedVisibilityAndSmartcast_fakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_fakeOverride.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_noOverride.kt") + public void testProtectedVisibilityAndSmartcast_noOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_noOverride.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_overrideChangesType.kt") + public void testProtectedVisibilityAndSmartcast_overrideChangesType() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideChangesType.kt"); + } + + @Test + @TestMetadata("protectedVisibilityAndSmartcast_overrideSameType.kt") + public void testProtectedVisibilityAndSmartcast_overrideSameType() throws Exception { + runTest("compiler/testData/diagnostics/tests/visibility/protectedVisibilityAndSmartcast_overrideSameType.kt"); + } } @Nested diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 913da750c27..ab90ba6567c 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -16961,6 +16961,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/fakeOverride/diamondFunction.kt"); } + @Test + @TestMetadata("fakeOverrideInAnonymousObject.kt") + public void testFakeOverrideInAnonymousObject() throws Exception { + runTest("compiler/testData/codegen/box/fakeOverride/fakeOverrideInAnonymousObject.kt"); + } + @Test @TestMetadata("function.kt") public void testFunction() throws Exception { @@ -45635,12 +45641,30 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/smartCasts/nullSmartCast.kt"); } + @Test + @TestMetadata("resolveToMemberOfSuperclass_overrideWithDifferentType.kt") + public void testResolveToMemberOfSuperclass_overrideWithDifferentType() throws Exception { + runTest("compiler/testData/codegen/box/smartCasts/resolveToMemberOfSuperclass_overrideWithDifferentType.kt"); + } + + @Test + @TestMetadata("resolveToMemberOfSuperclass_overrideWithSameType.kt") + public void testResolveToMemberOfSuperclass_overrideWithSameType() throws Exception { + runTest("compiler/testData/codegen/box/smartCasts/resolveToMemberOfSuperclass_overrideWithSameType.kt"); + } + @Test @TestMetadata("smartCastInsideIf.kt") public void testSmartCastInsideIf() throws Exception { runTest("compiler/testData/codegen/box/smartCasts/smartCastInsideIf.kt"); } + @Test + @TestMetadata("toStringOnReceiverWIthSmartcast.kt") + public void testToStringOnReceiverWIthSmartcast() throws Exception { + runTest("compiler/testData/codegen/box/smartCasts/toStringOnReceiverWIthSmartcast.kt"); + } + @Test @TestMetadata("whenSmartCast.kt") public void testWhenSmartCast() throws Exception {