diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 34d491c15f5..96bfededdf0 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -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 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); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 11306ec0a52..0434d0822fc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -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); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index bfdb61ee990..86ea5cfe42e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -74,7 +74,7 @@ public class CandidateResolver { ResolvedCallImpl 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 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 variants = + List 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 ResolutionStatus checkReceiverTypeError( - @NotNull ResolvedCall candidateCall + @NotNull CallCandidateResolutionContext context ) { + ResolvedCallImpl 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); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastReceiver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastReceiver.java deleted file mode 100644 index 2ece3be430a..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastReceiver.java +++ /dev/null @@ -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() + ")"; - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java index 876c11df923..cae1d47e6cc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java @@ -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 getAutoCastVariants( + public static List getAutoCastVariants( @NotNull ReceiverValue receiverToCast, @NotNull ResolutionContext context ) { return getAutoCastVariants(receiverToCast, context.trace.getBindingContext(), context.dataFlowInfo); } - public static List getAutoCastVariants( + public static List getAutoCastVariants( @NotNull ReceiverValue receiverToCast, @NotNull BindingContext bindingContext, @NotNull DataFlowInfo dataFlowInfo ) { - List variants = Lists.newArrayList(); - variants.add(receiverToCast); + List 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 getAutoCastVariantsExcludingReceiver( + public static List 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 collectAutoCastReceiverValues( + private static List collectAutoCastReceiverValues( @NotNull DataFlowInfo dataFlowInfo, - @NotNull ReceiverValue receiver, @NotNull DataFlowValue dataFlowValue ) { - Set possibleTypes = dataFlowInfo.getPossibleTypes(dataFlowValue); - List result = new ArrayList(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 autoCastTypes = getAutoCastVariants(receiverArgument, context); + return isSubTypeByAutoCast(receiverParameterType, autoCastTypes); + } + + private static boolean isSubTypeByAutoCast( + @NotNull JetType receiverParameterType, + @NotNull List 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 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 autoCastVariants = getAutoCastVariants(receiver, bindingContext, dataFlowInfo); - for (ReceiverValue autoCastVariant : autoCastVariants) { - if (!autoCastVariant.getType().isNullable()) return true; + List autoCastVariants = getAutoCastVariants(receiver, bindingContext, dataFlowInfo); + for (JetType autoCastVariant : autoCastVariants) { + if (!autoCastVariant.isNullable()) return true; } return false; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowValueFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowValueFactory.java index 850601736f3..8f1f4997eaa 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowValueFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowValueFactory.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java index 60f6b23e066..a0ea7c6a766 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java @@ -128,22 +128,22 @@ public class TaskPrioritizer { } private static void addCandidatesForExplicitReceiver( - @NotNull ReceiverValue receiver, + @NotNull ReceiverValue explicitReceiver, @NotNull List implicitReceivers, @NotNull TaskPrioritizerContext c, boolean isExplicit ) { - List variantsForExplicitReceiver = AutoCastUtils.getAutoCastVariants(receiver, c.context); + List variantsForExplicitReceiver = AutoCastUtils.getAutoCastVariants(explicitReceiver, c.context); //members for (CallableDescriptorCollector callableDescriptorCollector : c.callableDescriptorCollectors) { Collection> members = Lists.newArrayList(); - for (ReceiverValue variant : variantsForExplicitReceiver) { + for (JetType type : variantsForExplicitReceiver) { Collection 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 callableDescriptorCollector : c.callableDescriptorCollectors) { //member extensions for (ReceiverValue implicitReceiver : implicitReceivers) { - addMemberExtensionCandidates(implicitReceiver, variantsForExplicitReceiver, + addMemberExtensionCandidates(implicitReceiver, explicitReceiver, callableDescriptorCollector, c, createKind(RECEIVER_ARGUMENT, isExplicit)); } //extensions Collection> 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 void addMemberExtensionCandidates( @NotNull ReceiverValue thisObject, - @NotNull List receiverParameters, + @NotNull ReceiverValue receiverParameter, @NotNull CallableDescriptorCollector callableDescriptorCollector, TaskPrioritizerContext c, @NotNull ExplicitReceiverKind receiverKind ) { Collection memberExtensions = callableDescriptorCollector.getNonMembersByName( thisObject.getType().getMemberScope(), c.name, c.context.trace); - List thisObjects = AutoCastUtils.getAutoCastVariants(thisObject, c.context); c.result.addCandidates(convertWithReceivers( - memberExtensions, thisObjects, receiverParameters, receiverKind)); + memberExtensions, thisObject, receiverParameter, receiverKind)); } private static void addCandidatesForNoReceiver( @@ -255,45 +254,39 @@ public class TaskPrioritizer { @NotNull TaskPrioritizerContext c, @NotNull ExplicitReceiverKind receiverKind ) { - List receiverParameters = AutoCastUtils.getAutoCastVariants(receiverParameter, c.context); - for (CallableDescriptorCollector callableDescriptorCollector : c.callableDescriptorCollectors) { - addMemberExtensionCandidates(thisObject, receiverParameters, callableDescriptorCollector, c, receiverKind); + addMemberExtensionCandidates(thisObject, receiverParameter, callableDescriptorCollector, c, receiverKind); } } private static Collection> convertWithReceivers( @NotNull Collection descriptors, - @NotNull Iterable thisObjects, - @NotNull Iterable receiverParameters, + @NotNull ReceiverValue thisObject, + @NotNull ReceiverValue receiverParameter, @NotNull ExplicitReceiverKind explicitReceiverKind ) { Collection> result = Lists.newArrayList(); - convertWithReceivers(descriptors, thisObjects, receiverParameters, result, explicitReceiverKind); + convertWithReceivers(descriptors, thisObject, receiverParameter, result, explicitReceiverKind); return result; } private static void convertWithReceivers( @NotNull Collection descriptors, - @NotNull Iterable thisObjects, - @NotNull Iterable receiverParameters, + @NotNull ReceiverValue thisObject, + @NotNull ReceiverValue receiverParameter, @NotNull Collection> 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 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 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 descriptors ) { - return convertWithImpliedThis(scope, Collections.singletonList(NO_RECEIVER), descriptors, NO_EXPLICIT_RECEIVER); + return convertWithImpliedThis(scope, NO_RECEIVER, descriptors, NO_EXPLICIT_RECEIVER); } public static Collection> convertWithImpliedThis( @NotNull JetScope scope, - @NotNull Collection receiverParameters, + @NotNull ReceiverValue receiverParameter, @NotNull Collection descriptors, ExplicitReceiverKind receiverKind ) { Collection> result = Lists.newArrayList(); - for (ReceiverValue receiverParameter : receiverParameters) { - for (D descriptor : descriptors) { - ResolutionCandidate candidate = ResolutionCandidate.create(descriptor); - candidate.setReceiverArgument(receiverParameter); - candidate.setExplicitReceiverKind(receiverKind); - if (setImpliedThis(scope, candidate)) { - result.add(candidate); - } + for (D descriptor : descriptors) { + ResolutionCandidate candidate = ResolutionCandidate.create(descriptor); + candidate.setReceiverArgument(receiverParameter); + candidate.setExplicitReceiverKind(receiverKind); + if (setImpliedThis(scope, candidate)) { + result.add(candidate); } } return result; diff --git a/compiler/testData/diagnostics/tests/smartCasts/inference/kt4403.kt b/compiler/testData/diagnostics/tests/smartCasts/inference/kt4403.kt new file mode 100644 index 00000000000..a51e416ada4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/inference/kt4403.kt @@ -0,0 +1,11 @@ +//KT-4403 Wrong "type mismatch" on smart cast with inference + +trait A +trait B : A + +fun T.f(): T = this + +fun test(a: A) { + if (a !is B) return + val c = a.f() // type mismatch +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/inference/kt4415.kt b/compiler/testData/diagnostics/tests/smartCasts/inference/kt4415.kt new file mode 100644 index 00000000000..a45dd7c2d1a --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/inference/kt4415.kt @@ -0,0 +1,17 @@ +//KT-4415 Class Auto-Cast Bug + +trait SelfJson + +object A { + fun find(clz:Class<*>){ } + + fun toJson2(obj:Any){ + if(obj is SelfJson){ + // A.find( (obj as SelfJson).javaClass) // OK + A.find( obj.javaClass ) // ERROR: Type mismatch: inferred type is jet.Any but SelfJson was expected + } + } +} + +//from library +val T.javaClass : Class get() = throw Exception() diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt1461.kt b/compiler/testData/diagnostics/tests/smartCasts/kt1461.kt index 9a453904b98..585117a5696 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/kt1461.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/kt1461.kt @@ -7,8 +7,8 @@ class Sub(str : String) : Super(str) {} fun foo(sup : Super, sub : Sub) { if (sup is Sub) { - println("${sup.property}") - println(sup.property) + println("${sup.property}") + println(sup.property) } println("${sub.property}") println(sub.property) diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 19c9c44656f..91372f90588 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -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"); diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.java index d9a7a8eabce..d202f6d75e3 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.java +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.java @@ -69,12 +69,12 @@ public final class TipsManager { info = DataFlowInfo.EMPTY; } - List variantsForExplicitReceiver = AutoCastUtils.getAutoCastVariants(receiverValue, context, info); + List 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; diff --git a/idea/testData/checker/infos/Autocasts.kt b/idea/testData/checker/infos/Autocasts.kt index e6bbb1ef9c8..f001b26fd81 100644 --- a/idea/testData/checker/infos/Autocasts.kt +++ b/idea/testData/checker/infos/Autocasts.kt @@ -11,7 +11,7 @@ fun f9(a : A?) { a?.bar() if (a is B) { a.bar() - a.foo() + a.foo() } a?.foo() a?.bar() @@ -26,7 +26,7 @@ fun f9(a : A?) { return; } a.bar() - a.foo() + a.foo() } fun f10(a : A?) { @@ -80,7 +80,7 @@ fun f12(a : A?) { fun f13(a : A?) { if (a is B) { - a.foo() + a.foo() a.bar() } else { @@ -93,12 +93,12 @@ fun f13(a : A?) { a?.foo() } else { - a.foo() + a.foo() } a?.foo() - if (a is B && a.foo() == Unit.VALUE) { - a.foo() + if (a is B && a.foo() == Unit.VALUE) { + a.foo() a.bar() } else { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java index 49b51891e79..8554f97cd75 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java @@ -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); }