diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java index cae1d47e6cc..ca0a0f646df 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java @@ -17,7 +17,9 @@ package org.jetbrains.jet.lang.resolve.calls.autocasts; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; @@ -28,9 +30,11 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeUtils; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import java.util.Collections; import java.util.List; +import java.util.Set; import static org.jetbrains.jet.lang.diagnostics.Errors.AUTOCAST_IMPOSSIBLE; import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST; @@ -96,20 +100,28 @@ public class AutoCastUtils { @NotNull ResolutionContext context ) { List autoCastTypes = getAutoCastVariants(receiverArgument, context); - return isSubTypeByAutoCast(receiverParameterType, autoCastTypes); + return getAutoCastSubType(receiverParameterType, autoCastTypes) != null; } - private static boolean isSubTypeByAutoCast( + @Nullable + private static JetType getAutoCastSubType( @NotNull JetType receiverParameterType, @NotNull List autoCastTypes ) { + Set subTypes = Sets.newHashSet(); for (JetType autoCastType : autoCastTypes) { JetType effectiveAutoCastType = TypeUtils.makeNotNullable(autoCastType); if (ArgumentTypeResolver.isSubtypeOfForArgumentType(effectiveAutoCastType, receiverParameterType)) { - return true; + subTypes.add(autoCastType); } } - return false; + if (subTypes.isEmpty()) return null; + + JetType intersection = TypeUtils.intersect(JetTypeChecker.INSTANCE, subTypes); + if (intersection == null || !intersection.getConstructor().isDenotable()) { + return receiverParameterType; + } + return intersection; } public static boolean recordAutoCastIfNecessary( @@ -125,14 +137,14 @@ public class AutoCastUtils { List autoCastTypesExcludingReceiver = getAutoCastVariantsExcludingReceiver( context.trace.getBindingContext(), context.dataFlowInfo, receiver); - boolean autoCast = isSubTypeByAutoCast(receiverType, autoCastTypesExcludingReceiver); - if (autoCast) { - JetExpression expression = ((ExpressionReceiver) receiver).getExpression(); - DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, context.trace.getBindingContext()); + JetType autoCastSubType = getAutoCastSubType(receiverType, autoCastTypesExcludingReceiver); + if (autoCastSubType == null) return false; - recordCastOrError(expression, receiverType, context.trace, dataFlowValue.isStableIdentifier(), true); - } - return autoCast; + JetExpression expression = ((ExpressionReceiver) receiver).getExpression(); + DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, context.trace.getBindingContext()); + + recordCastOrError(expression, autoCastSubType, context.trace, dataFlowValue.isStableIdentifier(), true); + return true; } public static void recordAutoCastToNotNullableType(@NotNull ReceiverValue receiver, @NotNull BindingTrace trace) { diff --git a/idea/testData/checker/infos/Autocasts.kt b/idea/testData/checker/infos/Autocasts.kt index f001b26fd81..e6bbb1ef9c8 100644 --- a/idea/testData/checker/infos/Autocasts.kt +++ b/idea/testData/checker/infos/Autocasts.kt @@ -11,7 +11,7 @@ fun f9(a : A?) { a?.bar() if (a is B) { a.bar() - a.foo() + a.foo() } a?.foo() a?.bar() @@ -26,7 +26,7 @@ fun f9(a : A?) { return; } a.bar() - a.foo() + a.foo() } fun f10(a : A?) { @@ -80,7 +80,7 @@ fun f12(a : A?) { fun f13(a : A?) { if (a is B) { - a.foo() + a.foo() a.bar() } else { @@ -93,12 +93,12 @@ fun f13(a : A?) { a?.foo() } else { - a.foo() + a.foo() } a?.foo() - if (a is B && a.foo() == Unit.VALUE) { - a.foo() + if (a is B && a.foo() == Unit.VALUE) { + a.foo() a.bar() } else {