From d16e5e5e504e7ee6b30a3d7c84183283c341e701 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 12 Jul 2022 10:25:42 +0200 Subject: [PATCH] FIR: Support checking PRIVATE_TO_THIS visibility #KT-49875 Fixed --- .../kotlin/fir/FirVisibilityChecker.kt | 23 ++++++++++++++++++- .../bound/privateToThis.fir.kt | 4 ++-- .../privateToThis/FunctionCall.fir.kt | 8 +++---- .../variance/privateToThis/GetVal.fir.kt | 8 +++---- .../variance/privateToThis/SetVar.fir.kt | 8 +++---- .../tests/visibility/privateToThis.fir.kt | 2 +- .../tests/visibility/privateToThis.fir.txt | 2 +- 7 files changed, 38 insertions(+), 17 deletions(-) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt index 0befc4c0eaa..2e16716c23a 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt @@ -12,10 +12,12 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression +import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol +import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider @@ -243,8 +245,9 @@ abstract class FirVisibilityChecker : FirSessionComponent { } if (dispatchReceiver != null) { + val fir = symbol.fir val dispatchReceiverParameterClassSymbol = - (symbol.fir as? FirCallableDeclaration) + (fir as? FirCallableDeclaration) ?.propertyIfAccessor?.propertyIfBackingField ?.dispatchReceiverClassOrNull()?.toSymbol(session) ?: return true @@ -260,6 +263,24 @@ abstract class FirVisibilityChecker : FirSessionComponent { ) if (dispatchReceiverParameterClassLookupTag != dispatchReceiverValueOwnerLookupTag) return false + if (fir.visibility == Visibilities.PrivateToThis) { + when (dispatchReceiver) { + is ExpressionReceiverValue -> { + val explicitReceiver = dispatchReceiver.explicitReceiver + if (explicitReceiver !is FirThisReceiverExpression) { + return false + } + if (explicitReceiver.calleeReference.boundSymbol != dispatchReceiverParameterClassSymbol) { + return false + } + } + is ImplicitReceiverValue<*> -> { + if (dispatchReceiver.boundSymbol != dispatchReceiverParameterClassSymbol) { + return false + } + } + } + } } for (declaration in containingDeclarationOfUseSite) { diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/privateToThis.fir.kt b/compiler/testData/diagnostics/tests/callableReference/bound/privateToThis.fir.kt index e578a364358..442c3627147 100644 --- a/compiler/testData/diagnostics/tests/callableReference/bound/privateToThis.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/bound/privateToThis.fir.kt @@ -9,7 +9,7 @@ class Foo(name: T) { val ok2 = this@Foo::prop val ok3 = object { val y: Any = this@Foo::prop } - val fail1 = Foo(prop)::prop + val fail1 = Foo(prop)::prop } fun testFunc() { @@ -17,7 +17,7 @@ class Foo(name: T) { val ok2 = this@Foo::func val ok3 = object { val y: Any = this@Foo::func } - val fail1 = Foo(prop)::func + val fail1 = Foo(prop)::func } private fun func(t: T): T = t diff --git a/compiler/testData/diagnostics/tests/variance/privateToThis/FunctionCall.fir.kt b/compiler/testData/diagnostics/tests/variance/privateToThis/FunctionCall.fir.kt index 596158fe1c6..b04690f6481 100644 --- a/compiler/testData/diagnostics/tests/variance/privateToThis/FunctionCall.fir.kt +++ b/compiler/testData/diagnostics/tests/variance/privateToThis/FunctionCall.fir.kt @@ -15,19 +15,19 @@ class Test { apply(this.foo()) with(Test()) { apply(foo()) // resolved to this@Test.foo - apply(this.foo()) - apply(this@with.foo()) + apply(this.foo()) + apply(this@with.foo()) apply(this@Test.foo()) } } fun test(t: Test) { - t.apply(t.foo()) + t.apply(t.foo()) } companion object { fun test(t: Test) { - t.apply(t.foo()) + t.apply(t.foo()) } } } diff --git a/compiler/testData/diagnostics/tests/variance/privateToThis/GetVal.fir.kt b/compiler/testData/diagnostics/tests/variance/privateToThis/GetVal.fir.kt index 41e4388514b..61622ca5eba 100644 --- a/compiler/testData/diagnostics/tests/variance/privateToThis/GetVal.fir.kt +++ b/compiler/testData/diagnostics/tests/variance/privateToThis/GetVal.fir.kt @@ -15,19 +15,19 @@ class Test { apply(this.i) with(Test()) { apply(i) // resolved to this@Test.i - apply(this.i) - apply(this@with.i) + apply(this.i) + apply(this@with.i) apply(this@Test.i) } } fun test(t: Test) { - t.apply(t.i) + t.apply(t.i) } companion object { fun test(t: Test) { - t.apply(t.i) + t.apply(t.i) } } } diff --git a/compiler/testData/diagnostics/tests/variance/privateToThis/SetVar.fir.kt b/compiler/testData/diagnostics/tests/variance/privateToThis/SetVar.fir.kt index 2e60cdab406..1f9d8ef2c99 100644 --- a/compiler/testData/diagnostics/tests/variance/privateToThis/SetVar.fir.kt +++ b/compiler/testData/diagnostics/tests/variance/privateToThis/SetVar.fir.kt @@ -15,19 +15,19 @@ class Test { this.i = getT() with(Test()) { i = getT() // resolved to this@Test.i - this.i = getT() - this@with.i = getT() + this.i = getT() + this@with.i = getT() this@Test.i = getT() } } fun test(t: Test) { - t.i = getT() + t.i = getT() } companion object { fun test(t: Test) { - t.i = getT() + t.i = getT() } } } diff --git a/compiler/testData/diagnostics/tests/visibility/privateToThis.fir.kt b/compiler/testData/diagnostics/tests/visibility/privateToThis.fir.kt index 52c6a704545..ba1de56c81e 100644 --- a/compiler/testData/diagnostics/tests/visibility/privateToThis.fir.kt +++ b/compiler/testData/diagnostics/tests/visibility/privateToThis.fir.kt @@ -9,6 +9,6 @@ class A(t: T) { } fun foo(a: A) { - val x: String = a.t // Invisible! + val x: String = a.t // Invisible! } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/visibility/privateToThis.fir.txt b/compiler/testData/diagnostics/tests/visibility/privateToThis.fir.txt index acf2117f5e5..58de82c9300 100644 --- a/compiler/testData/diagnostics/tests/visibility/privateToThis.fir.txt +++ b/compiler/testData/diagnostics/tests/visibility/privateToThis.fir.txt @@ -13,7 +13,7 @@ FILE: privateToThis.fir.kt } public final fun foo(a: R|A|): R|kotlin/Unit| { - lval x: R|kotlin/String| = R|/a|.R|SubstitutionOverride| + lval x: R|kotlin/String| = R|/a|.# } }