removed AutoCastReceiver
check subtype for receiver by AutoCastUtils.isSubTypeByAutoCast directly #KT-4403 Fixed #KT-4415 Fixed
This commit is contained in:
@@ -46,7 +46,6 @@ import org.jetbrains.jet.lang.evaluate.EvaluatePackage;
|
|||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastReceiver;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.*;
|
import org.jetbrains.jet.lang.resolve.calls.model.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
|
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
|
import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
|
||||||
@@ -2168,12 +2167,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
JetExpression expr = expressionReceiver.getExpression();
|
JetExpression expr = expressionReceiver.getExpression();
|
||||||
gen(expr, type);
|
gen(expr, type);
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof AutoCastReceiver) {
|
|
||||||
AutoCastReceiver autoCastReceiver = (AutoCastReceiver) descriptor;
|
|
||||||
Type originalType = asmType(autoCastReceiver.getOriginal().getType());
|
|
||||||
generateFromResolvedCall(autoCastReceiver.getOriginal(), originalType);
|
|
||||||
StackValue.onStack(originalType).put(type, v);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("Unsupported receiver type: " + descriptor);
|
throw new UnsupportedOperationException("Unsupported receiver type: " + descriptor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import org.jetbrains.jet.lang.psi.*;
|
|||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastReceiver;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||||
@@ -1061,10 +1060,6 @@ public class JetControlFlowProcessor {
|
|||||||
else if (receiver instanceof TransientReceiver) {
|
else if (receiver instanceof TransientReceiver) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
else if (receiver instanceof AutoCastReceiver) {
|
|
||||||
// No cast instruction in our CFG
|
|
||||||
generateReceiver(((AutoCastReceiver) receiver).getOriginal());
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
throw new IllegalArgumentException("Unknown receiver kind: " + receiver);
|
throw new IllegalArgumentException("Unknown receiver kind: " + receiver);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public class CandidateResolver {
|
|||||||
ResolvedCallImpl<D> candidateCall = context.candidateCall;
|
ResolvedCallImpl<D> candidateCall = context.candidateCall;
|
||||||
D candidate = candidateCall.getCandidateDescriptor();
|
D candidate = candidateCall.getCandidateDescriptor();
|
||||||
|
|
||||||
candidateCall.addStatus(checkReceiverTypeError(context.candidateCall));
|
candidateCall.addStatus(checkReceiverTypeError(context));
|
||||||
|
|
||||||
if (ErrorUtils.isError(candidate)) {
|
if (ErrorUtils.isError(candidate)) {
|
||||||
candidateCall.addStatus(SUCCESS);
|
candidateCall.addStatus(SUCCESS);
|
||||||
@@ -167,9 +167,6 @@ public class CandidateResolver {
|
|||||||
context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
|
context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
|
||||||
candidateCall.addStatus(OTHER_ERROR);
|
candidateCall.addStatus(OTHER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoCastUtils.recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
|
|
||||||
AutoCastUtils.recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void markAllArgumentsAsUnmapped(CallCandidateResolutionContext<?> context) {
|
private static void markAllArgumentsAsUnmapped(CallCandidateResolutionContext<?> context) {
|
||||||
@@ -744,7 +741,7 @@ public class CandidateResolver {
|
|||||||
ResolutionStatus resultStatus = SUCCESS;
|
ResolutionStatus resultStatus = SUCCESS;
|
||||||
ResolvedCall<D> candidateCall = context.candidateCall;
|
ResolvedCall<D> candidateCall = context.candidateCall;
|
||||||
|
|
||||||
resultStatus = resultStatus.combine(checkReceiverTypeError(candidateCall));
|
resultStatus = resultStatus.combine(checkReceiverTypeError(context));
|
||||||
|
|
||||||
// Comment about a very special case.
|
// Comment about a very special case.
|
||||||
// Call 'b.foo(1)' where class 'Foo' has an extension member 'fun B.invoke(Int)' should be checked two times for safe call (in 'checkReceiver'), because
|
// Call 'b.foo(1)' where class 'Foo' has an extension member 'fun B.invoke(Int)' should be checked two times for safe call (in 'checkReceiver'), because
|
||||||
@@ -832,10 +829,9 @@ public class CandidateResolver {
|
|||||||
@NotNull ResolutionContext<?> context
|
@NotNull ResolutionContext<?> context
|
||||||
) {
|
) {
|
||||||
ExpressionReceiver receiverToCast = new ExpressionReceiver(JetPsiUtil.safeDeparenthesize(expression, false), actualType);
|
ExpressionReceiver receiverToCast = new ExpressionReceiver(JetPsiUtil.safeDeparenthesize(expression, false), actualType);
|
||||||
List<ReceiverValue> variants =
|
List<JetType> variants =
|
||||||
AutoCastUtils.getAutoCastVariantsExcludingReceiver(context.trace.getBindingContext(), context.dataFlowInfo, receiverToCast);
|
AutoCastUtils.getAutoCastVariantsExcludingReceiver(context.trace.getBindingContext(), context.dataFlowInfo, receiverToCast);
|
||||||
for (ReceiverValue receiverValue : variants) {
|
for (JetType possibleType : variants) {
|
||||||
JetType possibleType = receiverValue.getType();
|
|
||||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) {
|
if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) {
|
||||||
return possibleType;
|
return possibleType;
|
||||||
}
|
}
|
||||||
@@ -844,33 +840,35 @@ public class CandidateResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
|
private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
|
||||||
@NotNull ResolvedCall<D> candidateCall
|
@NotNull CallCandidateResolutionContext<D> context
|
||||||
) {
|
) {
|
||||||
|
ResolvedCallImpl<D> candidateCall = context.candidateCall;
|
||||||
D candidateDescriptor = candidateCall.getCandidateDescriptor();
|
D candidateDescriptor = candidateCall.getCandidateDescriptor();
|
||||||
if (candidateDescriptor instanceof ExpressionAsFunctionDescriptor) return SUCCESS;
|
if (candidateDescriptor instanceof ExpressionAsFunctionDescriptor) return SUCCESS;
|
||||||
|
|
||||||
ReceiverParameterDescriptor receiverDescriptor = candidateDescriptor.getReceiverParameter();
|
ReceiverParameterDescriptor receiverDescriptor = candidateDescriptor.getReceiverParameter();
|
||||||
ReceiverParameterDescriptor expectedThisObjectDescriptor = candidateDescriptor.getExpectedThisObject();
|
ReceiverParameterDescriptor expectedThisObjectDescriptor = candidateDescriptor.getExpectedThisObject();
|
||||||
ReceiverParameterDescriptor receiverParameterDescriptor;
|
ReceiverParameterDescriptor receiverParameterDescriptor;
|
||||||
JetType receiverArgumentType;
|
ReceiverValue receiverArgument;
|
||||||
if (receiverDescriptor != null && candidateCall.getReceiverArgument().exists()) {
|
if (receiverDescriptor != null && candidateCall.getReceiverArgument().exists()) {
|
||||||
receiverParameterDescriptor = receiverDescriptor;
|
receiverParameterDescriptor = receiverDescriptor;
|
||||||
receiverArgumentType = candidateCall.getReceiverArgument().getType();
|
receiverArgument = candidateCall.getReceiverArgument();
|
||||||
}
|
}
|
||||||
else if (expectedThisObjectDescriptor != null && candidateCall.getThisObject().exists()) {
|
else if (expectedThisObjectDescriptor != null && candidateCall.getThisObject().exists()) {
|
||||||
receiverParameterDescriptor = expectedThisObjectDescriptor;
|
receiverParameterDescriptor = expectedThisObjectDescriptor;
|
||||||
receiverArgumentType = candidateCall.getThisObject().getType();
|
receiverArgument = candidateCall.getThisObject();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
JetType effectiveReceiverArgumentType = TypeUtils.makeNotNullable(receiverArgumentType);
|
|
||||||
JetType erasedReceiverType = CallResolverUtil.getErasedReceiverType(receiverParameterDescriptor, candidateDescriptor);
|
JetType erasedReceiverType = CallResolverUtil.getErasedReceiverType(receiverParameterDescriptor, candidateDescriptor);
|
||||||
|
|
||||||
if (!JetTypeChecker.INSTANCE.isSubtypeOf(effectiveReceiverArgumentType, erasedReceiverType)) {
|
boolean isSubtypeByAutoCast = AutoCastUtils.isSubTypeByAutoCast(receiverArgument, erasedReceiverType, context);
|
||||||
|
if (!isSubtypeByAutoCast) {
|
||||||
return RECEIVER_TYPE_ERROR;
|
return RECEIVER_TYPE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -884,15 +882,19 @@ public class CandidateResolver {
|
|||||||
boolean implicitInvokeCheck
|
boolean implicitInvokeCheck
|
||||||
) {
|
) {
|
||||||
if (receiverParameter == null || !receiverArgument.exists()) return SUCCESS;
|
if (receiverParameter == null || !receiverArgument.exists()) return SUCCESS;
|
||||||
|
D candidateDescriptor = candidateCall.getCandidateDescriptor();
|
||||||
|
|
||||||
|
boolean smartCastRecorded = false;
|
||||||
|
if (!TypeUtils.dependsOnTypeParameters(receiverParameter.getType(), candidateDescriptor.getTypeParameters())) {
|
||||||
|
boolean isSubtypeByAutoCast = AutoCastUtils.isSubTypeByAutoCast(receiverArgument, receiverParameter.getType(), context);
|
||||||
|
if (!isSubtypeByAutoCast) {
|
||||||
|
context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument);
|
||||||
|
return OTHER_ERROR;
|
||||||
|
}
|
||||||
|
smartCastRecorded = AutoCastUtils.recordAutoCastIfNecessary(receiverArgument, receiverParameter.getType(), context);
|
||||||
|
}
|
||||||
|
|
||||||
JetType receiverArgumentType = receiverArgument.getType();
|
JetType receiverArgumentType = receiverArgument.getType();
|
||||||
JetType effectiveReceiverArgumentType = TypeUtils.makeNotNullable(receiverArgumentType);
|
|
||||||
D candidateDescriptor = candidateCall.getCandidateDescriptor();
|
|
||||||
if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(effectiveReceiverArgumentType, receiverParameter.getType())
|
|
||||||
&& !TypeUtils.dependsOnTypeParameters(receiverParameter.getType(), candidateDescriptor.getTypeParameters())) {
|
|
||||||
context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument);
|
|
||||||
return OTHER_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
BindingContext bindingContext = trace.getBindingContext();
|
BindingContext bindingContext = trace.getBindingContext();
|
||||||
boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && candidateCall.isSafeCall();
|
boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && candidateCall.isSafeCall();
|
||||||
@@ -902,7 +904,7 @@ public class CandidateResolver {
|
|||||||
context.tracing.unsafeCall(trace, receiverArgumentType, implicitInvokeCheck);
|
context.tracing.unsafeCall(trace, receiverArgumentType, implicitInvokeCheck);
|
||||||
return UNSAFE_CALL_ERROR;
|
return UNSAFE_CALL_ERROR;
|
||||||
}
|
}
|
||||||
if (isExplicitReceiver) {
|
if (!smartCastRecorded && isExplicitReceiver) {
|
||||||
AutoCastUtils.recordAutoCastToNotNullableType(receiverArgument, context.trace);
|
AutoCastUtils.recordAutoCastToNotNullableType(receiverArgument, context.trace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-47
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2013 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve.calls.autocasts;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.AbstractReceiverValue;
|
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
|
||||||
|
|
||||||
public class AutoCastReceiver extends AbstractReceiverValue {
|
|
||||||
private final ReceiverValue original;
|
|
||||||
private final boolean canCast;
|
|
||||||
|
|
||||||
public AutoCastReceiver(@NotNull ReceiverValue original, @NotNull JetType castTo, boolean canCast) {
|
|
||||||
super(castTo);
|
|
||||||
this.original = original;
|
|
||||||
this.canCast = canCast;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canCast() {
|
|
||||||
return canCast;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public ReceiverValue getOriginal() {
|
|
||||||
return original;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "(" + original + " as " + getType() + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+54
-33
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
|
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||||
@@ -28,10 +29,8 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver;
|
|||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.AUTOCAST_IMPOSSIBLE;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.AUTOCAST_IMPOSSIBLE;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
|
||||||
@@ -41,20 +40,20 @@ public class AutoCastUtils {
|
|||||||
|
|
||||||
private AutoCastUtils() {}
|
private AutoCastUtils() {}
|
||||||
|
|
||||||
public static List<ReceiverValue> getAutoCastVariants(
|
public static List<JetType> getAutoCastVariants(
|
||||||
@NotNull ReceiverValue receiverToCast,
|
@NotNull ReceiverValue receiverToCast,
|
||||||
@NotNull ResolutionContext context
|
@NotNull ResolutionContext context
|
||||||
) {
|
) {
|
||||||
return getAutoCastVariants(receiverToCast, context.trace.getBindingContext(), context.dataFlowInfo);
|
return getAutoCastVariants(receiverToCast, context.trace.getBindingContext(), context.dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<ReceiverValue> getAutoCastVariants(
|
public static List<JetType> getAutoCastVariants(
|
||||||
@NotNull ReceiverValue receiverToCast,
|
@NotNull ReceiverValue receiverToCast,
|
||||||
@NotNull BindingContext bindingContext,
|
@NotNull BindingContext bindingContext,
|
||||||
@NotNull DataFlowInfo dataFlowInfo
|
@NotNull DataFlowInfo dataFlowInfo
|
||||||
) {
|
) {
|
||||||
List<ReceiverValue> variants = Lists.newArrayList();
|
List<JetType> variants = Lists.newArrayList();
|
||||||
variants.add(receiverToCast);
|
variants.add(receiverToCast.getType());
|
||||||
variants.addAll(getAutoCastVariantsExcludingReceiver(bindingContext, dataFlowInfo, receiverToCast));
|
variants.addAll(getAutoCastVariantsExcludingReceiver(bindingContext, dataFlowInfo, receiverToCast));
|
||||||
return variants;
|
return variants;
|
||||||
}
|
}
|
||||||
@@ -63,7 +62,7 @@ public class AutoCastUtils {
|
|||||||
* @return variants @param receiverToCast may be cast to according to @param dataFlowInfo, @param receiverToCast itself is NOT included
|
* @return variants @param receiverToCast may be cast to according to @param dataFlowInfo, @param receiverToCast itself is NOT included
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public static List<ReceiverValue> getAutoCastVariantsExcludingReceiver(
|
public static List<JetType> getAutoCastVariantsExcludingReceiver(
|
||||||
@NotNull BindingContext bindingContext,
|
@NotNull BindingContext bindingContext,
|
||||||
@NotNull DataFlowInfo dataFlowInfo,
|
@NotNull DataFlowInfo dataFlowInfo,
|
||||||
@NotNull ReceiverValue receiverToCast
|
@NotNull ReceiverValue receiverToCast
|
||||||
@@ -72,46 +71,68 @@ public class AutoCastUtils {
|
|||||||
ThisReceiver receiver = (ThisReceiver) receiverToCast;
|
ThisReceiver receiver = (ThisReceiver) receiverToCast;
|
||||||
assert receiver.exists();
|
assert receiver.exists();
|
||||||
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver);
|
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver);
|
||||||
return collectAutoCastReceiverValues(dataFlowInfo, receiver, dataFlowValue);
|
return collectAutoCastReceiverValues(dataFlowInfo, dataFlowValue);
|
||||||
}
|
}
|
||||||
else if (receiverToCast instanceof ExpressionReceiver) {
|
else if (receiverToCast instanceof ExpressionReceiver) {
|
||||||
ExpressionReceiver receiver = (ExpressionReceiver) receiverToCast;
|
ExpressionReceiver receiver = (ExpressionReceiver) receiverToCast;
|
||||||
DataFlowValue dataFlowValue =
|
DataFlowValue dataFlowValue =
|
||||||
DataFlowValueFactory.createDataFlowValue(receiver.getExpression(), receiver.getType(), bindingContext);
|
DataFlowValueFactory.createDataFlowValue(receiver.getExpression(), receiver.getType(), bindingContext);
|
||||||
return collectAutoCastReceiverValues(dataFlowInfo, receiver, dataFlowValue);
|
return collectAutoCastReceiverValues(dataFlowInfo, dataFlowValue);
|
||||||
}
|
|
||||||
else if (receiverToCast instanceof AutoCastReceiver) {
|
|
||||||
return getAutoCastVariantsExcludingReceiver(bindingContext, dataFlowInfo, ((AutoCastReceiver) receiverToCast).getOriginal());
|
|
||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static List<ReceiverValue> collectAutoCastReceiverValues(
|
private static List<JetType> collectAutoCastReceiverValues(
|
||||||
@NotNull DataFlowInfo dataFlowInfo,
|
@NotNull DataFlowInfo dataFlowInfo,
|
||||||
@NotNull ReceiverValue receiver,
|
|
||||||
@NotNull DataFlowValue dataFlowValue
|
@NotNull DataFlowValue dataFlowValue
|
||||||
) {
|
) {
|
||||||
Set<JetType> possibleTypes = dataFlowInfo.getPossibleTypes(dataFlowValue);
|
return Lists.newArrayList(dataFlowInfo.getPossibleTypes(dataFlowValue));
|
||||||
List<ReceiverValue> result = new ArrayList<ReceiverValue>(possibleTypes.size());
|
|
||||||
for (JetType possibleType : possibleTypes) {
|
|
||||||
result.add(new AutoCastReceiver(receiver, possibleType, dataFlowValue.isStableIdentifier()));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void recordAutoCastIfNecessary(ReceiverValue receiver, @NotNull BindingTrace trace) {
|
public static boolean isSubTypeByAutoCast(
|
||||||
if (receiver instanceof AutoCastReceiver) {
|
@NotNull ReceiverValue receiverArgument,
|
||||||
AutoCastReceiver autoCastReceiver = (AutoCastReceiver) receiver;
|
@NotNull JetType receiverParameterType,
|
||||||
ReceiverValue original = autoCastReceiver.getOriginal();
|
@NotNull ResolutionContext context
|
||||||
if (original instanceof ExpressionReceiver) {
|
) {
|
||||||
JetExpression expression = ((ExpressionReceiver) original).getExpression();
|
List<JetType> autoCastTypes = getAutoCastVariants(receiverArgument, context);
|
||||||
recordCastOrError(expression, autoCastReceiver.getType(), trace, autoCastReceiver.canCast(), true);
|
return isSubTypeByAutoCast(receiverParameterType, autoCastTypes);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
assert autoCastReceiver.canCast() : "A non-expression receiver must always be autocastabe: " + original;
|
private static boolean isSubTypeByAutoCast(
|
||||||
|
@NotNull JetType receiverParameterType,
|
||||||
|
@NotNull List<JetType> autoCastTypes
|
||||||
|
) {
|
||||||
|
for (JetType autoCastType : autoCastTypes) {
|
||||||
|
JetType effectiveAutoCastType = TypeUtils.makeNotNullable(autoCastType);
|
||||||
|
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(effectiveAutoCastType, receiverParameterType)) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean recordAutoCastIfNecessary(
|
||||||
|
ReceiverValue receiver,
|
||||||
|
@NotNull JetType receiverType,
|
||||||
|
@NotNull ResolutionContext context
|
||||||
|
) {
|
||||||
|
if (!(receiver instanceof ExpressionReceiver)) return false;
|
||||||
|
|
||||||
|
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(receiver.getType(), receiverType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<JetType> 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());
|
||||||
|
|
||||||
|
recordCastOrError(expression, receiverType, context.trace, dataFlowValue.isStableIdentifier(), true);
|
||||||
|
}
|
||||||
|
return autoCast;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void recordAutoCastToNotNullableType(@NotNull ReceiverValue receiver, @NotNull BindingTrace trace) {
|
public static void recordAutoCastToNotNullableType(@NotNull ReceiverValue receiver, @NotNull BindingTrace trace) {
|
||||||
@@ -153,9 +174,9 @@ public class AutoCastUtils {
|
|||||||
) {
|
) {
|
||||||
if (!receiver.getType().isNullable()) return true;
|
if (!receiver.getType().isNullable()) return true;
|
||||||
|
|
||||||
List<ReceiverValue> autoCastVariants = getAutoCastVariants(receiver, bindingContext, dataFlowInfo);
|
List<JetType> autoCastVariants = getAutoCastVariants(receiver, bindingContext, dataFlowInfo);
|
||||||
for (ReceiverValue autoCastVariant : autoCastVariants) {
|
for (JetType autoCastVariant : autoCastVariants) {
|
||||||
if (!autoCastVariant.getType().isNullable()) return true;
|
if (!autoCastVariant.isNullable()) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
-6
@@ -70,9 +70,6 @@ public class DataFlowValueFactory {
|
|||||||
else if (receiverValue instanceof ExpressionReceiver) {
|
else if (receiverValue instanceof ExpressionReceiver) {
|
||||||
return createDataFlowValue(((ExpressionReceiver) receiverValue).getExpression(), receiverValue.getType(), bindingContext);
|
return createDataFlowValue(((ExpressionReceiver) receiverValue).getExpression(), receiverValue.getType(), bindingContext);
|
||||||
}
|
}
|
||||||
else if (receiverValue instanceof AutoCastReceiver) {
|
|
||||||
return createDataFlowValue(((AutoCastReceiver) receiverValue).getOriginal(), bindingContext);
|
|
||||||
}
|
|
||||||
else if (receiverValue == ReceiverValue.NO_RECEIVER) {
|
else if (receiverValue == ReceiverValue.NO_RECEIVER) {
|
||||||
throw new IllegalArgumentException("No DataFlowValue exists for ReceiverValue.NO_RECEIVER");
|
throw new IllegalArgumentException("No DataFlowValue exists for ReceiverValue.NO_RECEIVER");
|
||||||
}
|
}
|
||||||
@@ -190,9 +187,6 @@ public class DataFlowValueFactory {
|
|||||||
if (receiverValue instanceof ThisReceiver) {
|
if (receiverValue instanceof ThisReceiver) {
|
||||||
return getIdForThisReceiver(((ThisReceiver) receiverValue).getDeclarationDescriptor());
|
return getIdForThisReceiver(((ThisReceiver) receiverValue).getDeclarationDescriptor());
|
||||||
}
|
}
|
||||||
else if (receiverValue instanceof AutoCastReceiver) {
|
|
||||||
return getIdForImplicitReceiver(((AutoCastReceiver) receiverValue).getOriginal(), expression);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
assert !(receiverValue instanceof TransientReceiver)
|
assert !(receiverValue instanceof TransientReceiver)
|
||||||
: "Transient receiver is implicit for an explicit expression: " + expression + ". Receiver: " + receiverValue;
|
: "Transient receiver is implicit for an explicit expression: " + expression + ". Receiver: " + receiverValue;
|
||||||
|
|||||||
+33
-42
@@ -128,22 +128,22 @@ public class TaskPrioritizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor, F extends D> void addCandidatesForExplicitReceiver(
|
private static <D extends CallableDescriptor, F extends D> void addCandidatesForExplicitReceiver(
|
||||||
@NotNull ReceiverValue receiver,
|
@NotNull ReceiverValue explicitReceiver,
|
||||||
@NotNull List<ReceiverValue> implicitReceivers,
|
@NotNull List<ReceiverValue> implicitReceivers,
|
||||||
@NotNull TaskPrioritizerContext<D, F> c,
|
@NotNull TaskPrioritizerContext<D, F> c,
|
||||||
boolean isExplicit
|
boolean isExplicit
|
||||||
) {
|
) {
|
||||||
|
|
||||||
List<ReceiverValue> variantsForExplicitReceiver = AutoCastUtils.getAutoCastVariants(receiver, c.context);
|
List<JetType> variantsForExplicitReceiver = AutoCastUtils.getAutoCastVariants(explicitReceiver, c.context);
|
||||||
|
|
||||||
//members
|
//members
|
||||||
for (CallableDescriptorCollector<? extends D> callableDescriptorCollector : c.callableDescriptorCollectors) {
|
for (CallableDescriptorCollector<? extends D> callableDescriptorCollector : c.callableDescriptorCollectors) {
|
||||||
Collection<ResolutionCandidate<D>> members = Lists.newArrayList();
|
Collection<ResolutionCandidate<D>> members = Lists.newArrayList();
|
||||||
for (ReceiverValue variant : variantsForExplicitReceiver) {
|
for (JetType type : variantsForExplicitReceiver) {
|
||||||
Collection<? extends D> membersForThisVariant =
|
Collection<? extends D> membersForThisVariant =
|
||||||
callableDescriptorCollector.getMembersByName(variant.getType(), c.name, c.context.trace);
|
callableDescriptorCollector.getMembersByName(type, c.name, c.context.trace);
|
||||||
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant),
|
convertWithReceivers(membersForThisVariant, explicitReceiver,
|
||||||
Collections.singletonList(NO_RECEIVER), members, createKind(THIS_OBJECT, isExplicit));
|
NO_RECEIVER, members, createKind(THIS_OBJECT, isExplicit));
|
||||||
}
|
}
|
||||||
c.result.addCandidates(members);
|
c.result.addCandidates(members);
|
||||||
}
|
}
|
||||||
@@ -151,12 +151,12 @@ public class TaskPrioritizer {
|
|||||||
for (CallableDescriptorCollector<? extends D> callableDescriptorCollector : c.callableDescriptorCollectors) {
|
for (CallableDescriptorCollector<? extends D> callableDescriptorCollector : c.callableDescriptorCollectors) {
|
||||||
//member extensions
|
//member extensions
|
||||||
for (ReceiverValue implicitReceiver : implicitReceivers) {
|
for (ReceiverValue implicitReceiver : implicitReceivers) {
|
||||||
addMemberExtensionCandidates(implicitReceiver, variantsForExplicitReceiver,
|
addMemberExtensionCandidates(implicitReceiver, explicitReceiver,
|
||||||
callableDescriptorCollector, c, createKind(RECEIVER_ARGUMENT, isExplicit));
|
callableDescriptorCollector, c, createKind(RECEIVER_ARGUMENT, isExplicit));
|
||||||
}
|
}
|
||||||
//extensions
|
//extensions
|
||||||
Collection<ResolutionCandidate<D>> extensions = convertWithImpliedThis(
|
Collection<ResolutionCandidate<D>> extensions = convertWithImpliedThis(
|
||||||
c.scope, variantsForExplicitReceiver, callableDescriptorCollector.getNonMembersByName(c.scope, c.name, c.context.trace),
|
c.scope, explicitReceiver, callableDescriptorCollector.getNonMembersByName(c.scope, c.name, c.context.trace),
|
||||||
createKind(RECEIVER_ARGUMENT, isExplicit));
|
createKind(RECEIVER_ARGUMENT, isExplicit));
|
||||||
c.result.addCandidates(extensions);
|
c.result.addCandidates(extensions);
|
||||||
}
|
}
|
||||||
@@ -169,15 +169,14 @@ public class TaskPrioritizer {
|
|||||||
|
|
||||||
private static <D extends CallableDescriptor, F extends D> void addMemberExtensionCandidates(
|
private static <D extends CallableDescriptor, F extends D> void addMemberExtensionCandidates(
|
||||||
@NotNull ReceiverValue thisObject,
|
@NotNull ReceiverValue thisObject,
|
||||||
@NotNull List<ReceiverValue> receiverParameters,
|
@NotNull ReceiverValue receiverParameter,
|
||||||
@NotNull CallableDescriptorCollector<? extends D> callableDescriptorCollector, TaskPrioritizerContext<D, F> c,
|
@NotNull CallableDescriptorCollector<? extends D> callableDescriptorCollector, TaskPrioritizerContext<D, F> c,
|
||||||
@NotNull ExplicitReceiverKind receiverKind
|
@NotNull ExplicitReceiverKind receiverKind
|
||||||
) {
|
) {
|
||||||
Collection<? extends D> memberExtensions = callableDescriptorCollector.getNonMembersByName(
|
Collection<? extends D> memberExtensions = callableDescriptorCollector.getNonMembersByName(
|
||||||
thisObject.getType().getMemberScope(), c.name, c.context.trace);
|
thisObject.getType().getMemberScope(), c.name, c.context.trace);
|
||||||
List<ReceiverValue> thisObjects = AutoCastUtils.getAutoCastVariants(thisObject, c.context);
|
|
||||||
c.result.addCandidates(convertWithReceivers(
|
c.result.addCandidates(convertWithReceivers(
|
||||||
memberExtensions, thisObjects, receiverParameters, receiverKind));
|
memberExtensions, thisObject, receiverParameter, receiverKind));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor, F extends D> void addCandidatesForNoReceiver(
|
private static <D extends CallableDescriptor, F extends D> void addCandidatesForNoReceiver(
|
||||||
@@ -255,45 +254,39 @@ public class TaskPrioritizer {
|
|||||||
@NotNull TaskPrioritizerContext<D, F> c,
|
@NotNull TaskPrioritizerContext<D, F> c,
|
||||||
@NotNull ExplicitReceiverKind receiverKind
|
@NotNull ExplicitReceiverKind receiverKind
|
||||||
) {
|
) {
|
||||||
List<ReceiverValue> receiverParameters = AutoCastUtils.getAutoCastVariants(receiverParameter, c.context);
|
|
||||||
|
|
||||||
for (CallableDescriptorCollector<? extends D> callableDescriptorCollector : c.callableDescriptorCollectors) {
|
for (CallableDescriptorCollector<? extends D> callableDescriptorCollector : c.callableDescriptorCollectors) {
|
||||||
addMemberExtensionCandidates(thisObject, receiverParameters, callableDescriptorCollector, c, receiverKind);
|
addMemberExtensionCandidates(thisObject, receiverParameter, callableDescriptorCollector, c, receiverKind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithReceivers(
|
private static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithReceivers(
|
||||||
@NotNull Collection<? extends D> descriptors,
|
@NotNull Collection<? extends D> descriptors,
|
||||||
@NotNull Iterable<ReceiverValue> thisObjects,
|
@NotNull ReceiverValue thisObject,
|
||||||
@NotNull Iterable<ReceiverValue> receiverParameters,
|
@NotNull ReceiverValue receiverParameter,
|
||||||
@NotNull ExplicitReceiverKind explicitReceiverKind
|
@NotNull ExplicitReceiverKind explicitReceiverKind
|
||||||
) {
|
) {
|
||||||
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
|
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
|
||||||
convertWithReceivers(descriptors, thisObjects, receiverParameters, result, explicitReceiverKind);
|
convertWithReceivers(descriptors, thisObject, receiverParameter, result, explicitReceiverKind);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> void convertWithReceivers(
|
private static <D extends CallableDescriptor> void convertWithReceivers(
|
||||||
@NotNull Collection<? extends D> descriptors,
|
@NotNull Collection<? extends D> descriptors,
|
||||||
@NotNull Iterable<ReceiverValue> thisObjects,
|
@NotNull ReceiverValue thisObject,
|
||||||
@NotNull Iterable<ReceiverValue> receiverParameters,
|
@NotNull ReceiverValue receiverParameter,
|
||||||
@NotNull Collection<ResolutionCandidate<D>> result,
|
@NotNull Collection<ResolutionCandidate<D>> result,
|
||||||
@NotNull ExplicitReceiverKind explicitReceiverKind
|
@NotNull ExplicitReceiverKind explicitReceiverKind
|
||||||
) {
|
) {
|
||||||
for (ReceiverValue thisObject : thisObjects) {
|
for (D extension : descriptors) {
|
||||||
for (ReceiverValue receiverParameter : receiverParameters) {
|
if (DescriptorUtils.isConstructorOfStaticNestedClass(extension)) {
|
||||||
for (D extension : descriptors) {
|
// We don't want static nested classes' constructors to be resolved with expectedThisObject
|
||||||
if (DescriptorUtils.isConstructorOfStaticNestedClass(extension)) {
|
continue;
|
||||||
// We don't want static nested classes' constructors to be resolved with expectedThisObject
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ResolutionCandidate<D> candidate = ResolutionCandidate.create(extension);
|
|
||||||
candidate.setThisObject(thisObject);
|
|
||||||
candidate.setReceiverArgument(receiverParameter);
|
|
||||||
candidate.setExplicitReceiverKind(explicitReceiverKind);
|
|
||||||
result.add(candidate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ResolutionCandidate<D> candidate = ResolutionCandidate.create(extension);
|
||||||
|
candidate.setThisObject(thisObject);
|
||||||
|
candidate.setReceiverArgument(receiverParameter);
|
||||||
|
candidate.setExplicitReceiverKind(explicitReceiverKind);
|
||||||
|
result.add(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,24 +294,22 @@ public class TaskPrioritizer {
|
|||||||
@NotNull JetScope scope,
|
@NotNull JetScope scope,
|
||||||
@NotNull Collection<? extends D> descriptors
|
@NotNull Collection<? extends D> descriptors
|
||||||
) {
|
) {
|
||||||
return convertWithImpliedThis(scope, Collections.singletonList(NO_RECEIVER), descriptors, NO_EXPLICIT_RECEIVER);
|
return convertWithImpliedThis(scope, NO_RECEIVER, descriptors, NO_EXPLICIT_RECEIVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithImpliedThis(
|
public static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithImpliedThis(
|
||||||
@NotNull JetScope scope,
|
@NotNull JetScope scope,
|
||||||
@NotNull Collection<ReceiverValue> receiverParameters,
|
@NotNull ReceiverValue receiverParameter,
|
||||||
@NotNull Collection<? extends D> descriptors,
|
@NotNull Collection<? extends D> descriptors,
|
||||||
ExplicitReceiverKind receiverKind
|
ExplicitReceiverKind receiverKind
|
||||||
) {
|
) {
|
||||||
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
|
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
|
||||||
for (ReceiverValue receiverParameter : receiverParameters) {
|
for (D descriptor : descriptors) {
|
||||||
for (D descriptor : descriptors) {
|
ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor);
|
||||||
ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor);
|
candidate.setReceiverArgument(receiverParameter);
|
||||||
candidate.setReceiverArgument(receiverParameter);
|
candidate.setExplicitReceiverKind(receiverKind);
|
||||||
candidate.setExplicitReceiverKind(receiverKind);
|
if (setImpliedThis(scope, candidate)) {
|
||||||
if (setImpliedThis(scope, candidate)) {
|
result.add(candidate);
|
||||||
result.add(candidate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
//KT-4403 Wrong "type mismatch" on smart cast with inference
|
||||||
|
|
||||||
|
trait A
|
||||||
|
trait B : A
|
||||||
|
|
||||||
|
fun <T> T.f(): T = this
|
||||||
|
|
||||||
|
fun test(a: A) {
|
||||||
|
if (a !is B) return
|
||||||
|
val <!UNUSED_VARIABLE!>c<!> = <!DEBUG_INFO_AUTOCAST!>a<!>.f() // type mismatch
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
//KT-4415 Class Auto-Cast Bug
|
||||||
|
|
||||||
|
trait SelfJson
|
||||||
|
|
||||||
|
object A {
|
||||||
|
fun find(<!UNUSED_PARAMETER!>clz<!>:Class<*>){ }
|
||||||
|
|
||||||
|
fun toJson2(obj:Any){
|
||||||
|
if(obj is SelfJson){
|
||||||
|
// A.find( (obj as SelfJson).javaClass) // OK
|
||||||
|
A.find( <!DEBUG_INFO_AUTOCAST!>obj<!>.javaClass ) // ERROR: Type mismatch: inferred type is jet.Any but SelfJson was expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//from library
|
||||||
|
val <T> T.javaClass : Class<T> get() = throw Exception()
|
||||||
@@ -7,8 +7,8 @@ class Sub(str : String) : Super(str) {}
|
|||||||
|
|
||||||
fun foo(sup : Super, sub : Sub) {
|
fun foo(sup : Super, sub : Sub) {
|
||||||
if (sup is Sub) {
|
if (sup is Sub) {
|
||||||
println("${<!DEBUG_INFO_AUTOCAST!>sup<!>.property}")
|
println("${sup.property}")
|
||||||
println(<!DEBUG_INFO_AUTOCAST!>sup<!>.property)
|
println(sup.property)
|
||||||
}
|
}
|
||||||
println("${sub.property}")
|
println("${sub.property}")
|
||||||
println(sub.property)
|
println(sub.property)
|
||||||
|
|||||||
@@ -6433,6 +6433,16 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest("compiler/testData/diagnostics/tests/smartCasts/inference/kt4009.kt");
|
doTest("compiler/testData/diagnostics/tests/smartCasts/inference/kt4009.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt4403.kt")
|
||||||
|
public void testKt4403() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/smartCasts/inference/kt4403.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt4415.kt")
|
||||||
|
public void testKt4415() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/smartCasts/inference/kt4415.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("smartCastOnReceiver.kt")
|
@TestMetadata("smartCastOnReceiver.kt")
|
||||||
public void testSmartCastOnReceiver() throws Exception {
|
public void testSmartCastOnReceiver() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/smartCasts/inference/smartCastOnReceiver.kt");
|
doTest("compiler/testData/diagnostics/tests/smartCasts/inference/smartCastOnReceiver.kt");
|
||||||
|
|||||||
@@ -69,12 +69,12 @@ public final class TipsManager {
|
|||||||
info = DataFlowInfo.EMPTY;
|
info = DataFlowInfo.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ReceiverValue> variantsForExplicitReceiver = AutoCastUtils.getAutoCastVariants(receiverValue, context, info);
|
List<JetType> variantsForExplicitReceiver = AutoCastUtils.getAutoCastVariants(receiverValue, context, info);
|
||||||
|
|
||||||
for (ReceiverValue descriptor : variantsForExplicitReceiver) {
|
for (JetType variant : variantsForExplicitReceiver) {
|
||||||
descriptors.addAll(includeExternalCallableExtensions(
|
descriptors.addAll(includeExternalCallableExtensions(
|
||||||
excludePrivateDescriptors(descriptor.getType().getMemberScope().getAllDescriptors()),
|
excludePrivateDescriptors(variant.getMemberScope().getAllDescriptors()),
|
||||||
resolutionScope, descriptor));
|
resolutionScope, receiverValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptors;
|
return descriptors;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ fun f9(a : A?) {
|
|||||||
a<info>?.</info><error descr="[UNRESOLVED_REFERENCE] Unresolved reference: bar">bar</error>()
|
a<info>?.</info><error descr="[UNRESOLVED_REFERENCE] Unresolved reference: bar">bar</error>()
|
||||||
if (a is B) {
|
if (a is B) {
|
||||||
<info descr="Automatically cast to B">a</info>.bar()
|
<info descr="Automatically cast to B">a</info>.bar()
|
||||||
<info descr="Automatically cast to B">a</info>.foo()
|
<info descr="Automatically cast to A">a</info>.foo()
|
||||||
}
|
}
|
||||||
a<info>?.</info>foo()
|
a<info>?.</info>foo()
|
||||||
a<info>?.</info><error descr="[UNRESOLVED_REFERENCE] Unresolved reference: bar">bar</error>()
|
a<info>?.</info><error descr="[UNRESOLVED_REFERENCE] Unresolved reference: bar">bar</error>()
|
||||||
@@ -26,7 +26,7 @@ fun f9(a : A?) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
<info descr="Automatically cast to B">a</info>.bar()
|
<info descr="Automatically cast to B">a</info>.bar()
|
||||||
<info descr="Automatically cast to B">a</info>.foo()
|
<info descr="Automatically cast to A">a</info>.foo()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun f10(a : A?) {
|
fun f10(a : A?) {
|
||||||
@@ -80,7 +80,7 @@ fun f12(a : A?) {
|
|||||||
|
|
||||||
fun f13(a : A?) {
|
fun f13(a : A?) {
|
||||||
if (a is B) {
|
if (a is B) {
|
||||||
<info descr="Automatically cast to B">a</info>.foo()
|
<info descr="Automatically cast to A">a</info>.foo()
|
||||||
<info descr="Automatically cast to B">a</info>.bar()
|
<info descr="Automatically cast to B">a</info>.bar()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -93,12 +93,12 @@ fun f13(a : A?) {
|
|||||||
a<info>?.</info>foo()
|
a<info>?.</info>foo()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
<info descr="Automatically cast to B">a</info>.foo()
|
<info descr="Automatically cast to A">a</info>.foo()
|
||||||
}
|
}
|
||||||
|
|
||||||
a<info>?.</info>foo()
|
a<info>?.</info>foo()
|
||||||
if (a is B && <info descr="Automatically cast to B">a</info>.foo() == Unit.VALUE) {
|
if (a is B && <info descr="Automatically cast to A">a</info>.foo() == Unit.VALUE) {
|
||||||
<info descr="Automatically cast to B">a</info>.foo()
|
<info descr="Automatically cast to A">a</info>.foo()
|
||||||
<info descr="Automatically cast to B">a</info>.bar()
|
<info descr="Automatically cast to B">a</info>.bar()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import org.jetbrains.jet.lang.descriptors.*;
|
|||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastReceiver;
|
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver;
|
||||||
@@ -120,10 +119,6 @@ public final class JsDescriptorUtils {
|
|||||||
if (receiverParameter instanceof ThisReceiver) {
|
if (receiverParameter instanceof ThisReceiver) {
|
||||||
declarationDescriptor = ((ThisReceiver) receiverParameter).getDeclarationDescriptor();
|
declarationDescriptor = ((ThisReceiver) receiverParameter).getDeclarationDescriptor();
|
||||||
}
|
}
|
||||||
else if (receiverParameter instanceof AutoCastReceiver) {
|
|
||||||
AutoCastReceiver autoCastReceiver = ((AutoCastReceiver) receiverParameter);
|
|
||||||
declarationDescriptor = getDeclarationDescriptorForReceiver(autoCastReceiver.getOriginal());
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("Unsupported receiver type: " + receiverParameter);
|
throw new UnsupportedOperationException("Unsupported receiver type: " + receiverParameter);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user