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:
Dmitry Petrov
2017-07-19 11:56:42 +03:00
parent c9d54d7110
commit bf3e896464
9 changed files with 91 additions and 1 deletions
@@ -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
@@ -67,4 +67,6 @@ public interface MutableResolvedCall<D extends CallableDescriptor> extends Resol
boolean hasInferredReturnType();
void setSmartCastDispatchReceiverType(@NotNull KotlinType smartCastDispatchReceiverType);
void updateExtensionReceiverWithSmartCastIfNeeded(@NotNull KotlinType smartCastExtensionReceiverType);
}
@@ -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
);
}
}
}