diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/diagnosticUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/diagnosticUtils.kt index e63ad39e3f7..8a8ea25d0eb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/diagnosticUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/diagnosticUtils.kt @@ -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 = diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt index 7d55604850d..b07b29b3127 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt @@ -436,7 +436,7 @@ class CandidateResolver( } private fun CallCandidateResolutionContext.checkReceiver( - candidateCall: ResolvedCall, + candidateCall: MutableResolvedCall, 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 + } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/DelegatingResolvedCall.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/DelegatingResolvedCall.java index b61d811ab70..c1a55b4d172 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/DelegatingResolvedCall.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/DelegatingResolvedCall.java @@ -121,4 +121,10 @@ public abstract class DelegatingResolvedCall imple public boolean isSafeCall() { return resolvedCall.isSafeCall(); } + + @Nullable + @Override + public KotlinType getSmartCastDispatchReceiverType() { + return resolvedCall.getSmartCastDispatchReceiverType(); + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/MutableResolvedCall.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/MutableResolvedCall.java index a66d17414a3..9b1968f1d19 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/MutableResolvedCall.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/MutableResolvedCall.java @@ -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 extends ResolvedCall { @@ -64,4 +65,6 @@ public interface MutableResolvedCall extends Resol //todo remove: use value to parameter map status boolean hasInferredReturnType(); + + void setSmartCastDispatchReceiverType(@NotNull KotlinType smartCastDispatchReceiverType); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCall.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCall.java index d04c472bbfb..1c0f7ddceb4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCall.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCall.java @@ -85,4 +85,7 @@ public interface ResolvedCall { DataFlowInfoForArguments getDataFlowInfoForArguments(); boolean isSafeCall(); + + @Nullable + KotlinType getSmartCastDispatchReceiverType(); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java index 8931a32fc2c..ac94c9b555c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java @@ -94,6 +94,7 @@ public class ResolvedCallImpl implements MutableRe private ConstraintSystem constraintSystem = null; private Boolean hasInferredReturnType = null; private boolean completed = false; + private KotlinType smartCastDispatchReceiverType = null; private ResolvedCallImpl( @NotNull ResolutionCandidate candidate, @@ -370,4 +371,15 @@ public class ResolvedCallImpl implements MutableRe public TypeSubstitutor getKnownTypeParametersSubstitutor() { return knownTypeParametersSubstitutor; } + + @Override + public void setSmartCastDispatchReceiverType(@NotNull KotlinType smartCastDispatchReceiverType) { + this.smartCastDispatchReceiverType = smartCastDispatchReceiverType; + } + + @Override + @Nullable + public KotlinType getSmartCastDispatchReceiverType() { + return smartCastDispatchReceiverType; + } } diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutSmartCast.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutSmartCast.kt new file mode 100644 index 00000000000..25493b567cf --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutSmartCast.kt @@ -0,0 +1,22 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +class Inv +class C { + fun bindTo(property: Inv) {} +} + +fun foo(x: Any?, y: C<*>) { + y.bindTo("") + + if (x is C<*>) { + x.bindTo("") + with(x) { + bindTo("") + } + } + + with(x) { + if (this is C<*>) { + bindTo("") + } + } +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutSmartCast.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutSmartCast.txt new file mode 100644 index 00000000000..5c3d0d5e020 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutSmartCast.txt @@ -0,0 +1,18 @@ +package + +public fun foo(/*0*/ x: kotlin.Any?, /*1*/ y: C<*>): kotlin.Unit + +public final class C { + public constructor C() + public final fun bindTo(/*0*/ property: Inv): 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 { + public constructor Inv() + 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 +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 66a40342938..336a482f9c6 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -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");