diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java index ad82e8fda2e..4d2ef1dbb03 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java @@ -653,7 +653,9 @@ public class CandidateResolver { context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument); return OTHER_ERROR; } - SmartCastUtils.recordSmartCastIfNecessary(receiverArgument, receiverParameter.getType(), context, safeAccess); + if (!SmartCastUtils.recordSmartCastIfNecessary(receiverArgument, receiverParameter.getType(), context, safeAccess)) { + return OTHER_ERROR; + } JetType receiverArgumentType = receiverArgument.getType(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastUtils.java index 3867e4de77a..24e818c6c09 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastUtils.java @@ -158,31 +158,31 @@ public class SmartCastUtils { return intersection; } + // Returns false when we need smart cast but cannot do it, otherwise true public static boolean recordSmartCastIfNecessary( @NotNull ReceiverValue receiver, @NotNull JetType receiverParameterType, @NotNull ResolutionContext context, boolean safeAccess ) { - if (!(receiver instanceof ExpressionReceiver)) return false; + if (!(receiver instanceof ExpressionReceiver)) return true; receiverParameterType = safeAccess ? TypeUtils.makeNullable(receiverParameterType) : receiverParameterType; if (ArgumentTypeResolver.isSubtypeOfForArgumentType(receiver.getType(), receiverParameterType)) { - return false; + return true; } Collection smartCastTypesExcludingReceiver = getSmartCastVariantsExcludingReceiver(context, receiver); JetType smartCastSubType = getSmartCastSubType(receiverParameterType, smartCastTypesExcludingReceiver); - if (smartCastSubType == null) return false; + if (smartCastSubType == null) return true; JetExpression expression = ((ExpressionReceiver) receiver).getExpression(); DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, context); - recordCastOrError(expression, smartCastSubType, context.trace, dataFlowValue.isPredictable(), true); - return true; + return recordCastOrError(expression, smartCastSubType, context.trace, dataFlowValue.isPredictable(), true); } - public static void recordCastOrError( + public static boolean recordCastOrError( @NotNull JetExpression expression, @NotNull JetType type, @NotNull BindingTrace trace, @@ -200,6 +200,7 @@ public class SmartCastUtils { else { trace.report(SMARTCAST_IMPOSSIBLE.on(expression, type, expression.getText())); } + return canBeCast; } public static boolean canBeSmartCast( diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt3572.kt b/compiler/testData/diagnostics/tests/smartCasts/kt3572.kt new file mode 100644 index 00000000000..bbc0f322f75 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/kt3572.kt @@ -0,0 +1,17 @@ +trait Printer { + fun print() +} + +class OKPrinter : Printer { + override fun print() { } +} + +class MyClass(var printer: Printer) + + +fun main(m: MyClass) { + if (m.printer is OKPrinter) { + // We do not need smart cast here, so we should not get SMARTCAST_IMPOSSIBLE + m.printer.print() + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt3572.txt b/compiler/testData/diagnostics/tests/smartCasts/kt3572.txt new file mode 100644 index 00000000000..33cec66768f --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/kt3572.txt @@ -0,0 +1,26 @@ +package + +internal fun main(/*0*/ m: MyClass): kotlin.Unit + +internal final class MyClass { + public constructor MyClass(/*0*/ printer: Printer) + internal final var printer: Printer + 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 +} + +internal final class OKPrinter : Printer { + public constructor OKPrinter() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + internal open override /*1*/ fun print(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal trait Printer { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + internal abstract fun print(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 622aa293815..357faf49e47 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -10998,6 +10998,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("kt3572.kt") + public void testKt3572() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/kt3572.kt"); + doTest(fileName); + } + @TestMetadata("kt3711.kt") public void testKt3711() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/kt3711.kt");