Fix for a problem with smart cast impossible in a situation when it's not needed. A test for KT-3572. #KT-3572 Fixed.
This commit is contained in:
@@ -653,7 +653,9 @@ public class CandidateResolver {
|
|||||||
context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument);
|
context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument);
|
||||||
return OTHER_ERROR;
|
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();
|
JetType receiverArgumentType = receiverArgument.getType();
|
||||||
|
|
||||||
|
|||||||
+7
-6
@@ -158,31 +158,31 @@ public class SmartCastUtils {
|
|||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns false when we need smart cast but cannot do it, otherwise true
|
||||||
public static boolean recordSmartCastIfNecessary(
|
public static boolean recordSmartCastIfNecessary(
|
||||||
@NotNull ReceiverValue receiver,
|
@NotNull ReceiverValue receiver,
|
||||||
@NotNull JetType receiverParameterType,
|
@NotNull JetType receiverParameterType,
|
||||||
@NotNull ResolutionContext context,
|
@NotNull ResolutionContext context,
|
||||||
boolean safeAccess
|
boolean safeAccess
|
||||||
) {
|
) {
|
||||||
if (!(receiver instanceof ExpressionReceiver)) return false;
|
if (!(receiver instanceof ExpressionReceiver)) return true;
|
||||||
|
|
||||||
receiverParameterType = safeAccess ? TypeUtils.makeNullable(receiverParameterType) : receiverParameterType;
|
receiverParameterType = safeAccess ? TypeUtils.makeNullable(receiverParameterType) : receiverParameterType;
|
||||||
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(receiver.getType(), receiverParameterType)) {
|
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(receiver.getType(), receiverParameterType)) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<JetType> smartCastTypesExcludingReceiver = getSmartCastVariantsExcludingReceiver(context, receiver);
|
Collection<JetType> smartCastTypesExcludingReceiver = getSmartCastVariantsExcludingReceiver(context, receiver);
|
||||||
JetType smartCastSubType = getSmartCastSubType(receiverParameterType, smartCastTypesExcludingReceiver);
|
JetType smartCastSubType = getSmartCastSubType(receiverParameterType, smartCastTypesExcludingReceiver);
|
||||||
if (smartCastSubType == null) return false;
|
if (smartCastSubType == null) return true;
|
||||||
|
|
||||||
JetExpression expression = ((ExpressionReceiver) receiver).getExpression();
|
JetExpression expression = ((ExpressionReceiver) receiver).getExpression();
|
||||||
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, context);
|
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, context);
|
||||||
|
|
||||||
recordCastOrError(expression, smartCastSubType, context.trace, dataFlowValue.isPredictable(), true);
|
return recordCastOrError(expression, smartCastSubType, context.trace, dataFlowValue.isPredictable(), true);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void recordCastOrError(
|
public static boolean recordCastOrError(
|
||||||
@NotNull JetExpression expression,
|
@NotNull JetExpression expression,
|
||||||
@NotNull JetType type,
|
@NotNull JetType type,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@@ -200,6 +200,7 @@ public class SmartCastUtils {
|
|||||||
else {
|
else {
|
||||||
trace.report(SMARTCAST_IMPOSSIBLE.on(expression, type, expression.getText()));
|
trace.report(SMARTCAST_IMPOSSIBLE.on(expression, type, expression.getText()));
|
||||||
}
|
}
|
||||||
|
return canBeCast;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canBeSmartCast(
|
public static boolean canBeSmartCast(
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -10998,6 +10998,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("kt3711.kt")
|
||||||
public void testKt3711() throws Exception {
|
public void testKt3711() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/kt3711.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/kt3711.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user