FIR: Support checking PRIVATE_TO_THIS visibility #KT-49875 Fixed
This commit is contained in:
@@ -12,10 +12,12 @@ import org.jetbrains.kotlin.fir.declarations.*
|
|||||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
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.references.FirSuperReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
|
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.calls.ReceiverValue
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
@@ -243,8 +245,9 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dispatchReceiver != null) {
|
if (dispatchReceiver != null) {
|
||||||
|
val fir = symbol.fir
|
||||||
val dispatchReceiverParameterClassSymbol =
|
val dispatchReceiverParameterClassSymbol =
|
||||||
(symbol.fir as? FirCallableDeclaration)
|
(fir as? FirCallableDeclaration)
|
||||||
?.propertyIfAccessor?.propertyIfBackingField
|
?.propertyIfAccessor?.propertyIfBackingField
|
||||||
?.dispatchReceiverClassOrNull()?.toSymbol(session)
|
?.dispatchReceiverClassOrNull()?.toSymbol(session)
|
||||||
?: return true
|
?: return true
|
||||||
@@ -260,6 +263,24 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (dispatchReceiverParameterClassLookupTag != dispatchReceiverValueOwnerLookupTag) return false
|
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) {
|
for (declaration in containingDeclarationOfUseSite) {
|
||||||
|
|||||||
+2
-2
@@ -9,7 +9,7 @@ class Foo<out T>(name: T) {
|
|||||||
val ok2 = this@Foo::prop
|
val ok2 = this@Foo::prop
|
||||||
val ok3 = object { val y: Any = this@Foo::prop }
|
val ok3 = object { val y: Any = this@Foo::prop }
|
||||||
|
|
||||||
val fail1 = Foo(prop)::prop
|
val fail1 = Foo(prop)::<!UNRESOLVED_REFERENCE!>prop<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testFunc() {
|
fun testFunc() {
|
||||||
@@ -17,7 +17,7 @@ class Foo<out T>(name: T) {
|
|||||||
val ok2 = this@Foo::func
|
val ok2 = this@Foo::func
|
||||||
val ok3 = object { val y: Any = this@Foo::func }
|
val ok3 = object { val y: Any = this@Foo::func }
|
||||||
|
|
||||||
val fail1 = Foo(prop)::func
|
val fail1 = Foo(prop)::<!UNRESOLVED_REFERENCE!>func<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun func(t: T): T = t
|
private fun func(t: T): T = t
|
||||||
|
|||||||
+4
-4
@@ -15,19 +15,19 @@ class Test<in I> {
|
|||||||
apply(this.foo())
|
apply(this.foo())
|
||||||
with(Test<I>()) {
|
with(Test<I>()) {
|
||||||
apply(foo()) // resolved to this@Test.foo
|
apply(foo()) // resolved to this@Test.foo
|
||||||
apply(this.foo())
|
apply(this.<!INVISIBLE_REFERENCE!>foo<!>())
|
||||||
apply(this@with.foo())
|
apply(this@with.<!INVISIBLE_REFERENCE!>foo<!>())
|
||||||
apply(this@Test.foo())
|
apply(this@Test.foo())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <I> test(t: Test<I>) {
|
fun <I> test(t: Test<I>) {
|
||||||
t.apply(t.foo())
|
t.apply(t.<!INVISIBLE_REFERENCE!>foo<!>())
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun <I> test(t: Test<I>) {
|
fun <I> test(t: Test<I>) {
|
||||||
t.apply(t.foo())
|
t.apply(t.<!INVISIBLE_REFERENCE!>foo<!>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,19 +15,19 @@ class Test<in I, out O> {
|
|||||||
apply(this.i)
|
apply(this.i)
|
||||||
with(Test<I, O>()) {
|
with(Test<I, O>()) {
|
||||||
apply(i) // resolved to this@Test.i
|
apply(i) // resolved to this@Test.i
|
||||||
apply(this.i)
|
apply(this.<!INVISIBLE_REFERENCE!>i<!>)
|
||||||
apply(this@with.i)
|
apply(this@with.<!INVISIBLE_REFERENCE!>i<!>)
|
||||||
apply(this@Test.i)
|
apply(this@Test.i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <I, O> test(t: Test<I, O>) {
|
fun <I, O> test(t: Test<I, O>) {
|
||||||
t.apply(t.i)
|
t.apply(t.<!INVISIBLE_REFERENCE!>i<!>)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun <I, O> test(t: Test<I, O>) {
|
fun <I, O> test(t: Test<I, O>) {
|
||||||
t.apply(t.i)
|
t.apply(t.<!INVISIBLE_REFERENCE!>i<!>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,19 +15,19 @@ class Test<in I, out O> {
|
|||||||
this.i = getT()
|
this.i = getT()
|
||||||
with(Test<I, O>()) {
|
with(Test<I, O>()) {
|
||||||
i = getT() // resolved to this@Test.i
|
i = getT() // resolved to this@Test.i
|
||||||
this.i = getT()
|
this.<!INVISIBLE_REFERENCE!>i<!> = getT()
|
||||||
this@with.i = getT()
|
this@with.<!INVISIBLE_REFERENCE!>i<!> = getT()
|
||||||
this@Test.i = getT()
|
this@Test.i = getT()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <I, O> test(t: Test<I, O>) {
|
fun <I, O> test(t: Test<I, O>) {
|
||||||
t.i = getT()
|
t.<!INVISIBLE_REFERENCE!>i<!> = getT()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun <I, O> test(t: Test<I, O>) {
|
fun <I, O> test(t: Test<I, O>) {
|
||||||
t.i = getT()
|
t.<!INVISIBLE_REFERENCE!>i<!> = getT()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ class A<in T>(t: T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun foo(a: A<String>) {
|
fun foo(a: A<String>) {
|
||||||
val x: String = a.t // Invisible!
|
val x: String = a.<!INVISIBLE_REFERENCE!>t<!> // Invisible!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ FILE: privateToThis.fir.kt
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final fun foo(a: R|A<kotlin/String>|): R|kotlin/Unit| {
|
public final fun foo(a: R|A<kotlin/String>|): R|kotlin/Unit| {
|
||||||
lval x: R|kotlin/String| = R|<local>/a|.R|SubstitutionOverride</A.t: R|kotlin/String|>|
|
lval x: R|kotlin/String| = R|<local>/a|.<HIDDEN: /A.t is invisible>#
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user