removed AutoCastReceiver

check subtype for receiver by AutoCastUtils.isSubTypeByAutoCast directly
 #KT-4403 Fixed
 #KT-4415 Fixed
This commit is contained in:
Svetlana Isakova
2014-01-18 23:13:31 +04:00
parent 5ef320173c
commit 9ed57a5767
14 changed files with 161 additions and 179 deletions
@@ -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);
}
}
@@ -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() + ")";
}
}
@@ -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;
}
@@ -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;
@@ -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;
+6 -6
View File
@@ -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);
}