Report MEMBER_PROJECTED_OUT on calls with smart cast receiver

#KT-10856 Fixed
This commit is contained in:
Denis Zharkov
2016-01-29 15:35:17 +03:00
parent 05192547da
commit 9b3f557337
9 changed files with 80 additions and 5 deletions
@@ -61,7 +61,9 @@ fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
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 substitutedDescriptor =
@@ -436,7 +436,7 @@ class CandidateResolver(
}
private fun <D : CallableDescriptor> CallCandidateResolutionContext<D>.checkReceiver(
candidateCall: ResolvedCall<D>,
candidateCall: MutableResolvedCall<D>,
receiverParameter: ReceiverParameterDescriptor?,
receiverArgument: ReceiverValue?,
isExplicitReceiver: Boolean,
@@ -497,9 +497,12 @@ class CandidateResolver(
if (smartCastResult == null) {
reportUnsafeCall = true
}
else if (!smartCastResult.isCorrect) {
// Error about unstable smart cast reported within checkAndRecordPossibleCast
return OTHER_ERROR
else {
candidateCall.setSmartCastDispatchReceiverType(smartCastResult.resultType)
if (!smartCastResult.isCorrect) {
// Error about unstable smart cast reported within checkAndRecordPossibleCast
return OTHER_ERROR
}
}
}
@@ -121,4 +121,10 @@ public abstract class DelegatingResolvedCall<D extends CallableDescriptor> imple
public boolean isSafeCall() {
return resolvedCall.isSafeCall();
}
@Nullable
@Override
public KotlinType getSmartCastDispatchReceiverType() {
return resolvedCall.getSmartCastDispatchReceiverType();
}
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.DelegatingBindingTrace;
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus;
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeSubstitutor;
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
boolean hasInferredReturnType();
void setSmartCastDispatchReceiverType(@NotNull KotlinType smartCastDispatchReceiverType);
}
@@ -85,4 +85,7 @@ public interface ResolvedCall<D extends CallableDescriptor> {
DataFlowInfoForArguments getDataFlowInfoForArguments();
boolean isSafeCall();
@Nullable
KotlinType getSmartCastDispatchReceiverType();
}
@@ -94,6 +94,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
private ConstraintSystem constraintSystem = null;
private Boolean hasInferredReturnType = null;
private boolean completed = false;
private KotlinType smartCastDispatchReceiverType = null;
private ResolvedCallImpl(
@NotNull ResolutionCandidate<D> candidate,
@@ -370,4 +371,15 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
public TypeSubstitutor getKnownTypeParametersSubstitutor() {
return knownTypeParametersSubstitutor;
}
@Override
public void setSmartCastDispatchReceiverType(@NotNull KotlinType smartCastDispatchReceiverType) {
this.smartCastDispatchReceiverType = smartCastDispatchReceiverType;
}
@Override
@Nullable
public KotlinType getSmartCastDispatchReceiverType() {
return smartCastDispatchReceiverType;
}
}
@@ -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<!>("")
}
}
}
@@ -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);
}
@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")
public void testRecursiveUpperBoundStar() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/recursiveUpperBoundStar.kt");