[FIR] Move check for _private-to-this_ visibility into checker
^KT-55446 ^KT-65790 Fixed
This commit is contained in:
committed by
Space Team
parent
5fe1e0c1a5
commit
c64575f4a2
+1
@@ -54,6 +54,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
FirMissingDependencyClassChecker,
|
FirMissingDependencyClassChecker,
|
||||||
FirMissingDependencySupertypeInQualifiedAccessExpressionsChecker,
|
FirMissingDependencySupertypeInQualifiedAccessExpressionsChecker,
|
||||||
FirArrayOfNothingQualifierChecker,
|
FirArrayOfNothingQualifierChecker,
|
||||||
|
FirPrivateToThisAccessChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val callCheckers: Set<FirCallChecker>
|
override val callCheckers: Set<FirCallChecker>
|
||||||
|
|||||||
+158
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
|
import org.jetbrains.kotlin.diagnostics.*
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.toReference
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirThisReference
|
||||||
|
import org.jetbrains.kotlin.fir.references.resolved
|
||||||
|
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeSetterVisibilityError
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeVisibilityError
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.toClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
|
||||||
|
import org.jetbrains.kotlin.types.EnrichedProjectionKind
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
|
||||||
|
object FirPrivateToThisAccessChecker : FirQualifiedAccessExpressionChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val reference = expression.calleeReference.resolved ?: return
|
||||||
|
if (reference is FirResolvedErrorReference) {
|
||||||
|
// If there was a visibility diagnostic, no need to report another one about visibility
|
||||||
|
when (reference.diagnostic) {
|
||||||
|
is ConeVisibilityError,
|
||||||
|
is ConeSetterVisibilityError -> return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val dispatchReceiver = expression.dispatchReceiver ?: return
|
||||||
|
val symbol = reference.toResolvedCallableSymbol(discardErrorReference = true) ?: return
|
||||||
|
if (symbol.visibility != Visibilities.Private) return
|
||||||
|
val session = context.session
|
||||||
|
val containingClassSymbol = symbol.containingClassLookupTag()?.toClassSymbol(session)
|
||||||
|
|
||||||
|
if (!isPrivateToThis(symbol.unwrapFakeOverrides(), containingClassSymbol, session)) return
|
||||||
|
|
||||||
|
val invisible = when (val receiverReference = dispatchReceiver.toReference(session)) {
|
||||||
|
is FirThisReference -> receiverReference.boundSymbol != containingClassSymbol
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invisible) {
|
||||||
|
reporter.reportOn(
|
||||||
|
source = expression.source,
|
||||||
|
factory = FirErrors.INVISIBLE_REFERENCE,
|
||||||
|
symbol,
|
||||||
|
Visibilities.PrivateToThis,
|
||||||
|
symbol.callableId.classId,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isPrivateToThis(
|
||||||
|
symbol: FirCallableSymbol<*>,
|
||||||
|
containingClassSymbol: FirClassSymbol<*>?,
|
||||||
|
session: FirSession
|
||||||
|
): Boolean {
|
||||||
|
if (containingClassSymbol == null) return false
|
||||||
|
if (symbol is FirConstructorSymbol) return false
|
||||||
|
if (containingClassSymbol.typeParameterSymbols.all { it.variance == Variance.INVARIANT }) return false
|
||||||
|
|
||||||
|
if (symbol.receiverParameter?.typeRef?.coneType?.contradictsWith(Variance.IN_VARIANCE, session) == true) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (symbol.resolvedReturnType.contradictsWith(
|
||||||
|
if (symbol is FirPropertySymbol && symbol.isVar) Variance.INVARIANT
|
||||||
|
else Variance.OUT_VARIANCE,
|
||||||
|
session
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (symbol is FirFunctionSymbol<*>) {
|
||||||
|
for (parameter in symbol.valueParameterSymbols) {
|
||||||
|
if (parameter.resolvedReturnType.contradictsWith(Variance.IN_VARIANCE, session)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ConeKotlinType.contradictsWith(requiredVariance: Variance, session: FirSession): Boolean {
|
||||||
|
when (this) {
|
||||||
|
is ConeLookupTagBasedType -> {
|
||||||
|
if (this is ConeTypeParameterType) {
|
||||||
|
return !this.lookupTag.typeParameterSymbol.variance.allowsPosition(requiredVariance)
|
||||||
|
}
|
||||||
|
if (this is ConeClassLikeType) {
|
||||||
|
// It's safe to access fir here, because later we access only variance of type parameters of the class
|
||||||
|
// And variance can not be changed after raw fir stage
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
val classLike = this.lookupTag.toSymbol(session)?.fir ?: return false
|
||||||
|
for ((index, argument) in this.typeArguments.withIndex()) {
|
||||||
|
val typeParameterRef = classLike.typeParameters.getOrNull(index)
|
||||||
|
if (typeParameterRef !is FirTypeParameter) continue
|
||||||
|
val requiredVarianceForArgument = when (
|
||||||
|
EnrichedProjectionKind.getEffectiveProjectionKind(typeParameterRef.variance, argument.variance)
|
||||||
|
) {
|
||||||
|
EnrichedProjectionKind.OUT -> requiredVariance
|
||||||
|
EnrichedProjectionKind.IN -> requiredVariance.opposite()
|
||||||
|
EnrichedProjectionKind.INV -> Variance.INVARIANT
|
||||||
|
EnrichedProjectionKind.STAR -> continue // CONFLICTING_PROJECTION error was reported
|
||||||
|
}
|
||||||
|
val argType = argument.type ?: continue
|
||||||
|
if (argType.contradictsWith(requiredVarianceForArgument, session)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is ConeFlexibleType -> {
|
||||||
|
return lowerBound.contradictsWith(requiredVariance, session)
|
||||||
|
}
|
||||||
|
is ConeDefinitelyNotNullType -> {
|
||||||
|
return original.contradictsWith(requiredVariance, session)
|
||||||
|
}
|
||||||
|
is ConeIntersectionType -> {
|
||||||
|
return this.intersectedTypes.any { it.contradictsWith(requiredVariance, session) }
|
||||||
|
}
|
||||||
|
is ConeCapturedType -> {
|
||||||
|
// Looks like not possible here
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
is ConeIntegerConstantOperatorType,
|
||||||
|
is ConeIntegerLiteralConstantType,
|
||||||
|
is ConeStubTypeForChainInference,
|
||||||
|
is ConeStubTypeForTypeVariableInSubtyping,
|
||||||
|
is ConeTypeVariableType,
|
||||||
|
-> return false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private val ConeTypeProjection.variance: Variance
|
||||||
|
get() = when (this.kind) {
|
||||||
|
ProjectionKind.STAR -> Variance.OUT_VARIANCE
|
||||||
|
ProjectionKind.IN -> Variance.IN_VARIANCE
|
||||||
|
ProjectionKind.OUT -> Variance.OUT_VARIANCE
|
||||||
|
ProjectionKind.INVARIANT -> Variance.INVARIANT
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,6 +61,12 @@ fun ConeClassLikeLookupTag.toSymbol(useSiteSession: FirSession): FirClassLikeSym
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see toSymbol
|
||||||
|
*/
|
||||||
|
fun ConeClassLikeLookupTag.toClassSymbol(session: FirSession): FirClassSymbol<*>? =
|
||||||
|
toSymbol(session) as? FirClassSymbol<*>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see toSymbol
|
* @see toSymbol
|
||||||
*/
|
*/
|
||||||
|
|||||||
+2
-107
@@ -15,15 +15,12 @@ import org.jetbrains.kotlin.fir.extensions.FirStatusTransformerExtension
|
|||||||
import org.jetbrains.kotlin.fir.extensions.extensionService
|
import org.jetbrains.kotlin.fir.extensions.extensionService
|
||||||
import org.jetbrains.kotlin.fir.extensions.statusTransformerExtensions
|
import org.jetbrains.kotlin.fir.extensions.statusTransformerExtensions
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
import org.jetbrains.kotlin.fir.toEffectiveVisibility
|
import org.jetbrains.kotlin.fir.toEffectiveVisibility
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
|
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
|
||||||
import org.jetbrains.kotlin.fir.visibilityChecker
|
import org.jetbrains.kotlin.fir.visibilityChecker
|
||||||
import org.jetbrains.kotlin.types.EnrichedProjectionKind
|
|
||||||
import org.jetbrains.kotlin.types.Variance
|
|
||||||
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
||||||
|
|
||||||
class FirStatusResolver(
|
class FirStatusResolver(
|
||||||
@@ -41,7 +38,7 @@ class FirStatusResolver(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val MODIFIERS_FROM_OVERRIDDEN: List<FirDeclarationStatusImpl.Modifier> =
|
private val MODIFIERS_FROM_OVERRIDDEN: List<FirDeclarationStatusImpl.Modifier> =
|
||||||
FirDeclarationStatusImpl.Modifier.values().toList() - NOT_INHERITED_MODIFIERS
|
FirDeclarationStatusImpl.Modifier.entries - NOT_INHERITED_MODIFIERS
|
||||||
}
|
}
|
||||||
|
|
||||||
private val extensionStatusTransformers = session.extensionService.statusTransformerExtensions
|
private val extensionStatusTransformers = session.extensionService.statusTransformerExtensions
|
||||||
@@ -247,18 +244,7 @@ class FirStatusResolver(
|
|||||||
isLocal -> Visibilities.Local
|
isLocal -> Visibilities.Local
|
||||||
else -> resolveVisibility(declaration, containingClass, containingProperty, overriddenStatuses)
|
else -> resolveVisibility(declaration, containingClass, containingProperty, overriddenStatuses)
|
||||||
}
|
}
|
||||||
|
Visibilities.Private -> Visibilities.Private
|
||||||
Visibilities.Private -> when {
|
|
||||||
declaration is FirPropertyAccessor -> if (containingProperty?.visibility == Visibilities.PrivateToThis) {
|
|
||||||
Visibilities.PrivateToThis
|
|
||||||
} else {
|
|
||||||
Visibilities.Private
|
|
||||||
}
|
|
||||||
|
|
||||||
isPrivateToThis(declaration, containingClass) -> Visibilities.PrivateToThis
|
|
||||||
else -> Visibilities.Private
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> status.visibility
|
else -> status.visibility
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,97 +303,6 @@ class FirStatusResolver(
|
|||||||
return status.resolved(visibility, modality, effectiveVisibility)
|
return status.resolved(visibility, modality, effectiveVisibility)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isPrivateToThis(
|
|
||||||
declaration: FirDeclaration,
|
|
||||||
containingClass: FirClass?,
|
|
||||||
): Boolean {
|
|
||||||
if (containingClass == null) return false
|
|
||||||
if (declaration !is FirCallableDeclaration) return false
|
|
||||||
if (declaration is FirConstructor) return false
|
|
||||||
if (containingClass.typeParameters.all { it.symbol.variance == Variance.INVARIANT }) return false
|
|
||||||
|
|
||||||
if (declaration.receiverParameter?.typeRef?.contradictsWith(Variance.IN_VARIANCE) == true) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (declaration.returnTypeRef.contradictsWith(
|
|
||||||
if (declaration is FirProperty && declaration.isVar) Variance.INVARIANT
|
|
||||||
else Variance.OUT_VARIANCE
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (declaration is FirFunction) {
|
|
||||||
for (parameter in declaration.valueParameters) {
|
|
||||||
if (parameter.returnTypeRef.contradictsWith(Variance.IN_VARIANCE)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirTypeRef.contradictsWith(requiredVariance: Variance): Boolean {
|
|
||||||
val type = coneTypeSafe<ConeKotlinType>() ?: return false
|
|
||||||
return contradictsWith(type, requiredVariance)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun contradictsWith(type: ConeKotlinType, requiredVariance: Variance): Boolean {
|
|
||||||
when (type) {
|
|
||||||
is ConeLookupTagBasedType -> {
|
|
||||||
if (type is ConeTypeParameterType) {
|
|
||||||
return !type.lookupTag.typeParameterSymbol.fir.variance.allowsPosition(requiredVariance)
|
|
||||||
}
|
|
||||||
if (type is ConeClassLikeType) {
|
|
||||||
val classLike = type.lookupTag.toSymbol(session)?.fir
|
|
||||||
for ((index, argument) in type.typeArguments.withIndex()) {
|
|
||||||
val typeParameterRef = classLike?.typeParameters?.getOrNull(index)
|
|
||||||
if (typeParameterRef !is FirTypeParameter) continue
|
|
||||||
val requiredVarianceForArgument = when (
|
|
||||||
EnrichedProjectionKind.getEffectiveProjectionKind(typeParameterRef.variance, argument.variance)
|
|
||||||
) {
|
|
||||||
EnrichedProjectionKind.OUT -> requiredVariance
|
|
||||||
EnrichedProjectionKind.IN -> requiredVariance.opposite()
|
|
||||||
EnrichedProjectionKind.INV -> Variance.INVARIANT
|
|
||||||
EnrichedProjectionKind.STAR -> continue // CONFLICTING_PROJECTION error was reported
|
|
||||||
}
|
|
||||||
val argType = argument.type ?: continue
|
|
||||||
if (contradictsWith(argType, requiredVarianceForArgument)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is ConeFlexibleType -> {
|
|
||||||
return contradictsWith(type.lowerBound, requiredVariance)
|
|
||||||
}
|
|
||||||
is ConeDefinitelyNotNullType -> {
|
|
||||||
return contradictsWith(type.original, requiredVariance)
|
|
||||||
}
|
|
||||||
is ConeIntersectionType -> {
|
|
||||||
return type.intersectedTypes.any { contradictsWith(it, requiredVariance) }
|
|
||||||
}
|
|
||||||
is ConeCapturedType -> {
|
|
||||||
// Looks like not possible here
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
is ConeIntegerConstantOperatorType,
|
|
||||||
is ConeIntegerLiteralConstantType,
|
|
||||||
is ConeStubTypeForChainInference,
|
|
||||||
is ConeStubTypeForTypeVariableInSubtyping,
|
|
||||||
is ConeTypeVariableType,
|
|
||||||
-> return false
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private val ConeTypeProjection.variance: Variance
|
|
||||||
get() = when (this.kind) {
|
|
||||||
ProjectionKind.STAR -> Variance.OUT_VARIANCE
|
|
||||||
ProjectionKind.IN -> Variance.IN_VARIANCE
|
|
||||||
ProjectionKind.OUT -> Variance.OUT_VARIANCE
|
|
||||||
ProjectionKind.INVARIANT -> Variance.INVARIANT
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resolveVisibility(
|
private fun resolveVisibility(
|
||||||
declaration: FirDeclaration,
|
declaration: FirDeclaration,
|
||||||
containingClass: FirClass?,
|
containingClass: FirClass?,
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ class Test<in I> {
|
|||||||
apply(foo())
|
apply(foo())
|
||||||
apply(this.foo())
|
apply(this.foo())
|
||||||
with(Test<I>()) {
|
with(Test<I>()) {
|
||||||
apply(foo()) // resolved to this@Test.foo
|
apply(<!INVISIBLE_REFERENCE!>foo<!>()) // K1: this@Test.foo, K2: this@with.foo, see KT-55446
|
||||||
apply(this.<!INVISIBLE_REFERENCE!>foo<!>())
|
apply(this.<!INVISIBLE_REFERENCE!>foo<!>())
|
||||||
apply(this@with.<!INVISIBLE_REFERENCE!>foo<!>())
|
apply(this@with.<!INVISIBLE_REFERENCE!>foo<!>())
|
||||||
apply(this@Test.foo())
|
apply(this@Test.foo())
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class Test<in I> {
|
|||||||
apply(foo())
|
apply(foo())
|
||||||
apply(this.foo())
|
apply(this.foo())
|
||||||
with(Test<I>()) {
|
with(Test<I>()) {
|
||||||
apply(foo()) // resolved to this@Test.foo
|
apply(foo()) // K1: this@Test.foo, K2: this@with.foo, see KT-55446
|
||||||
apply(this.<!INVISIBLE_MEMBER("foo; private/*private to this*/; 'Test'")!>foo<!>())
|
apply(this.<!INVISIBLE_MEMBER("foo; private/*private to this*/; 'Test'")!>foo<!>())
|
||||||
apply(this@with.<!INVISIBLE_MEMBER("foo; private/*private to this*/; 'Test'")!>foo<!>())
|
apply(this@with.<!INVISIBLE_MEMBER("foo; private/*private to this*/; 'Test'")!>foo<!>())
|
||||||
apply(this@Test.foo())
|
apply(this@Test.foo())
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class Test<in I, out O> {
|
|||||||
apply(i)
|
apply(i)
|
||||||
apply(this.i)
|
apply(this.i)
|
||||||
with(Test<I, O>()) {
|
with(Test<I, O>()) {
|
||||||
apply(i) // resolved to this@Test.i
|
apply(<!INVISIBLE_REFERENCE!>i<!>) // K1: this@Test.i, K2: this@with.i, see KT-55446
|
||||||
apply(this.<!INVISIBLE_REFERENCE!>i<!>)
|
apply(this.<!INVISIBLE_REFERENCE!>i<!>)
|
||||||
apply(this@with.<!INVISIBLE_REFERENCE!>i<!>)
|
apply(this@with.<!INVISIBLE_REFERENCE!>i<!>)
|
||||||
apply(this@Test.i)
|
apply(this@Test.i)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class Test<in I, out O> {
|
|||||||
apply(i)
|
apply(i)
|
||||||
apply(this.i)
|
apply(this.i)
|
||||||
with(Test<I, O>()) {
|
with(Test<I, O>()) {
|
||||||
apply(i) // resolved to this@Test.i
|
apply(i) // K1: this@Test.i, K2: this@with.i, see KT-55446
|
||||||
apply(this.<!INVISIBLE_MEMBER("i; private/*private to this*/; 'Test'")!>i<!>)
|
apply(this.<!INVISIBLE_MEMBER("i; private/*private to this*/; 'Test'")!>i<!>)
|
||||||
apply(this@with.<!INVISIBLE_MEMBER("i; private/*private to this*/; 'Test'")!>i<!>)
|
apply(this@with.<!INVISIBLE_MEMBER("i; private/*private to this*/; 'Test'")!>i<!>)
|
||||||
apply(this@Test.i)
|
apply(this@Test.i)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class Test<in I, out O> {
|
|||||||
i = getT()
|
i = getT()
|
||||||
this.i = getT()
|
this.i = getT()
|
||||||
with(Test<I, O>()) {
|
with(Test<I, O>()) {
|
||||||
i = getT() // resolved to this@Test.i
|
<!INVISIBLE_REFERENCE!>i<!> = getT() // K1: this@Test.i, K2: this@with.i, see KT-55446
|
||||||
this.<!INVISIBLE_REFERENCE!>i<!> = getT()
|
this.<!INVISIBLE_REFERENCE!>i<!> = getT()
|
||||||
this@with.<!INVISIBLE_REFERENCE!>i<!> = getT()
|
this@with.<!INVISIBLE_REFERENCE!>i<!> = getT()
|
||||||
this@Test.i = getT()
|
this@Test.i = getT()
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class Test<in I, out O> {
|
|||||||
i = getT()
|
i = getT()
|
||||||
this.i = getT()
|
this.i = getT()
|
||||||
with(Test<I, O>()) {
|
with(Test<I, O>()) {
|
||||||
i = getT() // resolved to this@Test.i
|
i = getT() // K1: this@Test.i, K2: this@with.i, see KT-55446
|
||||||
this.<!INVISIBLE_MEMBER("i; private/*private to this*/; 'Test'")!>i<!> = getT()
|
this.<!INVISIBLE_MEMBER("i; private/*private to this*/; 'Test'")!>i<!> = getT()
|
||||||
this@with.<!INVISIBLE_MEMBER("i; private/*private to this*/; 'Test'")!>i<!> = getT()
|
this@with.<!INVISIBLE_MEMBER("i; private/*private to this*/; 'Test'")!>i<!> = getT()
|
||||||
this@Test.i = getT()
|
this@Test.i = getT()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// FIR_DUMP
|
// FIR_DUMP
|
||||||
|
|
||||||
|
// explicit types
|
||||||
class A<in T>(t: T) {
|
class A<in T>(t: T) {
|
||||||
private val t: T = t // PRIVATE_TO_THIS
|
private val t: T = t // PRIVATE_TO_THIS
|
||||||
|
|
||||||
@@ -24,3 +25,13 @@ class A<in T>(t: T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// implicit types
|
||||||
|
class C<in T>(t: T) {
|
||||||
|
private val t: T = t
|
||||||
|
private val tt = t
|
||||||
|
|
||||||
|
fun foo(a: C<String>) {
|
||||||
|
val x: String = a.<!INVISIBLE_REFERENCE!>tt<!>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ FILE: privateToThis.fir.kt
|
|||||||
super<R|kotlin/Any|>()
|
super<R|kotlin/Any|>()
|
||||||
}
|
}
|
||||||
|
|
||||||
private/*private to this*/ final val t: R|T| = R|<local>/t|
|
private final val t: R|T| = R|<local>/t|
|
||||||
private/*private to this*/ get(): R|T|
|
private get(): R|T|
|
||||||
|
|
||||||
private final val i: R|A.B<T>| = this@R|/A|.R|SubstitutionOverride</A.B.B>|()
|
private final val i: R|A.B<T>| = this@R|/A|.R|SubstitutionOverride</A.B.B>|()
|
||||||
private get(): R|A.B<T>|
|
private get(): R|A.B<T>|
|
||||||
@@ -16,11 +16,11 @@ 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|><HIDDEN: /A.t is invisible>#|
|
lval x: R|kotlin/String| = R|<local>/a|.R|SubstitutionOverride</A.t: R|kotlin/String|>|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final fun bar(a: R|A<*>|): R|kotlin/Unit| {
|
public final fun bar(a: R|A<*>|): R|kotlin/Unit| {
|
||||||
R|<local>/a|.R|SubstitutionOverride</A.t: R|CapturedType(*)|><HIDDEN: /A.t is invisible>#|
|
R|<local>/a|.R|SubstitutionOverride</A.t: R|CapturedType(*)|>|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final inner class B<in Outer(T)> : R|kotlin/Any| {
|
public final inner class B<in Outer(T)> : R|kotlin/Any| {
|
||||||
@@ -35,3 +35,19 @@ FILE: privateToThis.fir.kt
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
public final class C<in T> : R|kotlin/Any| {
|
||||||
|
public constructor<in T>(t: R|T|): R|C<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
private final val t: R|T| = R|<local>/t|
|
||||||
|
private get(): R|T|
|
||||||
|
|
||||||
|
private final val tt: R|T| = R|<local>/t|
|
||||||
|
private get(): R|T|
|
||||||
|
|
||||||
|
public final fun foo(a: R|C<kotlin/String>|): R|kotlin/Unit| {
|
||||||
|
lval x: R|kotlin/String| = R|<local>/a|.R|SubstitutionOverride</C.tt: R|kotlin/String|>|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// FIR_DUMP
|
// FIR_DUMP
|
||||||
|
|
||||||
|
// explicit types
|
||||||
class A<in T>(t: T) {
|
class A<in T>(t: T) {
|
||||||
private val t: T = t // PRIVATE_TO_THIS
|
private val t: T = t // PRIVATE_TO_THIS
|
||||||
|
|
||||||
@@ -24,3 +25,13 @@ class A<in T>(t: T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// implicit types
|
||||||
|
class C<in T>(t: T) {
|
||||||
|
private val t: T = t
|
||||||
|
private val tt = t
|
||||||
|
|
||||||
|
fun foo(a: C<String>) {
|
||||||
|
val x: String = a.<!INVISIBLE_MEMBER!>tt<!>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,3 +19,14 @@ public final class A</*0*/ in T> {
|
|||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class C</*0*/ in T> {
|
||||||
|
public constructor C</*0*/ in T>(/*0*/ t: T)
|
||||||
|
private/*private to this*/ final val t: T
|
||||||
|
private/*private to this*/ final val tt: T
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun foo(/*0*/ a: C<kotlin.String>): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ class Foo<in T> : Base<<!TYPE_VARIANCE_CONFLICT_ERROR!>T<!>>() {
|
|||||||
|
|
||||||
fun bar(f: Foo<Bar>) {
|
fun bar(f: Foo<Bar>) {
|
||||||
val dnn = f.<!INVISIBLE_REFERENCE!>dnn<!>
|
val dnn = f.<!INVISIBLE_REFERENCE!>dnn<!>
|
||||||
// This case (and any other with non-denotable type) requires KT-55446 to be fixed
|
val flex = f.<!INVISIBLE_REFERENCE!>flex<!>
|
||||||
val flex = f.flex
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ class Foo<in T> : Base<<!TYPE_VARIANCE_CONFLICT_ERROR!>T<!>>() {
|
|||||||
|
|
||||||
fun bar(f: Foo<Bar>) {
|
fun bar(f: Foo<Bar>) {
|
||||||
val dnn = f.<!INVISIBLE_MEMBER!>dnn<!>
|
val dnn = f.<!INVISIBLE_MEMBER!>dnn<!>
|
||||||
// This case (and any other with non-denotable type) requires KT-55446 to be fixed
|
|
||||||
val flex = f.<!INVISIBLE_MEMBER!>flex<!>
|
val flex = f.<!INVISIBLE_MEMBER!>flex<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -1,19 +1,19 @@
|
|||||||
public final class A<in I> : R|kotlin/Any| {
|
public final class A<in I> : R|kotlin/Any| {
|
||||||
private/*private to this*/ final fun bas(): R|I|
|
private final fun bas(): R|I|
|
||||||
|
|
||||||
private/*private to this*/ final val foo: R|I|
|
private final val foo: R|I|
|
||||||
private/*private to this*/ get(): R|I|
|
private get(): R|I|
|
||||||
|
|
||||||
private/*private to this*/ final var bar: R|I|
|
private final var bar: R|I|
|
||||||
private/*private to this*/ get(): R|I|
|
private get(): R|I|
|
||||||
private/*private to this*/ set(value: R|I|): R|kotlin/Unit|
|
private set(value: R|I|): R|kotlin/Unit|
|
||||||
|
|
||||||
private/*private to this*/ final val val_with_accessors: R|I|
|
private final val val_with_accessors: R|I|
|
||||||
private/*private to this*/ get(): R|I|
|
private get(): R|I|
|
||||||
|
|
||||||
private/*private to this*/ final var var_with_accessors: R|I|
|
private final var var_with_accessors: R|I|
|
||||||
private/*private to this*/ get(): R|I|
|
private get(): R|I|
|
||||||
private/*private to this*/ set(value: R|I|): R|kotlin/Unit|
|
private set(value: R|I|): R|kotlin/Unit|
|
||||||
|
|
||||||
public constructor<in I>(): R|test/A<I>|
|
public constructor<in I>(): R|test/A<I>|
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ object Visibilities {
|
|||||||
override fun mustCheckInImports(): Boolean = true
|
override fun mustCheckInImports(): Boolean = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// K2 doesn't use this visibility, see KT-55446 for details
|
||||||
object PrivateToThis : Visibility("private_to_this", isPublicAPI = false) {
|
object PrivateToThis : Visibility("private_to_this", isPublicAPI = false) {
|
||||||
override val internalDisplayName: String
|
override val internalDisplayName: String
|
||||||
get() = "private/*private to this*/"
|
get() = "private/*private to this*/"
|
||||||
|
|||||||
Reference in New Issue
Block a user