FIR: Fix case when smartcast receiver is used for call to private method

^KT-54432 Fixed
This commit is contained in:
Denis.Zharkov
2022-05-27 16:07:38 +03:00
committed by teamcity
parent ccc32b4e3b
commit c1904004c4
20 changed files with 306 additions and 27 deletions
@@ -33508,6 +33508,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClass.kt");
}
@Test
@TestMetadata("invisiblePrivateThroughSubClassDoubleSmartCast.kt")
public void testInvisiblePrivateThroughSubClassDoubleSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClassDoubleSmartCast.kt");
}
@Test
@TestMetadata("invisiblePrivateThroughSubClassSmartCast.kt")
public void testInvisiblePrivateThroughSubClassSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClassSmartCast.kt");
}
@Test
@TestMetadata("invisibleSetterOfJavaClass.kt")
public void testInvisibleSetterOfJavaClass() throws Exception {
@@ -33508,6 +33508,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClass.kt");
}
@Test
@TestMetadata("invisiblePrivateThroughSubClassDoubleSmartCast.kt")
public void testInvisiblePrivateThroughSubClassDoubleSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClassDoubleSmartCast.kt");
}
@Test
@TestMetadata("invisiblePrivateThroughSubClassSmartCast.kt")
public void testInvisiblePrivateThroughSubClassSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClassSmartCast.kt");
}
@Test
@TestMetadata("invisibleSetterOfJavaClass.kt")
public void testInvisibleSetterOfJavaClass() throws Exception {
@@ -33508,6 +33508,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClass.kt");
}
@Test
@TestMetadata("invisiblePrivateThroughSubClassDoubleSmartCast.kt")
public void testInvisiblePrivateThroughSubClassDoubleSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClassDoubleSmartCast.kt");
}
@Test
@TestMetadata("invisiblePrivateThroughSubClassSmartCast.kt")
public void testInvisiblePrivateThroughSubClassSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClassSmartCast.kt");
}
@Test
@TestMetadata("invisibleSetterOfJavaClass.kt")
public void testInvisibleSetterOfJavaClass() throws Exception {
@@ -45671,6 +45671,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/smartCasts"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("avoidSmartCastToDerivedForPrivate.kt")
public void testAvoidSmartCastToDerivedForPrivate() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/avoidSmartCastToDerivedForPrivate.kt");
}
@Test
@TestMetadata("complexExplicitReceiver.kt")
public void testComplexExplicitReceiver() throws Exception {
@@ -45791,6 +45797,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/smartCasts/kt48163_smartCastToThrowable.kt");
}
@Test
@TestMetadata("kt52432.kt")
public void testKt52432() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt52432.kt");
}
@Test
@TestMetadata("lambdaArgumentWithoutType.kt")
public void testLambdaArgumentWithoutType() throws Exception {
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
class Candidate(
override val symbol: FirBasedSymbol<*>,
override val dispatchReceiverValue: ReceiverValue?,
override var dispatchReceiverValue: ReceiverValue?,
// In most cases, it contains zero or single element
// More than one, only in case of context receiver group
val givenExtensionReceiverOptions: List<ReceiverValue>,
@@ -6,17 +6,20 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirVisibilityChecker
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.FirBackingField
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.utils.getExplicitBackingField
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.isIntersectionOverride
import org.jetbrains.kotlin.fir.isSubstitutionOverride
import org.jetbrains.kotlin.fir.originalIfFakeOverride
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionWithSmartcast
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isNullableNothing
import org.jetbrains.kotlin.fir.types.makeConeTypeDefinitelyNotNullOrNotNull
import org.jetbrains.kotlin.fir.types.typeContext
fun FirVisibilityChecker.isVisible(
declaration: FirMemberDeclaration,
@@ -55,27 +58,59 @@ fun FirVisibilityChecker.isVisible(
): Boolean {
val callInfo = candidate.callInfo
val visible = isVisible(
declaration,
callInfo,
candidate.dispatchReceiverValue
)
if (!isVisible(declaration, callInfo, candidate.dispatchReceiverValue)) {
val dispatchReceiverWithoutSmartCastType =
removeSmartCastTypeForAttemptToFitVisibility(candidate.dispatchReceiverValue, candidate.callInfo.session) ?: return false
if (visible) {
val backingField = declaration.getBackingFieldIfApplicable()
if (backingField != null) {
candidate.hasVisibleBackingField = isVisible(
backingField,
callInfo.session,
callInfo.containingFile,
callInfo.containingDeclarations,
candidate.dispatchReceiverValue,
candidate.callInfo.callSite is FirVariableAssignment,
)
if (!isVisible(declaration, callInfo, dispatchReceiverWithoutSmartCastType)) return false
candidate.dispatchReceiverValue = dispatchReceiverWithoutSmartCastType
}
val backingField = declaration.getBackingFieldIfApplicable()
if (backingField != null) {
candidate.hasVisibleBackingField = isVisible(
backingField,
callInfo.session,
callInfo.containingFile,
callInfo.containingDeclarations,
candidate.dispatchReceiverValue,
candidate.callInfo.callSite is FirVariableAssignment,
)
}
return true
}
private fun removeSmartCastTypeForAttemptToFitVisibility(dispatchReceiverValue: ReceiverValue?, session: FirSession): ReceiverValue? {
val expressionWithSmartcastIfStable =
(dispatchReceiverValue?.receiverExpression as? FirExpressionWithSmartcast)?.takeIf { it.isStable } ?: return null
if (dispatchReceiverValue.type.isNullableNothing) return null
val originalTypeNotNullable =
expressionWithSmartcastIfStable.originalType.coneType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext)
// Basically, this `if` is just for sake of optimizaton
// We have only nullability enhancement, here, so return initial smart cast receiver value
if (originalTypeNotNullable == dispatchReceiverValue.type) return null
val expressionForReceiver = with(session.typeContext) {
when {
expressionWithSmartcastIfStable.originalType.coneType.isNullableType() && !dispatchReceiverValue.type.isNullableType() ->
buildExpressionWithSmartcast {
originalExpression = expressionWithSmartcastIfStable.originalExpression
smartcastType =
expressionWithSmartcastIfStable.originalExpression.typeRef.resolvedTypeFromPrototype(originalTypeNotNullable)
typesFromSmartCast = listOf(originalTypeNotNullable)
smartcastStability = expressionWithSmartcastIfStable.smartcastStability
}
else -> expressionWithSmartcastIfStable.originalExpression
}
}
return visible
return ExpressionReceiverValue(expressionForReceiver)
}
private fun FirMemberDeclaration.getBackingFieldIfApplicable(): FirBackingField? {
@@ -138,11 +138,7 @@ class MemberScopeTowerLevel(
}
val visibleCandidatesFromSmartcast = visibleCandidates.filter { candidatesMapping.getValue(it) }
if (visibleCandidatesFromSmartcast.isNotEmpty()) {
candidates += visibleCandidatesFromSmartcast
} else {
group.filterNotTo(candidates) { candidatesMapping.getValue(it) }
}
candidates += visibleCandidatesFromSmartcast.ifEmpty { group }
}
consumeCandidates(output, candidates)
}
@@ -0,0 +1,16 @@
open class Base {
fun foo(): String {
return when (this) {
is Derived -> baz()
else -> "fail 1"
}
}
private fun baz(): String = "OK"
}
class Derived : Base()
fun box(): String {
return Derived().foo()
}
+21
View File
@@ -0,0 +1,21 @@
abstract class Base {
fun foo(): String {
return when (this) {
is Derived -> baz()
else -> "fail 1"
}
}
abstract fun bar(): String
private fun Derived.baz(): String = bar() + k
}
class Derived : Base() {
override fun bar(): String = "O"
val k: String get() = "K"
}
fun box(): String {
return Derived().foo()
}
@@ -0,0 +1,25 @@
// SKIP_TXT
// ISSUE: KT-52543
abstract class A {
fun foo(a: Any) {
if (a is A) {
a.prv()
if (a is B) {
a.<!INVISIBLE_REFERENCE!>prv<!>()
}
}
if (a is B) {
a.<!INVISIBLE_REFERENCE!>prv<!>()
if (<!USELESS_IS_CHECK!>a is A<!>) {
a.<!INVISIBLE_REFERENCE!>prv<!>()
}
}
}
private fun prv() {}
}
open class B : A()
@@ -0,0 +1,25 @@
// SKIP_TXT
// ISSUE: KT-52543
abstract class A {
fun foo(a: Any) {
if (a is A) {
<!DEBUG_INFO_SMARTCAST!>a<!>.prv()
if (a is B) {
<!DEBUG_INFO_SMARTCAST!>a<!>.prv()
}
}
if (a is B) {
<!DEBUG_INFO_SMARTCAST!>a<!>.<!INVISIBLE_MEMBER!>prv<!>()
if (<!USELESS_IS_CHECK!>a is A<!>) {
<!DEBUG_INFO_SMARTCAST!>a<!>.<!INVISIBLE_MEMBER!>prv<!>()
}
}
}
private fun prv() {}
}
open class B : A()
@@ -0,0 +1,15 @@
// FIR_IDENTICAL
// SKIP_TXT
abstract class A {
fun foo(a: A) {
a.prv()
if (a is B) {
a.prv()
}
}
private fun prv() {}
}
abstract class B : A()
@@ -33592,6 +33592,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/visibility/innerNestedAndAnonymousClasses.kt");
}
@Test
@TestMetadata("invisiblePrivateThroughSubClass.kt")
public void testInvisiblePrivateThroughSubClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClass.kt");
}
@Test
@TestMetadata("invisiblePrivateThroughSubClassDoubleSmartCast.kt")
public void testInvisiblePrivateThroughSubClassDoubleSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClassDoubleSmartCast.kt");
}
@Test
@TestMetadata("invisiblePrivateThroughSubClassSmartCast.kt")
public void testInvisiblePrivateThroughSubClassSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/invisiblePrivateThroughSubClassSmartCast.kt");
}
@Test
@TestMetadata("invisibleSetterOfJavaClass.kt")
public void testInvisibleSetterOfJavaClass() throws Exception {
@@ -45095,6 +45095,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/smartCasts"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@Test
@TestMetadata("avoidSmartCastToDerivedForPrivate.kt")
public void testAvoidSmartCastToDerivedForPrivate() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/avoidSmartCastToDerivedForPrivate.kt");
}
@Test
@TestMetadata("complexExplicitReceiver.kt")
public void testComplexExplicitReceiver() throws Exception {
@@ -45215,6 +45221,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/smartCasts/kt48163_smartCastToThrowable.kt");
}
@Test
@TestMetadata("kt52432.kt")
public void testKt52432() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt52432.kt");
}
@Test
@TestMetadata("lambdaArgumentWithoutType.kt")
public void testLambdaArgumentWithoutType() throws Exception {
@@ -45671,6 +45671,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/smartCasts"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("avoidSmartCastToDerivedForPrivate.kt")
public void testAvoidSmartCastToDerivedForPrivate() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/avoidSmartCastToDerivedForPrivate.kt");
}
@Test
@TestMetadata("complexExplicitReceiver.kt")
public void testComplexExplicitReceiver() throws Exception {
@@ -45791,6 +45797,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/smartCasts/kt48163_smartCastToThrowable.kt");
}
@Test
@TestMetadata("kt52432.kt")
public void testKt52432() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt52432.kt");
}
@Test
@TestMetadata("lambdaArgumentWithoutType.kt")
public void testLambdaArgumentWithoutType() throws Exception {
@@ -36494,6 +36494,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/smartCasts"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("avoidSmartCastToDerivedForPrivate.kt")
public void testAvoidSmartCastToDerivedForPrivate() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/avoidSmartCastToDerivedForPrivate.kt");
}
@TestMetadata("complexExplicitReceiver.kt")
public void testComplexExplicitReceiver() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/complexExplicitReceiver.kt");
@@ -36594,6 +36599,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/smartCasts/kt48163_smartCastToThrowable.kt");
}
@TestMetadata("kt52432.kt")
public void testKt52432() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt52432.kt");
}
@TestMetadata("lambdaArgumentWithoutType.kt")
public void testLambdaArgumentWithoutType() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
@@ -32791,6 +32791,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/smartCasts"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@Test
@TestMetadata("avoidSmartCastToDerivedForPrivate.kt")
public void testAvoidSmartCastToDerivedForPrivate() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/avoidSmartCastToDerivedForPrivate.kt");
}
@Test
@TestMetadata("complexExplicitReceiver.kt")
public void testComplexExplicitReceiver() throws Exception {
@@ -32893,6 +32899,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/smartCasts/kt44942.kt");
}
@Test
@TestMetadata("kt52432.kt")
public void testKt52432() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt52432.kt");
}
@Test
@TestMetadata("lambdaArgumentWithoutType.kt")
public void testLambdaArgumentWithoutType() throws Exception {
@@ -32893,6 +32893,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/smartCasts"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@Test
@TestMetadata("avoidSmartCastToDerivedForPrivate.kt")
public void testAvoidSmartCastToDerivedForPrivate() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/avoidSmartCastToDerivedForPrivate.kt");
}
@Test
@TestMetadata("complexExplicitReceiver.kt")
public void testComplexExplicitReceiver() throws Exception {
@@ -32995,6 +33001,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/smartCasts/kt44942.kt");
}
@Test
@TestMetadata("kt52432.kt")
public void testKt52432() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt52432.kt");
}
@Test
@TestMetadata("lambdaArgumentWithoutType.kt")
public void testLambdaArgumentWithoutType() throws Exception {
@@ -29453,6 +29453,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/smartCasts"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@TestMetadata("avoidSmartCastToDerivedForPrivate.kt")
public void testAvoidSmartCastToDerivedForPrivate() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/avoidSmartCastToDerivedForPrivate.kt");
}
@TestMetadata("complexExplicitReceiver.kt")
public void testComplexExplicitReceiver() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/complexExplicitReceiver.kt");
@@ -29538,6 +29543,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/smartCasts/kt44942.kt");
}
@TestMetadata("kt52432.kt")
public void testKt52432() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt52432.kt");
}
@TestMetadata("lambdaArgumentWithoutType.kt")
public void testLambdaArgumentWithoutType() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
@@ -35902,6 +35902,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/smartCasts"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
@Test
@TestMetadata("avoidSmartCastToDerivedForPrivate.kt")
public void testAvoidSmartCastToDerivedForPrivate() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/avoidSmartCastToDerivedForPrivate.kt");
}
@Test
@TestMetadata("complexExplicitReceiver.kt")
public void testComplexExplicitReceiver() throws Exception {
@@ -36004,6 +36010,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/smartCasts/kt44942.kt");
}
@Test
@TestMetadata("kt52432.kt")
public void testKt52432() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt52432.kt");
}
@Test
@TestMetadata("lambdaArgumentWithoutType.kt")
public void testLambdaArgumentWithoutType() throws Exception {