[FIR] Don't smartcast variables to invisible types
#KT-44802 Fixed
This commit is contained in:
+5
@@ -2885,6 +2885,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToNothing.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("smartcastToTypeParameter.kt")
|
||||
public void testSmartcastToTypeParameter() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToTypeParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
FILE: smartcastToTypeParameter.kt
|
||||
public abstract interface FirTypeScope : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface AbstractFirBasedSymbol<E : R|FirSymbolOwner<E>|, R|FirDeclaration|> : R|kotlin/Any| {
|
||||
public abstract val fir: R|E|
|
||||
public get(): R|E|
|
||||
|
||||
}
|
||||
public abstract interface FirCallableSymbol<D : R|FirCallableDeclaration<D>|> : R|AbstractFirBasedSymbol<D>| {
|
||||
}
|
||||
public abstract interface FirElement : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface FirSymbolOwner<E : R|FirSymbolOwner<E>|, R|FirDeclaration|> : R|FirElement| {
|
||||
public abstract val symbol: R|AbstractFirBasedSymbol<E>|
|
||||
public get(): R|AbstractFirBasedSymbol<E>|
|
||||
|
||||
}
|
||||
public abstract interface FirDeclaration : R|FirElement| {
|
||||
}
|
||||
public abstract interface FirCallableDeclaration<F : R|FirCallableDeclaration<F>|> : R|FirDeclaration|, R|FirSymbolOwner<F>| {
|
||||
}
|
||||
public abstract interface FirCallableMemberDeclaration<F : R|FirCallableMemberDeclaration<F>|> : R|FirCallableDeclaration<F>| {
|
||||
}
|
||||
private final inline fun <reified S : R|FirCallableSymbol<*>|> computeBaseSymbols(symbol: R|S|, basedSymbol: R|S|, directOverridden: R|FirTypeScope.(S) -> kotlin/collections/List<S>|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun R|FirCallableSymbol<*>|.dispatchReceiverClassOrNull(): R|kotlin/Boolean?| {
|
||||
^dispatchReceiverClassOrNull Boolean(true)
|
||||
}
|
||||
private final inline fun <reified D : R|FirCallableMemberDeclaration<D>|, reified S : R|FirCallableSymbol<D>|> createFakeOverriddenIfNeeded(originalSymbol: R|FirCallableSymbol<*>|, basedSymbol: R|S|, computeDirectOverridden: R|FirTypeScope.(S) -> kotlin/collections/List<S>|, someCondition: R|kotlin/Boolean|): R|kotlin/Unit| {
|
||||
when () {
|
||||
(R|<local>/originalSymbol| !is R|S|) -> {
|
||||
^createFakeOverriddenIfNeeded Unit
|
||||
}
|
||||
}
|
||||
|
||||
when () {
|
||||
==(R|<local>/originalSymbol|.R|/dispatchReceiverClassOrNull|(), Boolean(true)) && R|<local>/someCondition| -> {
|
||||
^createFakeOverriddenIfNeeded Unit
|
||||
}
|
||||
}
|
||||
|
||||
R|/computeBaseSymbols|<R|S|>(R|<local>/originalSymbol|, R|<local>/basedSymbol|, R|<local>/computeDirectOverridden|)
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
interface FirTypeScope
|
||||
|
||||
interface AbstractFirBasedSymbol<E> where E : FirSymbolOwner<E>, E : FirDeclaration {
|
||||
val fir: E
|
||||
}
|
||||
|
||||
interface FirCallableSymbol<D : FirCallableDeclaration<D>> : AbstractFirBasedSymbol<D>
|
||||
|
||||
interface FirElement
|
||||
interface FirSymbolOwner<E> : FirElement where E : FirSymbolOwner<E>, E : FirDeclaration {
|
||||
val symbol: AbstractFirBasedSymbol<E>
|
||||
}
|
||||
interface FirDeclaration : FirElement
|
||||
interface FirCallableDeclaration<F : FirCallableDeclaration<F>> : FirDeclaration, FirSymbolOwner<F>
|
||||
interface FirCallableMemberDeclaration<F : FirCallableMemberDeclaration<F>> : FirCallableDeclaration<F>
|
||||
|
||||
private inline fun <reified S : FirCallableSymbol<*>> computeBaseSymbols(
|
||||
symbol: S,
|
||||
basedSymbol: S,
|
||||
directOverridden: FirTypeScope.(S) -> List<S>
|
||||
) {}
|
||||
|
||||
fun FirCallableSymbol<*>.dispatchReceiverClassOrNull(): Boolean? = true
|
||||
|
||||
private inline fun <reified D : FirCallableMemberDeclaration<D>, reified S : FirCallableSymbol<D>> createFakeOverriddenIfNeeded(
|
||||
originalSymbol: FirCallableSymbol<*>,
|
||||
basedSymbol: S,
|
||||
computeDirectOverridden: FirTypeScope.(S) -> List<S>,
|
||||
someCondition: Boolean
|
||||
) {
|
||||
if (originalSymbol !is S) return
|
||||
if (originalSymbol.dispatchReceiverClassOrNull() == true && someCondition) return
|
||||
computeBaseSymbols(originalSymbol, basedSymbol, computeDirectOverridden)
|
||||
}
|
||||
+6
@@ -3263,6 +3263,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToNothing.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("smartcastToTypeParameter.kt")
|
||||
public void testSmartcastToTypeParameter() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToTypeParameter.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+6
@@ -3300,6 +3300,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToNothing.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("smartcastToTypeParameter.kt")
|
||||
public void testSmartcastToTypeParameter() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToTypeParameter.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+12
@@ -25651,6 +25651,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastOnSameFieldOfDifferentInstances.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("smartcastToInvisibleType_java.kt")
|
||||
public void testSmartcastToInvisibleType_java() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastToInvisibleType_java.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("smartcastToInvisibleType_kotlin.kt")
|
||||
public void testSmartcastToInvisibleType_kotlin() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastToInvisibleType_kotlin.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("smartcastToNothingAfterCheckingForNull.kt")
|
||||
public void testSmartcastToNothingAfterCheckingForNull() throws Exception {
|
||||
|
||||
+4
@@ -53,6 +53,10 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
|
||||
|
||||
override fun updateAllReceivers(flow: PersistentFlow) =
|
||||
throw IllegalStateException("Update of all receivers is not possible for this logic system")
|
||||
|
||||
override fun ConeKotlinType.isAcceptableForSmartcast(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
effects.forEach { effect ->
|
||||
|
||||
+6
@@ -37668,6 +37668,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt44802.kt")
|
||||
public void testKt44802() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/smartCasts/kt44802.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt44804.kt")
|
||||
public void testKt44804() throws Exception {
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.NoMutableState
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.getOwnerId
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
|
||||
@NoMutableState
|
||||
@@ -23,7 +23,7 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() {
|
||||
symbol: AbstractFirBasedSymbol<*>,
|
||||
useSiteFile: FirFile,
|
||||
containingDeclarations: List<FirDeclaration>,
|
||||
candidate: Candidate,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
session: FirSession
|
||||
): Boolean {
|
||||
return when (declarationVisibility) {
|
||||
@@ -32,7 +32,7 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() {
|
||||
true
|
||||
} else {
|
||||
val ownerId = symbol.getOwnerId()
|
||||
ownerId != null && canSeeProtectedMemberOf(containingDeclarations, candidate.dispatchReceiverValue, ownerId, session)
|
||||
ownerId != null && canSeeProtectedMemberOf(containingDeclarations, dispatchReceiver, ownerId, session)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
symbol: AbstractFirBasedSymbol<*>,
|
||||
useSiteFile: FirFile,
|
||||
containingDeclarations: List<FirDeclaration>,
|
||||
candidate: Candidate,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
session: FirSession
|
||||
): Boolean {
|
||||
return true
|
||||
@@ -45,8 +45,6 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
declaration: T,
|
||||
candidate: Candidate
|
||||
): Boolean where T : FirMemberDeclaration, T : FirSymbolOwner<*> {
|
||||
val symbol = declaration.symbol
|
||||
|
||||
if (declaration is FirCallableDeclaration<*> && (declaration.isIntersectionOverride || declaration.isSubstitutionOverride)) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return isVisible(declaration.originalIfFakeOverride() as T, candidate)
|
||||
@@ -56,8 +54,19 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
val useSiteFile = callInfo.containingFile
|
||||
val containingDeclarations = callInfo.containingDeclarations
|
||||
val session = callInfo.session
|
||||
val provider = session.firProvider
|
||||
|
||||
return isVisible(declaration, session, useSiteFile, containingDeclarations, candidate.dispatchReceiverValue)
|
||||
}
|
||||
|
||||
fun <T> isVisible(
|
||||
declaration: T,
|
||||
session: FirSession,
|
||||
useSiteFile: FirFile,
|
||||
containingDeclarations: List<FirDeclaration>,
|
||||
dispatchReceiver: ReceiverValue?
|
||||
): Boolean where T : FirMemberDeclaration, T : FirSymbolOwner<*> {
|
||||
val provider = session.firProvider
|
||||
val symbol = declaration.symbol
|
||||
return when (declaration.visibility) {
|
||||
Visibilities.Internal -> {
|
||||
declaration.session == session || session.moduleVisibilityChecker?.isInFriendModule(declaration) == true
|
||||
@@ -91,7 +100,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
|
||||
Visibilities.Protected -> {
|
||||
val ownerId = symbol.getOwnerId()
|
||||
ownerId != null && canSeeProtectedMemberOf(containingDeclarations, candidate.dispatchReceiverValue, ownerId, session)
|
||||
ownerId != null && canSeeProtectedMemberOf(containingDeclarations, dispatchReceiver, ownerId, session)
|
||||
}
|
||||
|
||||
else -> platformVisibilityCheck(
|
||||
@@ -99,7 +108,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
symbol,
|
||||
useSiteFile,
|
||||
containingDeclarations,
|
||||
candidate,
|
||||
dispatchReceiver,
|
||||
session
|
||||
)
|
||||
}
|
||||
@@ -110,7 +119,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
symbol: AbstractFirBasedSymbol<*>,
|
||||
useSiteFile: FirFile,
|
||||
containingDeclarations: List<FirDeclaration>,
|
||||
candidate: Candidate,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
session: FirSession
|
||||
): Boolean
|
||||
|
||||
|
||||
+26
-2
@@ -18,8 +18,7 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.PersistentImplicitReceiverStack
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.contracts.buildContractFir
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.contracts.createArgumentsMapping
|
||||
@@ -31,6 +30,7 @@ import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.visibilityChecker
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -84,6 +84,9 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
private val receiverStack: PersistentImplicitReceiverStack
|
||||
get() = components.implicitReceiverStack as PersistentImplicitReceiverStack
|
||||
|
||||
private val symbolProvider = components.session.symbolProvider
|
||||
private val visibilityChecker = components.session.visibilityChecker
|
||||
|
||||
override val logicSystem: PersistentLogicSystem =
|
||||
object : PersistentLogicSystem(components.session.inferenceComponents.ctx) {
|
||||
override fun processUpdatedReceiverVariable(flow: PersistentFlow, variable: RealVariable) {
|
||||
@@ -109,6 +112,27 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun ConeKotlinType.isAcceptableForSmartcast(): Boolean {
|
||||
return when (this) {
|
||||
is ConeClassLikeType -> {
|
||||
val symbol = fullyExpandedType(components.session).lookupTag.toSymbol(components.session) ?: return false
|
||||
val declaration = symbol.fir as? FirRegularClass ?: return true
|
||||
visibilityChecker.isVisible(
|
||||
declaration,
|
||||
components.session,
|
||||
components.context.file,
|
||||
components.context.containers,
|
||||
dispatchReceiver = null
|
||||
)
|
||||
}
|
||||
is ConeTypeParameterType -> true
|
||||
is ConeFlexibleType -> lowerBound.isAcceptableForSmartcast() && upperBound.isAcceptableForSmartcast()
|
||||
is ConeIntersectionType -> intersectedTypes.all { it.isAcceptableForSmartcast() }
|
||||
is ConeDefinitelyNotNullType -> original.isAcceptableForSmartcast()
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.dfa
|
||||
|
||||
import org.jetbrains.kotlin.fir.types.ConeInferenceContext
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.canBeNull
|
||||
import org.jetbrains.kotlin.fir.types.commonSuperTypeOrNull
|
||||
|
||||
abstract class Flow {
|
||||
@@ -59,6 +60,8 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
|
||||
|
||||
protected abstract fun getImplicationsWithVariable(flow: FLOW, variable: DataFlowVariable): Collection<Implication>
|
||||
|
||||
protected abstract fun ConeKotlinType.isAcceptableForSmartcast(): Boolean
|
||||
|
||||
// ------------------------------- Callbacks for updating implicit receiver stack -------------------------------
|
||||
|
||||
abstract fun processUpdatedReceiverVariable(flow: FLOW, variable: RealVariable)
|
||||
@@ -150,7 +153,14 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
|
||||
}
|
||||
}
|
||||
val result = mutableSetOf<ConeKotlinType>()
|
||||
context.commonSuperTypeOrNull(intersectedTypes)?.let { result.add(it) }
|
||||
context.commonSuperTypeOrNull(intersectedTypes)?.let {
|
||||
if (it.isAcceptableForSmartcast()) {
|
||||
result.add(it)
|
||||
} else if (!it.canBeNull) {
|
||||
result.add(context.anyType())
|
||||
}
|
||||
Unit
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -32,19 +32,19 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
||||
|
||||
val symbolProvider: FirSymbolProvider get() = session.symbolProvider
|
||||
|
||||
override fun nullableNothingType(): SimpleTypeMarker {
|
||||
override fun nullableNothingType(): ConeClassLikeType {
|
||||
return session.builtinTypes.nullableNothingType.type
|
||||
}
|
||||
|
||||
override fun nullableAnyType(): SimpleTypeMarker {
|
||||
override fun nullableAnyType(): ConeClassLikeType {
|
||||
return session.builtinTypes.nullableAnyType.type
|
||||
}
|
||||
|
||||
override fun nothingType(): SimpleTypeMarker {
|
||||
override fun nothingType(): ConeClassLikeType {
|
||||
return session.builtinTypes.nothingType.type
|
||||
}
|
||||
|
||||
override fun anyType(): SimpleTypeMarker {
|
||||
override fun anyType(): ConeClassLikeType {
|
||||
return session.builtinTypes.anyType.type
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// ISSUE: KT-44802
|
||||
|
||||
// FILE: foo/Base.java
|
||||
package foo;
|
||||
|
||||
public interface Base {
|
||||
String foo();
|
||||
}
|
||||
|
||||
// FILE: foo/PackagePrivateInterface.java
|
||||
package foo;
|
||||
|
||||
interface PackagePrivateInterface extends Base {}
|
||||
|
||||
// FILE: foo/A.java
|
||||
package foo;
|
||||
|
||||
public class A implements PackagePrivateInterface {
|
||||
public String foo() { return "OK"; }
|
||||
}
|
||||
|
||||
// FILE: foo/B.java
|
||||
package foo;
|
||||
|
||||
public class B implements PackagePrivateInterface {
|
||||
public String foo() { return "B"; }
|
||||
}
|
||||
|
||||
// FILE: foo/C.java
|
||||
package foo;
|
||||
|
||||
// FILE: main.kt
|
||||
package bar
|
||||
|
||||
import foo.Base
|
||||
import foo.A
|
||||
import foo.B
|
||||
|
||||
fun testSmartcast(x: Base): String {
|
||||
if (x !is A && x !is B) return "fail"
|
||||
return x.foo()
|
||||
}
|
||||
|
||||
fun box() = testSmartcast(A())
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// ISSUE: KT-44802
|
||||
// INFERENCE_HELPERS
|
||||
|
||||
// FILE: foo/PackagePrivateInterface.java
|
||||
package foo;
|
||||
|
||||
interface PackagePrivateInterface {
|
||||
default void foo() {}
|
||||
}
|
||||
|
||||
// FILE: foo/A.java
|
||||
package foo;
|
||||
|
||||
public class A implements PackagePrivateInterface {}
|
||||
|
||||
// FILE: foo/B.java
|
||||
package foo;
|
||||
|
||||
public class B implements PackagePrivateInterface {}
|
||||
|
||||
// FILE: differentPackage.kt
|
||||
package bar
|
||||
|
||||
import foo.A
|
||||
import foo.B
|
||||
import select
|
||||
|
||||
fun testSmartcast(x: Any) {
|
||||
if (x is A || x is B) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>x<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun testInference(a: A, b: B) {
|
||||
val x = <!DEBUG_INFO_EXPRESSION_TYPE("foo.PackagePrivateInterface")!>select(a, b)<!>
|
||||
x.foo()
|
||||
}
|
||||
|
||||
// FILE: samePackage.kt
|
||||
package foo
|
||||
|
||||
import select
|
||||
|
||||
fun testSmartcast(x: Any) {
|
||||
if (x is A || x is B) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & foo.PackagePrivateInterface")!>x<!>.foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun testInference(a: A, b: B) {
|
||||
val x = <!DEBUG_INFO_EXPRESSION_TYPE("foo.PackagePrivateInterface")!>select(a, b)<!>
|
||||
x.foo()
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// ISSUE: KT-44802
|
||||
// INFERENCE_HELPERS
|
||||
|
||||
// FILE: foo/PackagePrivateInterface.java
|
||||
package foo;
|
||||
|
||||
interface PackagePrivateInterface {
|
||||
default void foo() {}
|
||||
}
|
||||
|
||||
// FILE: foo/A.java
|
||||
package foo;
|
||||
|
||||
public class A implements PackagePrivateInterface {}
|
||||
|
||||
// FILE: foo/B.java
|
||||
package foo;
|
||||
|
||||
public class B implements PackagePrivateInterface {}
|
||||
|
||||
// FILE: differentPackage.kt
|
||||
package bar
|
||||
|
||||
import foo.A
|
||||
import foo.B
|
||||
import select
|
||||
|
||||
fun testSmartcast(x: Any) {
|
||||
if (x is A || x is B) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>x<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun testInference(a: A, b: B) {
|
||||
val x = <!DEBUG_INFO_EXPRESSION_TYPE("foo.PackagePrivateInterface"), INACCESSIBLE_TYPE!>select(a, b)<!>
|
||||
<!INACCESSIBLE_TYPE!>x<!>.<!INVISIBLE_MEMBER!>foo<!>()
|
||||
}
|
||||
|
||||
// FILE: samePackage.kt
|
||||
package foo
|
||||
|
||||
import select
|
||||
|
||||
fun testSmartcast(x: Any) {
|
||||
if (x is A || x is B) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>x<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun testInference(a: A, b: B) {
|
||||
val x = <!DEBUG_INFO_EXPRESSION_TYPE("foo.PackagePrivateInterface")!>select(a, b)<!>
|
||||
x.foo()
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ K> id(/*0*/ x: K): K
|
||||
public fun </*0*/ K> materialize(): K
|
||||
public fun </*0*/ K> select(/*0*/ vararg values: K /*kotlin.Array<out K>*/): K
|
||||
|
||||
package bar {
|
||||
public fun testInference(/*0*/ a: foo.A, /*1*/ b: foo.B): kotlin.Unit
|
||||
public fun testSmartcast(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
}
|
||||
|
||||
package foo {
|
||||
public fun testInference(/*0*/ a: foo.A, /*1*/ b: foo.B): kotlin.Unit
|
||||
public fun testSmartcast(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
|
||||
public open class A : foo.PackagePrivateInterface {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ 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 open class B : foo.PackagePrivateInterface {
|
||||
public constructor B()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ 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/*package*/ interface PackagePrivateInterface {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// INFERENCE_HELPERS
|
||||
// ISSUE: KT-44802
|
||||
// FILE: a.kt
|
||||
|
||||
package foo
|
||||
import select
|
||||
|
||||
private interface PrivateInterface {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
class A : PrivateInterface
|
||||
class B : PrivateInterface
|
||||
|
||||
fun testSmartcast(x: Any) {
|
||||
if (x is A || x is B) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & foo.PrivateInterface")!>x<!>.foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun testInference(a: A, b: B) {
|
||||
val x = <!DEBUG_INFO_EXPRESSION_TYPE("foo.PrivateInterface")!>select(a, b)<!>
|
||||
x.foo()
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
package bar
|
||||
|
||||
import foo.A
|
||||
import foo.B
|
||||
import select
|
||||
|
||||
fun testSmartcast(x: Any) {
|
||||
if (x is A || x is B) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>x<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun testInference(a: A, b: B) {
|
||||
val x = <!DEBUG_INFO_EXPRESSION_TYPE("foo.PrivateInterface")!>select(a, b)<!>
|
||||
x.foo()
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// INFERENCE_HELPERS
|
||||
// ISSUE: KT-44802
|
||||
// FILE: a.kt
|
||||
|
||||
package foo
|
||||
import select
|
||||
|
||||
private interface PrivateInterface {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
class A : PrivateInterface
|
||||
class B : PrivateInterface
|
||||
|
||||
fun testSmartcast(x: Any) {
|
||||
if (x is A || x is B) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>x<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun testInference(a: A, b: B) {
|
||||
val x = <!DEBUG_INFO_EXPRESSION_TYPE("foo.PrivateInterface")!>select(a, b)<!>
|
||||
x.foo()
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
package bar
|
||||
|
||||
import foo.A
|
||||
import foo.B
|
||||
import select
|
||||
|
||||
fun testSmartcast(x: Any) {
|
||||
if (x is A || x is B) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>x<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun testInference(a: A, b: B) {
|
||||
val x = <!DEBUG_INFO_EXPRESSION_TYPE("foo.PrivateInterface")!>select(a, b)<!>
|
||||
x.<!INVISIBLE_MEMBER!>foo<!>()
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ K> id(/*0*/ x: K): K
|
||||
public fun </*0*/ K> materialize(): K
|
||||
public fun </*0*/ K> select(/*0*/ vararg values: K /*kotlin.Array<out K>*/): K
|
||||
|
||||
package bar {
|
||||
public fun testInference(/*0*/ a: foo.A, /*1*/ b: foo.B): kotlin.Unit
|
||||
public fun testSmartcast(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
}
|
||||
|
||||
package foo {
|
||||
public fun testInference(/*0*/ a: foo.A, /*1*/ b: foo.B): kotlin.Unit
|
||||
public fun testSmartcast(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
|
||||
public final class A : foo.PrivateInterface {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ 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 final class B : foo.PrivateInterface {
|
||||
public constructor B()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
private interface PrivateInterface {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+12
@@ -25741,6 +25741,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastOnSameFieldOfDifferentInstances.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("smartcastToInvisibleType_java.kt")
|
||||
public void testSmartcastToInvisibleType_java() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastToInvisibleType_java.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("smartcastToInvisibleType_kotlin.kt")
|
||||
public void testSmartcastToInvisibleType_kotlin() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastToInvisibleType_kotlin.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("smartcastToNothingAfterCheckingForNull.kt")
|
||||
public void testSmartcastToNothingAfterCheckingForNull() throws Exception {
|
||||
|
||||
+6
@@ -37668,6 +37668,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt44802.kt")
|
||||
public void testKt44802() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/smartCasts/kt44802.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt44804.kt")
|
||||
public void testKt44804() throws Exception {
|
||||
|
||||
+6
@@ -37668,6 +37668,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt44802.kt")
|
||||
public void testKt44802() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/smartCasts/kt44802.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt44804.kt")
|
||||
public void testKt44804() throws Exception {
|
||||
|
||||
+5
@@ -30120,6 +30120,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt44802.kt")
|
||||
public void testKt44802() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/smartCasts/kt44802.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt44804.kt")
|
||||
public void testKt44804() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/smartCasts/kt44804.kt");
|
||||
|
||||
Reference in New Issue
Block a user