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.resolve.BindingContext;
|
||||
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.util.CallMaker;
|
||||
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();
|
||||
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 {
|
||||
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.BindingContextUtils;
|
||||
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.ResolvedValueArgument;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
@@ -1061,10 +1060,6 @@ public class JetControlFlowProcessor {
|
||||
else if (receiver instanceof TransientReceiver) {
|
||||
// Do nothing
|
||||
}
|
||||
else if (receiver instanceof AutoCastReceiver) {
|
||||
// No cast instruction in our CFG
|
||||
generateReceiver(((AutoCastReceiver) receiver).getOriginal());
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown receiver kind: " + receiver);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class CandidateResolver {
|
||||
ResolvedCallImpl<D> candidateCall = context.candidateCall;
|
||||
D candidate = candidateCall.getCandidateDescriptor();
|
||||
|
||||
candidateCall.addStatus(checkReceiverTypeError(context.candidateCall));
|
||||
candidateCall.addStatus(checkReceiverTypeError(context));
|
||||
|
||||
if (ErrorUtils.isError(candidate)) {
|
||||
candidateCall.addStatus(SUCCESS);
|
||||
@@ -167,9 +167,6 @@ public class CandidateResolver {
|
||||
context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
|
||||
candidateCall.addStatus(OTHER_ERROR);
|
||||
}
|
||||
|
||||
AutoCastUtils.recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
|
||||
AutoCastUtils.recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
|
||||
}
|
||||
|
||||
private static void markAllArgumentsAsUnmapped(CallCandidateResolutionContext<?> context) {
|
||||
@@ -744,7 +741,7 @@ public class CandidateResolver {
|
||||
ResolutionStatus resultStatus = SUCCESS;
|
||||
ResolvedCall<D> candidateCall = context.candidateCall;
|
||||
|
||||
resultStatus = resultStatus.combine(checkReceiverTypeError(candidateCall));
|
||||
resultStatus = resultStatus.combine(checkReceiverTypeError(context));
|
||||
|
||||
// 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
|
||||
@@ -832,10 +829,9 @@ public class CandidateResolver {
|
||||
@NotNull ResolutionContext<?> context
|
||||
) {
|
||||
ExpressionReceiver receiverToCast = new ExpressionReceiver(JetPsiUtil.safeDeparenthesize(expression, false), actualType);
|
||||
List<ReceiverValue> variants =
|
||||
List<JetType> variants =
|
||||
AutoCastUtils.getAutoCastVariantsExcludingReceiver(context.trace.getBindingContext(), context.dataFlowInfo, receiverToCast);
|
||||
for (ReceiverValue receiverValue : variants) {
|
||||
JetType possibleType = receiverValue.getType();
|
||||
for (JetType possibleType : variants) {
|
||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) {
|
||||
return possibleType;
|
||||
}
|
||||
@@ -844,33 +840,35 @@ public class CandidateResolver {
|
||||
}
|
||||
|
||||
private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
|
||||
@NotNull ResolvedCall<D> candidateCall
|
||||
@NotNull CallCandidateResolutionContext<D> context
|
||||
) {
|
||||
ResolvedCallImpl<D> candidateCall = context.candidateCall;
|
||||
D candidateDescriptor = candidateCall.getCandidateDescriptor();
|
||||
if (candidateDescriptor instanceof ExpressionAsFunctionDescriptor) return SUCCESS;
|
||||
|
||||
ReceiverParameterDescriptor receiverDescriptor = candidateDescriptor.getReceiverParameter();
|
||||
ReceiverParameterDescriptor expectedThisObjectDescriptor = candidateDescriptor.getExpectedThisObject();
|
||||
ReceiverParameterDescriptor receiverParameterDescriptor;
|
||||
JetType receiverArgumentType;
|
||||
ReceiverValue receiverArgument;
|
||||
if (receiverDescriptor != null && candidateCall.getReceiverArgument().exists()) {
|
||||
receiverParameterDescriptor = receiverDescriptor;
|
||||
receiverArgumentType = candidateCall.getReceiverArgument().getType();
|
||||
receiverArgument = candidateCall.getReceiverArgument();
|
||||
}
|
||||
else if (expectedThisObjectDescriptor != null && candidateCall.getThisObject().exists()) {
|
||||
receiverParameterDescriptor = expectedThisObjectDescriptor;
|
||||
receiverArgumentType = candidateCall.getThisObject().getType();
|
||||
receiverArgument = candidateCall.getThisObject();
|
||||
}
|
||||
else {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
JetType effectiveReceiverArgumentType = TypeUtils.makeNotNullable(receiverArgumentType);
|
||||
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 SUCCESS;
|
||||
}
|
||||
|
||||
@@ -884,15 +882,19 @@ public class CandidateResolver {
|
||||
boolean implicitInvokeCheck
|
||||
) {
|
||||
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 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();
|
||||
boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && candidateCall.isSafeCall();
|
||||
@@ -902,7 +904,7 @@ public class CandidateResolver {
|
||||
context.tracing.unsafeCall(trace, receiverArgumentType, implicitInvokeCheck);
|
||||
return UNSAFE_CALL_ERROR;
|
||||
}
|
||||
if (isExplicitReceiver) {
|
||||
if (!smartCastRecorded && isExplicitReceiver) {
|
||||
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.resolve.BindingContext;
|
||||
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.scopes.receivers.ExpressionReceiver;
|
||||
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.TypeUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
@@ -41,20 +40,20 @@ public class AutoCastUtils {
|
||||
|
||||
private AutoCastUtils() {}
|
||||
|
||||
public static List<ReceiverValue> getAutoCastVariants(
|
||||
public static List<JetType> getAutoCastVariants(
|
||||
@NotNull ReceiverValue receiverToCast,
|
||||
@NotNull ResolutionContext context
|
||||
) {
|
||||
return getAutoCastVariants(receiverToCast, context.trace.getBindingContext(), context.dataFlowInfo);
|
||||
}
|
||||
|
||||
public static List<ReceiverValue> getAutoCastVariants(
|
||||
public static List<JetType> getAutoCastVariants(
|
||||
@NotNull ReceiverValue receiverToCast,
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull DataFlowInfo dataFlowInfo
|
||||
) {
|
||||
List<ReceiverValue> variants = Lists.newArrayList();
|
||||
variants.add(receiverToCast);
|
||||
List<JetType> variants = Lists.newArrayList();
|
||||
variants.add(receiverToCast.getType());
|
||||
variants.addAll(getAutoCastVariantsExcludingReceiver(bindingContext, dataFlowInfo, receiverToCast));
|
||||
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
|
||||
*/
|
||||
@NotNull
|
||||
public static List<ReceiverValue> getAutoCastVariantsExcludingReceiver(
|
||||
public static List<JetType> getAutoCastVariantsExcludingReceiver(
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull ReceiverValue receiverToCast
|
||||
@@ -72,46 +71,68 @@ public class AutoCastUtils {
|
||||
ThisReceiver receiver = (ThisReceiver) receiverToCast;
|
||||
assert receiver.exists();
|
||||
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver);
|
||||
return collectAutoCastReceiverValues(dataFlowInfo, receiver, dataFlowValue);
|
||||
return collectAutoCastReceiverValues(dataFlowInfo, dataFlowValue);
|
||||
}
|
||||
else if (receiverToCast instanceof ExpressionReceiver) {
|
||||
ExpressionReceiver receiver = (ExpressionReceiver) receiverToCast;
|
||||
DataFlowValue dataFlowValue =
|
||||
DataFlowValueFactory.createDataFlowValue(receiver.getExpression(), receiver.getType(), bindingContext);
|
||||
return collectAutoCastReceiverValues(dataFlowInfo, receiver, dataFlowValue);
|
||||
}
|
||||
else if (receiverToCast instanceof AutoCastReceiver) {
|
||||
return getAutoCastVariantsExcludingReceiver(bindingContext, dataFlowInfo, ((AutoCastReceiver) receiverToCast).getOriginal());
|
||||
return collectAutoCastReceiverValues(dataFlowInfo, dataFlowValue);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<ReceiverValue> collectAutoCastReceiverValues(
|
||||
private static List<JetType> collectAutoCastReceiverValues(
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull ReceiverValue receiver,
|
||||
@NotNull DataFlowValue dataFlowValue
|
||||
) {
|
||||
Set<JetType> possibleTypes = 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;
|
||||
return Lists.newArrayList(dataFlowInfo.getPossibleTypes(dataFlowValue));
|
||||
}
|
||||
|
||||
public static void recordAutoCastIfNecessary(ReceiverValue receiver, @NotNull BindingTrace trace) {
|
||||
if (receiver instanceof AutoCastReceiver) {
|
||||
AutoCastReceiver autoCastReceiver = (AutoCastReceiver) receiver;
|
||||
ReceiverValue original = autoCastReceiver.getOriginal();
|
||||
if (original instanceof ExpressionReceiver) {
|
||||
JetExpression expression = ((ExpressionReceiver) original).getExpression();
|
||||
recordCastOrError(expression, autoCastReceiver.getType(), trace, autoCastReceiver.canCast(), true);
|
||||
}
|
||||
else {
|
||||
assert autoCastReceiver.canCast() : "A non-expression receiver must always be autocastabe: " + original;
|
||||
public static boolean isSubTypeByAutoCast(
|
||||
@NotNull ReceiverValue receiverArgument,
|
||||
@NotNull JetType receiverParameterType,
|
||||
@NotNull ResolutionContext context
|
||||
) {
|
||||
List<JetType> autoCastTypes = getAutoCastVariants(receiverArgument, context);
|
||||
return isSubTypeByAutoCast(receiverParameterType, autoCastTypes);
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -153,9 +174,9 @@ public class AutoCastUtils {
|
||||
) {
|
||||
if (!receiver.getType().isNullable()) return true;
|
||||
|
||||
List<ReceiverValue> autoCastVariants = getAutoCastVariants(receiver, bindingContext, dataFlowInfo);
|
||||
for (ReceiverValue autoCastVariant : autoCastVariants) {
|
||||
if (!autoCastVariant.getType().isNullable()) return true;
|
||||
List<JetType> autoCastVariants = getAutoCastVariants(receiver, bindingContext, dataFlowInfo);
|
||||
for (JetType autoCastVariant : autoCastVariants) {
|
||||
if (!autoCastVariant.isNullable()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
-6
@@ -70,9 +70,6 @@ public class DataFlowValueFactory {
|
||||
else if (receiverValue instanceof ExpressionReceiver) {
|
||||
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) {
|
||||
throw new IllegalArgumentException("No DataFlowValue exists for ReceiverValue.NO_RECEIVER");
|
||||
}
|
||||
@@ -190,9 +187,6 @@ public class DataFlowValueFactory {
|
||||
if (receiverValue instanceof ThisReceiver) {
|
||||
return getIdForThisReceiver(((ThisReceiver) receiverValue).getDeclarationDescriptor());
|
||||
}
|
||||
else if (receiverValue instanceof AutoCastReceiver) {
|
||||
return getIdForImplicitReceiver(((AutoCastReceiver) receiverValue).getOriginal(), expression);
|
||||
}
|
||||
else {
|
||||
assert !(receiverValue instanceof TransientReceiver)
|
||||
: "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(
|
||||
@NotNull ReceiverValue receiver,
|
||||
@NotNull ReceiverValue explicitReceiver,
|
||||
@NotNull List<ReceiverValue> implicitReceivers,
|
||||
@NotNull TaskPrioritizerContext<D, F> c,
|
||||
boolean isExplicit
|
||||
) {
|
||||
|
||||
List<ReceiverValue> variantsForExplicitReceiver = AutoCastUtils.getAutoCastVariants(receiver, c.context);
|
||||
List<JetType> variantsForExplicitReceiver = AutoCastUtils.getAutoCastVariants(explicitReceiver, c.context);
|
||||
|
||||
//members
|
||||
for (CallableDescriptorCollector<? extends D> callableDescriptorCollector : c.callableDescriptorCollectors) {
|
||||
Collection<ResolutionCandidate<D>> members = Lists.newArrayList();
|
||||
for (ReceiverValue variant : variantsForExplicitReceiver) {
|
||||
for (JetType type : variantsForExplicitReceiver) {
|
||||
Collection<? extends D> membersForThisVariant =
|
||||
callableDescriptorCollector.getMembersByName(variant.getType(), c.name, c.context.trace);
|
||||
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant),
|
||||
Collections.singletonList(NO_RECEIVER), members, createKind(THIS_OBJECT, isExplicit));
|
||||
callableDescriptorCollector.getMembersByName(type, c.name, c.context.trace);
|
||||
convertWithReceivers(membersForThisVariant, explicitReceiver,
|
||||
NO_RECEIVER, members, createKind(THIS_OBJECT, isExplicit));
|
||||
}
|
||||
c.result.addCandidates(members);
|
||||
}
|
||||
@@ -151,12 +151,12 @@ public class TaskPrioritizer {
|
||||
for (CallableDescriptorCollector<? extends D> callableDescriptorCollector : c.callableDescriptorCollectors) {
|
||||
//member extensions
|
||||
for (ReceiverValue implicitReceiver : implicitReceivers) {
|
||||
addMemberExtensionCandidates(implicitReceiver, variantsForExplicitReceiver,
|
||||
addMemberExtensionCandidates(implicitReceiver, explicitReceiver,
|
||||
callableDescriptorCollector, c, createKind(RECEIVER_ARGUMENT, isExplicit));
|
||||
}
|
||||
//extensions
|
||||
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));
|
||||
c.result.addCandidates(extensions);
|
||||
}
|
||||
@@ -169,15 +169,14 @@ public class TaskPrioritizer {
|
||||
|
||||
private static <D extends CallableDescriptor, F extends D> void addMemberExtensionCandidates(
|
||||
@NotNull ReceiverValue thisObject,
|
||||
@NotNull List<ReceiverValue> receiverParameters,
|
||||
@NotNull ReceiverValue receiverParameter,
|
||||
@NotNull CallableDescriptorCollector<? extends D> callableDescriptorCollector, TaskPrioritizerContext<D, F> c,
|
||||
@NotNull ExplicitReceiverKind receiverKind
|
||||
) {
|
||||
Collection<? extends D> memberExtensions = callableDescriptorCollector.getNonMembersByName(
|
||||
thisObject.getType().getMemberScope(), c.name, c.context.trace);
|
||||
List<ReceiverValue> thisObjects = AutoCastUtils.getAutoCastVariants(thisObject, c.context);
|
||||
c.result.addCandidates(convertWithReceivers(
|
||||
memberExtensions, thisObjects, receiverParameters, receiverKind));
|
||||
memberExtensions, thisObject, receiverParameter, receiverKind));
|
||||
}
|
||||
|
||||
private static <D extends CallableDescriptor, F extends D> void addCandidatesForNoReceiver(
|
||||
@@ -255,45 +254,39 @@ public class TaskPrioritizer {
|
||||
@NotNull TaskPrioritizerContext<D, F> c,
|
||||
@NotNull ExplicitReceiverKind receiverKind
|
||||
) {
|
||||
List<ReceiverValue> receiverParameters = AutoCastUtils.getAutoCastVariants(receiverParameter, c.context);
|
||||
|
||||
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(
|
||||
@NotNull Collection<? extends D> descriptors,
|
||||
@NotNull Iterable<ReceiverValue> thisObjects,
|
||||
@NotNull Iterable<ReceiverValue> receiverParameters,
|
||||
@NotNull ReceiverValue thisObject,
|
||||
@NotNull ReceiverValue receiverParameter,
|
||||
@NotNull ExplicitReceiverKind explicitReceiverKind
|
||||
) {
|
||||
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
|
||||
convertWithReceivers(descriptors, thisObjects, receiverParameters, result, explicitReceiverKind);
|
||||
convertWithReceivers(descriptors, thisObject, receiverParameter, result, explicitReceiverKind);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static <D extends CallableDescriptor> void convertWithReceivers(
|
||||
@NotNull Collection<? extends D> descriptors,
|
||||
@NotNull Iterable<ReceiverValue> thisObjects,
|
||||
@NotNull Iterable<ReceiverValue> receiverParameters,
|
||||
@NotNull ReceiverValue thisObject,
|
||||
@NotNull ReceiverValue receiverParameter,
|
||||
@NotNull Collection<ResolutionCandidate<D>> result,
|
||||
@NotNull ExplicitReceiverKind explicitReceiverKind
|
||||
) {
|
||||
for (ReceiverValue thisObject : thisObjects) {
|
||||
for (ReceiverValue receiverParameter : receiverParameters) {
|
||||
for (D extension : descriptors) {
|
||||
if (DescriptorUtils.isConstructorOfStaticNestedClass(extension)) {
|
||||
// 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);
|
||||
}
|
||||
for (D extension : descriptors) {
|
||||
if (DescriptorUtils.isConstructorOfStaticNestedClass(extension)) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,24 +294,22 @@ public class TaskPrioritizer {
|
||||
@NotNull JetScope scope,
|
||||
@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(
|
||||
@NotNull JetScope scope,
|
||||
@NotNull Collection<ReceiverValue> receiverParameters,
|
||||
@NotNull ReceiverValue receiverParameter,
|
||||
@NotNull Collection<? extends D> descriptors,
|
||||
ExplicitReceiverKind receiverKind
|
||||
) {
|
||||
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
|
||||
for (ReceiverValue receiverParameter : receiverParameters) {
|
||||
for (D descriptor : descriptors) {
|
||||
ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor);
|
||||
candidate.setReceiverArgument(receiverParameter);
|
||||
candidate.setExplicitReceiverKind(receiverKind);
|
||||
if (setImpliedThis(scope, candidate)) {
|
||||
result.add(candidate);
|
||||
}
|
||||
for (D descriptor : descriptors) {
|
||||
ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor);
|
||||
candidate.setReceiverArgument(receiverParameter);
|
||||
candidate.setExplicitReceiverKind(receiverKind);
|
||||
if (setImpliedThis(scope, candidate)) {
|
||||
result.add(candidate);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (sup is Sub) {
|
||||
println("${<!DEBUG_INFO_AUTOCAST!>sup<!>.property}")
|
||||
println(<!DEBUG_INFO_AUTOCAST!>sup<!>.property)
|
||||
println("${sup.property}")
|
||||
println(sup.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");
|
||||
}
|
||||
|
||||
@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")
|
||||
public void testSmartCastOnReceiver() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/smartCasts/inference/smartCastOnReceiver.kt");
|
||||
|
||||
@@ -69,12 +69,12 @@ public final class TipsManager {
|
||||
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(
|
||||
excludePrivateDescriptors(descriptor.getType().getMemberScope().getAllDescriptors()),
|
||||
resolutionScope, descriptor));
|
||||
excludePrivateDescriptors(variant.getMemberScope().getAllDescriptors()),
|
||||
resolutionScope, receiverValue));
|
||||
}
|
||||
|
||||
return descriptors;
|
||||
|
||||
@@ -11,7 +11,7 @@ fun f9(a : A?) {
|
||||
a<info>?.</info><error descr="[UNRESOLVED_REFERENCE] Unresolved reference: bar">bar</error>()
|
||||
if (a is B) {
|
||||
<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><error descr="[UNRESOLVED_REFERENCE] Unresolved reference: bar">bar</error>()
|
||||
@@ -26,7 +26,7 @@ fun f9(a : A?) {
|
||||
return;
|
||||
}
|
||||
<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?) {
|
||||
@@ -80,7 +80,7 @@ fun f12(a : A?) {
|
||||
|
||||
fun f13(a : A?) {
|
||||
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()
|
||||
}
|
||||
else {
|
||||
@@ -93,12 +93,12 @@ fun f13(a : A?) {
|
||||
a<info>?.</info>foo()
|
||||
}
|
||||
else {
|
||||
<info descr="Automatically cast to B">a</info>.foo()
|
||||
<info descr="Automatically cast to A">a</info>.foo()
|
||||
}
|
||||
|
||||
a<info>?.</info>foo()
|
||||
if (a is B && <info descr="Automatically cast to B">a</info>.foo() == Unit.VALUE) {
|
||||
<info descr="Automatically cast to B">a</info>.foo()
|
||||
if (a is B && <info descr="Automatically cast to A">a</info>.foo() == Unit.VALUE) {
|
||||
<info descr="Automatically cast to A">a</info>.foo()
|
||||
<info descr="Automatically cast to B">a</info>.bar()
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
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.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver;
|
||||
@@ -120,10 +119,6 @@ public final class JsDescriptorUtils {
|
||||
if (receiverParameter instanceof ThisReceiver) {
|
||||
declarationDescriptor = ((ThisReceiver) receiverParameter).getDeclarationDescriptor();
|
||||
}
|
||||
else if (receiverParameter instanceof AutoCastReceiver) {
|
||||
AutoCastReceiver autoCastReceiver = ((AutoCastReceiver) receiverParameter);
|
||||
declarationDescriptor = getDeclarationDescriptorForReceiver(autoCastReceiver.getOriginal());
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Unsupported receiver type: " + receiverParameter);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user