Report MEMBER_PROJECTED_OUT on calls with smart cast receiver
#KT-10856 Fixed
This commit is contained in:
@@ -61,7 +61,9 @@ fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
|
|||||||
is CallPosition.Unknown -> return false
|
is CallPosition.Unknown -> return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val receiverType = resolvedCall.dispatchReceiver?.type ?: return false
|
val receiverType = resolvedCall.smartCastDispatchReceiverType
|
||||||
|
?: (resolvedCall.dispatchReceiver ?: return false).type
|
||||||
|
|
||||||
val callableDescriptor = resolvedCall.resultingDescriptor.original
|
val callableDescriptor = resolvedCall.resultingDescriptor.original
|
||||||
|
|
||||||
val substitutedDescriptor =
|
val substitutedDescriptor =
|
||||||
|
|||||||
@@ -436,7 +436,7 @@ class CandidateResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun <D : CallableDescriptor> CallCandidateResolutionContext<D>.checkReceiver(
|
private fun <D : CallableDescriptor> CallCandidateResolutionContext<D>.checkReceiver(
|
||||||
candidateCall: ResolvedCall<D>,
|
candidateCall: MutableResolvedCall<D>,
|
||||||
receiverParameter: ReceiverParameterDescriptor?,
|
receiverParameter: ReceiverParameterDescriptor?,
|
||||||
receiverArgument: ReceiverValue?,
|
receiverArgument: ReceiverValue?,
|
||||||
isExplicitReceiver: Boolean,
|
isExplicitReceiver: Boolean,
|
||||||
@@ -497,9 +497,12 @@ class CandidateResolver(
|
|||||||
if (smartCastResult == null) {
|
if (smartCastResult == null) {
|
||||||
reportUnsafeCall = true
|
reportUnsafeCall = true
|
||||||
}
|
}
|
||||||
else if (!smartCastResult.isCorrect) {
|
else {
|
||||||
// Error about unstable smart cast reported within checkAndRecordPossibleCast
|
candidateCall.setSmartCastDispatchReceiverType(smartCastResult.resultType)
|
||||||
return OTHER_ERROR
|
if (!smartCastResult.isCorrect) {
|
||||||
|
// Error about unstable smart cast reported within checkAndRecordPossibleCast
|
||||||
|
return OTHER_ERROR
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
@@ -121,4 +121,10 @@ public abstract class DelegatingResolvedCall<D extends CallableDescriptor> imple
|
|||||||
public boolean isSafeCall() {
|
public boolean isSafeCall() {
|
||||||
return resolvedCall.isSafeCall();
|
return resolvedCall.isSafeCall();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public KotlinType getSmartCastDispatchReceiverType() {
|
||||||
|
return resolvedCall.getSmartCastDispatchReceiverType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.DelegatingBindingTrace;
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus;
|
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus;
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||||
|
|
||||||
public interface MutableResolvedCall<D extends CallableDescriptor> extends ResolvedCall<D> {
|
public interface MutableResolvedCall<D extends CallableDescriptor> extends ResolvedCall<D> {
|
||||||
@@ -64,4 +65,6 @@ public interface MutableResolvedCall<D extends CallableDescriptor> extends Resol
|
|||||||
|
|
||||||
//todo remove: use value to parameter map status
|
//todo remove: use value to parameter map status
|
||||||
boolean hasInferredReturnType();
|
boolean hasInferredReturnType();
|
||||||
|
|
||||||
|
void setSmartCastDispatchReceiverType(@NotNull KotlinType smartCastDispatchReceiverType);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,4 +85,7 @@ public interface ResolvedCall<D extends CallableDescriptor> {
|
|||||||
DataFlowInfoForArguments getDataFlowInfoForArguments();
|
DataFlowInfoForArguments getDataFlowInfoForArguments();
|
||||||
|
|
||||||
boolean isSafeCall();
|
boolean isSafeCall();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
KotlinType getSmartCastDispatchReceiverType();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
|||||||
private ConstraintSystem constraintSystem = null;
|
private ConstraintSystem constraintSystem = null;
|
||||||
private Boolean hasInferredReturnType = null;
|
private Boolean hasInferredReturnType = null;
|
||||||
private boolean completed = false;
|
private boolean completed = false;
|
||||||
|
private KotlinType smartCastDispatchReceiverType = null;
|
||||||
|
|
||||||
private ResolvedCallImpl(
|
private ResolvedCallImpl(
|
||||||
@NotNull ResolutionCandidate<D> candidate,
|
@NotNull ResolutionCandidate<D> candidate,
|
||||||
@@ -370,4 +371,15 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
|||||||
public TypeSubstitutor getKnownTypeParametersSubstitutor() {
|
public TypeSubstitutor getKnownTypeParametersSubstitutor() {
|
||||||
return knownTypeParametersSubstitutor;
|
return knownTypeParametersSubstitutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSmartCastDispatchReceiverType(@NotNull KotlinType smartCastDispatchReceiverType) {
|
||||||
|
this.smartCastDispatchReceiverType = smartCastDispatchReceiverType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public KotlinType getSmartCastDispatchReceiverType() {
|
||||||
|
return smartCastDispatchReceiverType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
class Inv<E>
|
||||||
|
class C<R> {
|
||||||
|
fun bindTo(property: Inv<R>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(x: Any?, y: C<*>) {
|
||||||
|
y.<!MEMBER_PROJECTED_OUT!>bindTo<!>("")
|
||||||
|
|
||||||
|
if (x is C<*>) {
|
||||||
|
<!DEBUG_INFO_SMARTCAST!>x<!>.<!MEMBER_PROJECTED_OUT!>bindTo<!>("")
|
||||||
|
with(<!DEBUG_INFO_SMARTCAST!>x<!>) {
|
||||||
|
<!MEMBER_PROJECTED_OUT!>bindTo<!>("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
with(x) {
|
||||||
|
if (this is C<*>) {
|
||||||
|
<!MEMBER_PROJECTED_OUT, DEBUG_INFO_IMPLICIT_RECEIVER_SMARTCAST!>bindTo<!>("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun foo(/*0*/ x: kotlin.Any?, /*1*/ y: C<*>): kotlin.Unit
|
||||||
|
|
||||||
|
public final class C</*0*/ R> {
|
||||||
|
public constructor C</*0*/ R>()
|
||||||
|
public final fun bindTo(/*0*/ property: Inv<R>): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Inv</*0*/ E> {
|
||||||
|
public constructor Inv</*0*/ E>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -7382,6 +7382,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("projectedOutSmartCast.kt")
|
||||||
|
public void testProjectedOutSmartCast() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutSmartCast.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("recursiveUpperBoundStar.kt")
|
@TestMetadata("recursiveUpperBoundStar.kt")
|
||||||
public void testRecursiveUpperBoundStar() throws Exception {
|
public void testRecursiveUpperBoundStar() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/recursiveUpperBoundStar.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/recursiveUpperBoundStar.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user