提交 8723bbca 编写于 作者: S Svetlana Isakova

KT-1875 Safe call should be binded with receiver or this object (but not with both by default)

 #KT-1875 fixed
上级 47934b1f
......@@ -224,6 +224,7 @@ public class CallResolver {
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER);
ResolutionCandidate<CallableDescriptor> resolutionCandidate = ResolutionCandidate.<CallableDescriptor>create(functionDescriptor);
resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver());
resolutionCandidate.setExplicitReceiverKind(ExplicitReceiverKind.RECEIVER_ARGUMENT);
// strictly speaking, this is a hack:
// we need to pass a reference, but there's no reference in the PSI,
......@@ -327,7 +328,7 @@ public class CallResolver {
// Now, we try to remove this argument and see if it helps
Collection<ResolutionCandidate<D>> newCandidates = Lists.newArrayList();
for (ResolutionCandidate<D> candidate : task.getCandidates()) {
newCandidates.add(ResolutionCandidate.create(candidate.getDescriptor()));
newCandidates.add(ResolutionCandidate.create(candidate.getDescriptor(), candidate.getExplicitReceiverKind()));
}
ResolutionTask<D, F> newContext = new ResolutionTask<D, F>(newCandidates, task.reference, TemporaryBindingTrace.create(task.trace), task.scope, new DelegatingCall(task.call) {
@NotNull
......@@ -628,20 +629,35 @@ public class CallResolver {
private <D extends CallableDescriptor, F extends D> ResolutionStatus checkAllValueArguments(CallResolutionContext<D, F> context) {
ResolutionStatus result = checkValueArgumentTypes(context);
ResolvedCall candidateCall = context.candidateCall;
result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument()));
result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject()));
// 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
// both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
// Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument(),
candidateCall.getExplicitReceiverKind().isReceiver(), false));
result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject(),
candidateCall.getExplicitReceiverKind().isThisObject(),
// for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' as callOperationNode if necessary
context.call instanceof CallTransformer.CallForImplicitInvoke));
return result;
}
private <D extends CallableDescriptor, F extends D> ResolutionStatus checkReceiver(CallResolutionContext<D, F> context, ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument) {
private <D extends CallableDescriptor, F extends D> ResolutionStatus checkReceiver(CallResolutionContext<D, F> context, ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument,
boolean isExplicitReceiver, boolean implicitInvokeCheck) {
ResolutionStatus result = SUCCESS;
if (receiverParameter.exists() && receiverArgument.exists()) {
ASTNode callOperationNode = context.call.getCallOperationNode();
boolean safeAccess = callOperationNode != null && callOperationNode.getElementType() == JetTokens.SAFE_ACCESS;
boolean safeAccess = !implicitInvokeCheck && isExplicitReceiver && callOperationNode != null && callOperationNode.getElementType() == JetTokens.SAFE_ACCESS;
JetType receiverArgumentType = receiverArgument.getType();
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.candidateCall.getTrace().getBindingContext());
if (!safeAccess && !receiverParameter.getType().isNullable() && !autoCastService.isNotNull(receiverArgument)) {
context.tracing.unsafeCall(context.candidateCall.getTrace(), receiverArgumentType);
context.tracing.unsafeCall(context.candidateCall.getTrace(), receiverArgumentType, implicitInvokeCheck);
result = UNSAFE_CALL_ERROR;
}
else {
......@@ -653,7 +669,6 @@ public class CallResolver {
result = OTHER_ERROR;
}
}
if (safeAccess && (receiverParameter.getType().isNullable() || !receiverArgumentType.isNullable())) {
context.tracing.unnecessarySafeCall(context.candidateCall.getTrace(), receiverArgumentType);
}
......@@ -840,9 +855,6 @@ public class CallResolver {
TemporaryBindingTrace temporaryTrace = result.getTrace();
temporaryTrace.commit();
if (result instanceof VariableAsFunctionResolvedCall) {
((VariableAsFunctionResolvedCall)result).getVariableCall().getTrace().commit();
}
return OverloadResolutionResultsImpl.success(result);
}
}
......
......@@ -101,7 +101,7 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
candidate, variableCall, temporaryTrace, task);
ResolutionCandidate<CallableDescriptor> candidateWithoutReceiver = ResolutionCandidate.create(
candidate.getDescriptor(), candidate.getThisObject(), ReceiverDescriptor.NO_RECEIVER);
candidate.getDescriptor(), candidate.getThisObject(), ReceiverDescriptor.NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER);
CallResolutionContext<CallableDescriptor, FunctionDescriptor> contextWithoutReceiver = createContextWithChainedTrace(
candidateWithoutReceiver, variableCallWithoutReceiver, temporaryTrace, task);
......@@ -203,7 +203,7 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
final JetSimpleNameExpression invokeExpression = (JetSimpleNameExpression) JetPsiFactory.createExpression(
task.call.getCallElement().getProject(), "invoke");
return new DelegatingCall(task.call) {
return new CallForImplicitInvoke(task.call) {
@NotNull
@Override
public ReceiverDescriptor getExplicitReceiver() {
......@@ -236,4 +236,10 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
};
}
};
public static class CallForImplicitInvoke extends DelegatingCall {
public CallForImplicitInvoke(@NotNull Call delegate) {
super(delegate);
}
}
}
/*
* Copyright 2010-2012 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;
/**
* @author svtk
*/
public enum ExplicitReceiverKind {
RECEIVER_ARGUMENT,
THIS_OBJECT,
NO_EXPLICIT_RECEIVER,
// A very special case.
// In a call 'b.foo(1)' where class 'Foo' has an extension member 'fun B.invoke(Int)' function 'invoke' has two explicit receivers:
// 'b' (as receiver argument) and 'foo' (as this object).
BOTH_RECEIVERS;
public boolean isReceiver() {
return this == RECEIVER_ARGUMENT || this == BOTH_RECEIVERS;
}
public boolean isThisObject() {
return this == THIS_OBJECT || this == BOTH_RECEIVERS;
}
}
......@@ -33,6 +33,7 @@ public class ResolutionCandidate<D extends CallableDescriptor> {
private final D candidateDescriptor;
private ReceiverDescriptor thisObject; // receiver object of a method
private ReceiverDescriptor receiverArgument; // receiver of an extension function
private ExplicitReceiverKind explicitReceiverKind;
private ResolutionCandidate(@NotNull D descriptor, @NotNull ReceiverDescriptor thisObject, @NotNull ReceiverDescriptor receiverArgument) {
this.candidateDescriptor = descriptor;
......@@ -44,8 +45,16 @@ public class ResolutionCandidate<D extends CallableDescriptor> {
return new ResolutionCandidate<D>(descriptor, NO_RECEIVER, NO_RECEIVER);
}
public static <D extends CallableDescriptor> ResolutionCandidate<D> create(@NotNull D descriptor, @NotNull ReceiverDescriptor thisObject, @NotNull ReceiverDescriptor receiverArgument) {
return new ResolutionCandidate<D>(descriptor, thisObject, receiverArgument);
public static <D extends CallableDescriptor> ResolutionCandidate<D> create(@NotNull D descriptor, @NotNull ExplicitReceiverKind explicitReceiverKind) {
ResolutionCandidate<D> candidate = new ResolutionCandidate<D>(descriptor, NO_RECEIVER, NO_RECEIVER);
candidate.setExplicitReceiverKind(explicitReceiverKind);
return candidate;
}
public static <D extends CallableDescriptor> ResolutionCandidate<D> create(@NotNull D descriptor, @NotNull ReceiverDescriptor thisObject, @NotNull ReceiverDescriptor receiverArgument, @NotNull ExplicitReceiverKind explicitReceiverKind) {
ResolutionCandidate<D> resolutionCandidate = new ResolutionCandidate<D>(descriptor, thisObject, receiverArgument);
resolutionCandidate.setExplicitReceiverKind(explicitReceiverKind);
return resolutionCandidate;
}
public void setThisObject(@NotNull ReceiverDescriptor thisObject) {
......@@ -56,6 +65,10 @@ public class ResolutionCandidate<D extends CallableDescriptor> {
this.receiverArgument = receiverArgument;
}
public void setExplicitReceiverKind(@NotNull ExplicitReceiverKind explicitReceiverKind) {
this.explicitReceiverKind = explicitReceiverKind;
}
@NotNull
public D getDescriptor() {
return candidateDescriptor;
......@@ -70,12 +83,19 @@ public class ResolutionCandidate<D extends CallableDescriptor> {
public ReceiverDescriptor getReceiverArgument() {
return receiverArgument;
}
@NotNull
public ExplicitReceiverKind getExplicitReceiverKind() {
return explicitReceiverKind;
}
@NotNull
public static <D extends CallableDescriptor> List<ResolutionCandidate<D>> convertCollection(@NotNull Collection<? extends D> descriptors) {
List<ResolutionCandidate<D>> result = Lists.newArrayList();
for (D descriptor : descriptors) {
result.add(create(descriptor));
ResolutionCandidate<D> candidate = create(descriptor);
candidate.setExplicitReceiverKind(ExplicitReceiverKind.NO_EXPLICIT_RECEIVER);
result.add(candidate);
}
return result;
}
......
......@@ -16,7 +16,6 @@
package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
......@@ -195,9 +194,9 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends R
}
@Override
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type, boolean isCallForImplicitInvoke) {
ASTNode callOperationNode = call.getCallOperationNode();
if (callOperationNode != null) {
if (callOperationNode != null && !isCallForImplicitInvoke) {
trace.report(UNSAFE_CALL.on(callOperationNode.getPsi(), type));
}
else {
......
......@@ -46,6 +46,10 @@ public interface ResolvedCall<D extends CallableDescriptor> {
@NotNull
ReceiverDescriptor getThisObject();
/** Determines whether receiver argument or this object is substituted for explicit receiver */
@NotNull
ExplicitReceiverKind getExplicitReceiverKind();
/** Values (arguments) for value parameters */
@NotNull
Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments();
......
......@@ -53,18 +53,14 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
@NotNull
public static <D extends CallableDescriptor> ResolvedCallImpl<D> create(@NotNull ResolutionCandidate<D> candidate, @NotNull TemporaryBindingTrace trace) {
return create(candidate.getDescriptor(), candidate.getThisObject(), candidate.getReceiverArgument(), trace);
}
@NotNull
public static <D extends CallableDescriptor> ResolvedCallImpl<D> create(@NotNull D descriptor, @NotNull ReceiverDescriptor thisObject, @NotNull ReceiverDescriptor receiverArgument, @NotNull TemporaryBindingTrace trace) {
return new ResolvedCallImpl<D>(descriptor, thisObject, receiverArgument, trace);
return new ResolvedCallImpl<D>(candidate, trace);
}
private final D candidateDescriptor;
private D resultingDescriptor; // Probably substituted
private final ReceiverDescriptor thisObject; // receiver object of a method
private final ReceiverDescriptor receiverArgument; // receiver of an extension function
private final ExplicitReceiverKind explicitReceiverKind;
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap();
......@@ -73,13 +69,15 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
private TemporaryBindingTrace trace;
private ResolutionStatus status = UNKNOWN_STATUS;
private ResolvedCallImpl(@NotNull D candidateDescriptor, @NotNull ReceiverDescriptor thisObject, @NotNull ReceiverDescriptor receiverArgument, @NotNull TemporaryBindingTrace trace) {
this.candidateDescriptor = candidateDescriptor;
this.thisObject = thisObject;
this.receiverArgument = receiverArgument;
private ResolvedCallImpl(@NotNull ResolutionCandidate<D> candidate, @NotNull TemporaryBindingTrace trace) {
this.candidateDescriptor = candidate.getDescriptor();
this.thisObject = candidate.getThisObject();
this.receiverArgument = candidate.getReceiverArgument();
this.explicitReceiverKind = candidate.getExplicitReceiverKind();
this.trace = trace;
}
@Override
@NotNull
public ResolutionStatus getStatus() {
return status;
......@@ -89,6 +87,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
this.status = this.status.combine(status);
}
@Override
@NotNull
public TemporaryBindingTrace getTrace() {
return trace;
......@@ -138,6 +137,12 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
return thisObject;
}
@Override
@NotNull
public ExplicitReceiverKind getExplicitReceiverKind() {
return explicitReceiverKind;
}
@Override
@NotNull
public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() {
......@@ -171,6 +176,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
this.someArgumentHasNoType = true;
}
@Override
public boolean isDirty() {
return someArgumentHasNoType;
}
......
......@@ -109,7 +109,8 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.trace.getBindingContext());
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(implicitReceivers);
if (context.call.getThisObject().exists()) {
boolean hasExplicitThisObject = context.call.getThisObject().exists();
if (hasExplicitThisObject) {
implicitReceivers.add(context.call.getThisObject());
}
if (receiver.exists()) {
......@@ -124,7 +125,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
Collection<ResolutionCandidate<D>> members = Lists.newArrayList();
for (ReceiverDescriptor variant : variantsForExplicitReceiver) {
Collection<? extends D> membersForThisVariant = callableDescriptorCollector.getMembersByName(variant.getType(), name);
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant), Collections.singletonList(NO_RECEIVER), members);
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant), Collections.singletonList(NO_RECEIVER), members, hasExplicitThisObject);
}
result.addLocalExtensions(locals);
......@@ -134,7 +135,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
Collection<? extends D> memberExtensions = callableDescriptorCollector.getNonMembersByName(
implicitReceiver.getType().getMemberScope(), name);
List<ReceiverDescriptor> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver);
result.addNonLocalExtensions(convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver));
result.addNonLocalExtensions(convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver, hasExplicitThisObject));
}
result.addNonLocalExtensions(nonlocals);
......@@ -157,20 +158,26 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
}
}
private static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithReceivers(Collection<? extends D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters) {
private static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithReceivers(Collection<? extends D> descriptors, Iterable<ReceiverDescriptor> thisObjects,
Iterable<ReceiverDescriptor> receiverParameters, boolean hasExplicitThisObject) {
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
convertWithReceivers(descriptors, thisObjects, receiverParameters, result);
convertWithReceivers(descriptors, thisObjects, receiverParameters, result, hasExplicitThisObject);
return result;
}
private static <D extends CallableDescriptor> void convertWithReceivers(Collection<? extends D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters, Collection<ResolutionCandidate<D>> result) {
private static <D extends CallableDescriptor> void convertWithReceivers(Collection<? extends D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters,
Collection<ResolutionCandidate<D>> result, boolean hasExplicitThisObject) {
for (ReceiverDescriptor thisObject : thisObjects) {
for (ReceiverDescriptor receiverParameter : receiverParameters) {
for (D extension : descriptors) {
ResolutionCandidate<D> resolvedCall = ResolutionCandidate.create(extension);
resolvedCall.setThisObject(thisObject);
resolvedCall.setReceiverArgument(receiverParameter);
result.add(resolvedCall);
ResolutionCandidate<D> candidate = ResolutionCandidate.create(extension);
candidate.setThisObject(thisObject);
candidate.setReceiverArgument(receiverParameter);
candidate.setExplicitReceiverKind(
hasExplicitThisObject ? ExplicitReceiverKind.BOTH_RECEIVERS : ExplicitReceiverKind.THIS_OBJECT);
result.add(candidate);
}
}
}
......@@ -180,10 +187,12 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
for (ReceiverDescriptor receiverParameter : receiverParameters) {
for (D descriptor : descriptors) {
ResolutionCandidate<D> resolvedCall = ResolutionCandidate.create(descriptor);
resolvedCall.setReceiverArgument(receiverParameter);
if (setImpliedThis(scope, resolvedCall)) {
result.add(resolvedCall);
ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor);
candidate.setReceiverArgument(receiverParameter);
candidate.setExplicitReceiverKind(
receiverParameter.exists() ? ExplicitReceiverKind.RECEIVER_ARGUMENT : ExplicitReceiverKind.NO_EXPLICIT_RECEIVER);
if (setImpliedThis(scope, candidate)) {
result.add(candidate);
}
}
}
......@@ -195,24 +204,25 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
containingDeclaration = containingDeclaration.getContainingDeclaration();
}
if (containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT) {
ResolutionCandidate<D> resolvedCall = ResolutionCandidate.create(descriptor);
resolvedCall.setThisObject(new ClassReceiver((ClassDescriptor) containingDeclaration));
result.add(resolvedCall);
ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor);
candidate.setThisObject(new ClassReceiver((ClassDescriptor) containingDeclaration));
candidate.setExplicitReceiverKind(ExplicitReceiverKind.NO_EXPLICIT_RECEIVER);
result.add(candidate);
}
}
}
return result;
}
private static <D extends CallableDescriptor> boolean setImpliedThis(@NotNull JetScope scope, ResolutionCandidate<D> resolvedCall) {
ReceiverDescriptor expectedThisObject = resolvedCall.getDescriptor().getExpectedThisObject();
private static <D extends CallableDescriptor> boolean setImpliedThis(@NotNull JetScope scope, ResolutionCandidate<D> candidate) {
ReceiverDescriptor expectedThisObject = candidate.getDescriptor().getExpectedThisObject();
if (!expectedThisObject.exists()) return true;
List<ReceiverDescriptor> receivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(receivers);
for (ReceiverDescriptor receiver : receivers) {
if (JetTypeChecker.INSTANCE.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) {
// TODO : Autocasts & nullability
resolvedCall.setThisObject(expectedThisObject);
candidate.setThisObject(expectedThisObject);
return true;
}
}
......
......@@ -72,7 +72,7 @@ import java.util.List;
public void typeInferenceFailed(@NotNull BindingTrace trace, SolutionStatus status) {}
@Override
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {}
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type, boolean isCallForImplicitInvoke) {}
@Override
public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {}
......@@ -108,7 +108,7 @@ import java.util.List;
void typeInferenceFailed(@NotNull BindingTrace trace, SolutionStatus status);
void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type, boolean isCallForImplicitInvoke);
void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
......
......@@ -73,6 +73,12 @@ public class VariableAsFunctionResolvedCall implements ResolvedCallWithTrace<Fun
return variableCall.getThisObject();
}
@NotNull
@Override
public ExplicitReceiverKind getExplicitReceiverKind() {
return variableCall.getExplicitReceiverKind();
}
@NotNull
@Override
public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() {
......
//KT-1875 Safe call should be binded with receiver or this object (but not with both by default)
package kt1875
fun f(a : Int?, b : Int.(Int)->Int) = a?.b(1) //unnecessary safe call warning
trait T {
val f : ((i: Int) -> Unit)?
}
fun test(t: T) {
t.<!UNSAFE_CALL!>f<!>(1) //unsafe call error
t.f?.invoke(1)
}
fun test1(t: T?) {
t<!UNSAFE_CALL!>.<!><!UNSAFE_CALL!>f<!>(1)
t?.<!UNSAFE_CALL!>f<!>(1)
t<!UNSAFE_CALL!>.<!>f?.invoke(1)
t?.f?.invoke(1)
}
\ No newline at end of file
......@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.calls.ExplicitReceiverKind;
import org.jetbrains.jet.lang.resolve.calls.ResolutionCandidate;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl;
......@@ -106,7 +107,7 @@ public final class CallBuilder {
private CallTranslator finish() {
if (resolvedCall == null) {
assert descriptor != null;
resolvedCall = ResolvedCallImpl.create(ResolutionCandidate.create(descriptor),
resolvedCall = ResolvedCallImpl.create(ResolutionCandidate.create(descriptor, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER),
TemporaryBindingTrace.create(new BindingTraceContext())); //todo
}
if (descriptor == null) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册