Update 'this' extension receiver when there's a smart cast
If 'this' (implicit or explicit) was used as an extension receiver, and the corresponding call required a smart-cast, this information was effectively lost in "old" resolution & inference, but is required by "old" JVM BE to generate proper CHECKCASTs.
This commit is contained in:
@@ -566,6 +566,9 @@ class CandidateResolver(
|
||||
if (isDispatchReceiver) {
|
||||
candidateCall.setSmartCastDispatchReceiverType(smartCastResult.resultType)
|
||||
}
|
||||
else {
|
||||
candidateCall.updateExtensionReceiverWithSmartCastIfNeeded(smartCastResult.resultType)
|
||||
}
|
||||
if (!smartCastResult.isCorrect) {
|
||||
// Error about unstable smart cast reported within checkAndRecordPossibleCast
|
||||
return UNSTABLE_SMARTCAST_FOR_RECEIVER_ERROR
|
||||
|
||||
+2
@@ -67,4 +67,6 @@ public interface MutableResolvedCall<D extends CallableDescriptor> extends Resol
|
||||
boolean hasInferredReturnType();
|
||||
|
||||
void setSmartCastDispatchReceiverType(@NotNull KotlinType smartCastDispatchReceiverType);
|
||||
|
||||
void updateExtensionReceiverWithSmartCastIfNeeded(@NotNull KotlinType smartCastExtensionReceiverType);
|
||||
}
|
||||
|
||||
+13
-1
@@ -33,6 +33,8 @@ import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeProjection;
|
||||
@@ -60,7 +62,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
private final D candidateDescriptor;
|
||||
private D resultingDescriptor; // Probably substituted
|
||||
private final ReceiverValue dispatchReceiver; // receiver object of a method
|
||||
private final ReceiverValue extensionReceiver; // receiver of an extension function
|
||||
private ReceiverValue extensionReceiver; // receiver of an extension function
|
||||
private final ExplicitReceiverKind explicitReceiverKind;
|
||||
private final TypeSubstitutor knownTypeParametersSubstitutor;
|
||||
|
||||
@@ -378,4 +380,14 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
public KotlinType getSmartCastDispatchReceiverType() {
|
||||
return smartCastDispatchReceiverType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateExtensionReceiverWithSmartCastIfNeeded(@NotNull KotlinType smartCastExtensionReceiverType) {
|
||||
if (extensionReceiver instanceof ImplicitClassReceiver) {
|
||||
extensionReceiver = new CastImplicitClassReceiver(
|
||||
((ImplicitClassReceiver) extensionReceiver).getClassDescriptor(),
|
||||
smartCastExtensionReceiverType
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: Test.kt
|
||||
open class KFoo {
|
||||
fun foo(): String {
|
||||
if (this is KFooBar) return bar
|
||||
throw AssertionError()
|
||||
}
|
||||
}
|
||||
|
||||
class KFooBar : KFoo(), JBar
|
||||
|
||||
fun box(): String = KFooBar().foo()
|
||||
|
||||
// FILE: JBar.java
|
||||
public interface JBar {
|
||||
default String getBar() {
|
||||
return "OK";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
open class KFoo {
|
||||
fun foo(): String {
|
||||
if (this is KFooQux) return qux
|
||||
throw AssertionError()
|
||||
}
|
||||
}
|
||||
|
||||
class KFooQux : KFoo()
|
||||
|
||||
val KFooQux.qux get() = "OK"
|
||||
|
||||
fun box() = KFooQux().foo()
|
||||
+12
@@ -17600,6 +17600,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19058.kt")
|
||||
public void testKt19058() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/smartCasts/kt19058.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19100.kt")
|
||||
public void testKt19100() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/smartCasts/kt19100.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaArgumentWithoutType.kt")
|
||||
public void testLambdaArgumentWithoutType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
||||
|
||||
@@ -17600,6 +17600,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19058.kt")
|
||||
public void testKt19058() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/smartCasts/kt19058.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19100.kt")
|
||||
public void testKt19100() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/smartCasts/kt19100.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaArgumentWithoutType.kt")
|
||||
public void testLambdaArgumentWithoutType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
||||
|
||||
@@ -17600,6 +17600,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19058.kt")
|
||||
public void testKt19058() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/smartCasts/kt19058.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19100.kt")
|
||||
public void testKt19100() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/smartCasts/kt19100.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaArgumentWithoutType.kt")
|
||||
public void testLambdaArgumentWithoutType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
||||
|
||||
@@ -21506,6 +21506,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19100.kt")
|
||||
public void testKt19100() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/smartCasts/kt19100.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaArgumentWithoutType.kt")
|
||||
public void testLambdaArgumentWithoutType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
||||
|
||||
Reference in New Issue
Block a user