Implicit receivers checked properly. Receiver checks restructured.

This commit is contained in:
Andrey Breslav
2011-10-11 18:25:01 +04:00
parent a39379edbf
commit c53754b3e8
23 changed files with 253 additions and 189 deletions
@@ -73,7 +73,7 @@ public class ClassContext {
thisIdx++;
}
final boolean hasReceiver = descriptor.getReceiver().exists();
final boolean hasReceiver = descriptor.getReceiverParameter().exists();
if (hasReceiver) {
thisIdx++;
}
@@ -104,7 +104,7 @@ public class ClassContext {
}
private ReceiverDescriptor receiver() {
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiver() : ReceiverDescriptor.NO_RECEIVER;
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiverParameter() : ReceiverDescriptor.NO_RECEIVER;
}
private boolean hasReceiver() {
@@ -42,7 +42,7 @@ public class ClosureCodegen {
}
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
boolean isExtensionFunction = fd.getReceiver().exists();
boolean isExtensionFunction = fd.getReceiverParameter().exists();
int paramCount = fd.getValueParameters().size();
if (isExtensionFunction) {
paramCount++;
@@ -151,7 +151,7 @@ public class ClosureCodegen {
iv.load(0, Type.getObjectType(className));
final ReceiverDescriptor receiver = funDescriptor.getReceiver();
final ReceiverDescriptor receiver = funDescriptor.getReceiverParameter();
int count = 1;
if (receiver.exists()) {
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
@@ -229,7 +229,7 @@ public class ClosureCodegen {
public static String getInternalClassName(FunctionDescriptor descriptor) {
final int paramCount = descriptor.getValueParameters().size();
if (descriptor.getReceiver().exists()) {
if (descriptor.getReceiverParameter().exists()) {
return "jet/ExtensionFunction" + paramCount;
}
else {
@@ -250,7 +250,7 @@ public class ClosureCodegen {
Method descriptor = erasedInvokeSignature(fd);
String owner = getInternalClassName(fd);
final CallableMethod result = new CallableMethod(owner, descriptor, Opcodes.INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
if (fd.getReceiver().exists()) {
if (fd.getReceiverParameter().exists()) {
result.setNeedsReceiver(null);
}
result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd)));
@@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import jet.Function1;
import jet.JetObject;
import jet.typeinfo.TypeInfo;
import jet.typeinfo.TypeInfoProjection;
@@ -546,7 +545,7 @@ public class JetTypeMapper {
}
public Method mapSignature(String name, FunctionDescriptor f) {
final ReceiverDescriptor receiver = f.getReceiver();
final ReceiverDescriptor receiver = f.getReceiverParameter();
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
if (receiver.exists()) {
@@ -1,7 +1,6 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
@@ -14,7 +13,7 @@ import java.util.Set;
*/
public interface CallableDescriptor extends DeclarationDescriptor {
@NotNull
ReceiverDescriptor getReceiver();
ReceiverDescriptor getReceiverParameter();
@NotNull
List<TypeParameterDescriptor> getTypeParameters();
@@ -71,7 +71,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
@NotNull
@Override
public ReceiverDescriptor getReceiver() {
public ReceiverDescriptor getReceiverParameter() {
return receiver;
}
@@ -133,7 +133,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
JetType substitutedReceiverType = null;
if (receiver.exists()) {
substitutedReceiverType = substitutor.substitute(getReceiver().getType(), Variance.IN_VARIANCE);
substitutedReceiverType = substitutor.substitute(getReceiverParameter().getType(), Variance.IN_VARIANCE);
if (substitutedReceiverType == null) {
return null;
}
@@ -181,7 +181,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
public FunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) {
FunctionDescriptorImpl copy = new FunctionDescriptorImpl(newOwner, Lists.newArrayList(getAnnotations()), getName());
copy.initialize(
getReceiver().exists() ? getReceiver().getType() : null,
getReceiverParameter().exists() ? getReceiverParameter().getType() : null,
DescriptorUtils.copyTypeParameters(copy, typeParameters),
DescriptorUtils.copyValueParameters(copy, unsubstitutedValueParameters),
unsubstitutedReturnType,
@@ -95,7 +95,7 @@ public class FunctionDescriptorUtil {
@NotNull
public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function inner scope");
ReceiverDescriptor receiver = descriptor.getReceiver();
ReceiverDescriptor receiver = descriptor.getReceiverParameter();
if (receiver.exists()) {
parameterScope.setImplicitReceiver(receiver);
}
@@ -95,7 +95,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
}
@NotNull
public ReceiverDescriptor getReceiver() {
public ReceiverDescriptor getReceiverParameter() {
return receiver;
}
@@ -35,8 +35,8 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
@NotNull
@Override
public ReceiverDescriptor getReceiver() {
return getCorrespondingProperty().getReceiver();
public ReceiverDescriptor getReceiverParameter() {
return getCorrespondingProperty().getReceiverParameter();
}
@NotNull
@@ -44,8 +44,8 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
@NotNull
@Override
public ReceiverDescriptor getReceiver() {
return getCorrespondingProperty().getReceiver();
public ReceiverDescriptor getReceiverParameter() {
return getCorrespondingProperty().getReceiverParameter();
}
@NotNull
@@ -74,7 +74,7 @@ public abstract class VariableDescriptorImpl extends DeclarationDescriptorImpl i
@NotNull
@Override
public ReceiverDescriptor getReceiver() {
public ReceiverDescriptor getReceiverParameter() {
return ReceiverDescriptor.NO_RECEIVER;
}
@@ -459,7 +459,7 @@ public class BodyResolver {
for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParameters()) {
result.addTypeParameterDescriptor(typeParameterDescriptor);
}
ReceiverDescriptor receiver = propertyDescriptor.getReceiver();
ReceiverDescriptor receiver = propertyDescriptor.getReceiverParameter();
if (receiver.exists()) {
result.setImplicitReceiver(receiver);
}
@@ -4,11 +4,14 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
/**
* @author abreslav
*/
@@ -22,7 +25,7 @@ public class DescriptorUtils {
@Override
public Boolean visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) {
return descriptor.getReceiver().exists();
return descriptor.getReceiverParameter().exists();
}
@Override
@@ -32,7 +35,7 @@ public class DescriptorUtils {
@Override
public Boolean visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) {
return descriptor.getReceiver().exists();
return descriptor.getReceiverParameter().exists();
}
}, null);
}
@@ -111,4 +114,19 @@ public class DescriptorUtils {
if (makeNonAbstract && modality == Modality.ABSTRACT) return Modality.OPEN;
return modality;
}
@NotNull
public static ReceiverDescriptor getExpectedThisObject(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof ConstructorDescriptor) {
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) descriptor;
ClassDescriptor classDescriptor = constructorDescriptor.getContainingDeclaration();
return getExpectedThisObject(classDescriptor);
}
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
return classDescriptor.getImplicitReceiver();
}
return NO_RECEIVER;
}
}
@@ -15,6 +15,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.inference.ConstraintSystem;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
@@ -22,6 +23,7 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCall.MAP_TO_CANDIDATE;
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCall.MAP_TO_RESULT;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
/**
@@ -142,7 +144,7 @@ public class CallResolver {
trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(trace, scope, call);
}
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(ResolvedCall.convertCollection(constructors), call, DataFlowInfo.getEmpty()));
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(TaskPrioritizer.convertWithImpliedThis(scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors), call, DataFlowInfo.getEmpty()));
}
else {
// trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class");
@@ -173,7 +175,7 @@ public class CallResolver {
}
private FunctionDescriptor checkArgumentTypesAndFail(BindingTrace trace, JetScope scope, Call call) {
checkTypesWithNoCallee(trace, scope, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments());
checkTypesWithNoCallee(trace, scope, call);
return null;
}
@@ -235,6 +237,17 @@ public class CallResolver {
trace.report(MISSING_RECEIVER.on(reference, expectedReceiver.getType()));
}
@Override
public void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiverParameter, @NotNull ReceiverDescriptor receiverArgument) {
if (receiverArgument instanceof ExpressionReceiver) {
ExpressionReceiver expressionReceiver = (ExpressionReceiver) receiverArgument;
trace.report(TYPE_MISMATCH.on(expressionReceiver.getExpression(), receiverParameter.getType(), receiverArgument.getType()));
}
else {
trace.report(TYPE_MISMATCH.on(reference, receiverParameter.getType(), receiverArgument.getType()));
}
}
@Override
public void noReceiverAllowed(@NotNull BindingTrace trace) {
trace.report(NO_RECEIVER_ADMITTED.on(reference));
@@ -273,6 +286,23 @@ public class CallResolver {
trace.report(TYPE_INFERENCE_FAILED.on(callNode));
}
@Override
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
ASTNode callOperationNode = call.getCallOperationNode();
if (callOperationNode != null) {
trace.report(UNSAFE_CALL.on(callOperationNode, type));
}
else {
trace.report(UNSAFE_CALL.on(reference, type));
}
}
@Override
public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
ASTNode callOperationNode = call.getCallOperationNode();
assert callOperationNode != null;
trace.report(UNNECESSARY_SAFE_CALL.on(reference, callOperationNode, type));
}
};
for (ResolutionTask<D> task : prioritizedTasks) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
@@ -294,7 +324,7 @@ public class CallResolver {
}
else {
trace.report(UNRESOLVED_REFERENCE.on(reference));
checkTypesWithNoCallee(trace, scope, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments());
checkTypesWithNoCallee(trace, scope, call);
}
return null;
}
@@ -315,21 +345,19 @@ public class CallResolver {
if (ErrorUtils.isError(candidate)) {
successfulCandidates.add(candidateCall.setResultingDescriptor(candidate));
checkTypesWithNoCallee(temporaryTrace, scope, task.getTypeArguments(), task.getValueArguments(), task.getFunctionLiteralArguments());
checkTypesWithNoCallee(temporaryTrace, scope, task.getCall());
continue;
}
// Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters = Maps.newHashMap();
boolean error = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(task, tracing, candidateCall);
if (error) {
boolean errorInArgumentMapping = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(task, tracing, candidateCall);
if (errorInArgumentMapping) {
failedCandidates.add(candidateCall);
checkTypesWithNoCallee(temporaryTrace, scope, task.getTypeArguments(), task.getValueArguments(), task.getFunctionLiteralArguments());
checkTypesWithNoCallee(temporaryTrace, scope, task.getCall());
continue;
}
if (task.getTypeArguments().isEmpty()) {
List<JetTypeProjection> jetTypeArguments = task.getCall().getTypeArguments();
if (jetTypeArguments.isEmpty()) {
if (!candidate.getTypeParameters().isEmpty()) {
// Type argument inference
@@ -356,10 +384,11 @@ public class CallResolver {
}
}
checkReceiverAbsence(candidateCall, tracing, candidate);
// checkReceiverAbsence(candidateCall, tracing, candidate);
// Error is already reported if something is missing
ReceiverDescriptor receiverParameter = candidateCall.getReceiverParameter();
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
ReceiverDescriptor receiverParameter = candidateCall.getReceiverArgument();
ReceiverDescriptor candidateReceiver = candidate.getReceiverParameter();
if (receiverParameter.exists() && candidateReceiver.exists()) {
constraintSystem.addSubtypingConstraint(receiverParameter.getType(), candidateReceiver.getType());
}
@@ -382,8 +411,7 @@ public class CallResolver {
}
}
else {
if (checkValueArgumentTypes(scope, candidateCall)
&& checkReceiver(candidateCall, tracing, candidate)) {
if (checkAllValueArguments(scope, tracing, task, candidateCall, candidate)) {
successfulCandidates.add(candidateCall.setResultingDescriptor(candidate));
}
else {
@@ -394,8 +422,6 @@ public class CallResolver {
else {
// Explicit type arguments passed
final List<JetTypeProjection> jetTypeArguments = task.getTypeArguments();
for (JetTypeProjection typeArgument : jetTypeArguments) {
if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
// temporaryTrace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
@@ -415,14 +441,14 @@ public class CallResolver {
}
checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, temporaryTrace);
Map<TypeConstructor, TypeProjection> substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
D substitutedDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext));
candidateCall.setResultingDescriptor(substitutedDescriptor);
replaceValueParametersWithSubstitutedOnes(candidateCall, substitutedDescriptor);
if (checkValueArgumentTypes(scope, candidateCall)
&& checkReceiver(candidateCall, tracing, substitutedDescriptor)) {
successfulCandidates.add(candidateCall.setResultingDescriptor(substitutedDescriptor));
if (checkAllValueArguments(scope, tracing, task, candidateCall, substitutedDescriptor)) {
successfulCandidates.add(candidateCall);
}
else {
failedCandidates.add(candidateCall);
@@ -437,13 +463,13 @@ public class CallResolver {
task.performAdvancedChecks(candidate, temporaryTrace, tracing);
recordAutoCastIfNecessary(candidateCall.getReceiverParameter(), candidateCall.getTrace());
recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
}
OverloadResolutionResults<D> results = computeResultAndReportErrors(trace, tracing, successfulCandidates, failedCandidates);
if (!results.singleDescriptor()) {
checkTypesWithNoCallee(trace, scope, task.getTypeArguments(), task.getValueArguments(), task.getFunctionLiteralArguments());
checkTypesWithNoCallee(trace, scope, task.getCall());
}
return results;
}
@@ -467,19 +493,19 @@ public class CallResolver {
}
}
private void checkTypesWithNoCallee(BindingTrace trace, JetScope scope, List<JetTypeProjection> typeArguments, List<? extends ValueArgument> valueArguments, List<JetExpression> functionLiteralArguments) {
for (ValueArgument valueArgument : valueArguments) {
private void checkTypesWithNoCallee(BindingTrace trace, JetScope scope, Call call) {
for (ValueArgument valueArgument : call.getValueArguments()) {
JetExpression argumentExpression = valueArgument.getArgumentExpression();
if (argumentExpression != null) {
typeInferrer.getServices(trace).getType(scope, argumentExpression, NO_EXPECTED_TYPE);
}
}
for (JetExpression expression : functionLiteralArguments) {
for (JetExpression expression : call.getFunctionLiteralArguments()) {
typeInferrer.getServices(trace).getType(scope, expression, NO_EXPECTED_TYPE);
}
for (JetTypeProjection typeProjection : typeArguments) {
for (JetTypeProjection typeProjection : call.getTypeArguments()) {
new TypeResolver(semanticServices, trace, true).resolveType(scope, typeProjection.getTypeReference());
}
}
@@ -515,9 +541,33 @@ public class CallResolver {
}
}
private <D extends CallableDescriptor> boolean checkValueArgumentTypes(
JetScope scope,
ResolvedCall<D> candidateCall) {
private <D extends CallableDescriptor> boolean checkAllValueArguments(JetScope scope, TracingStrategy tracing, ResolutionTask<D> task, ResolvedCall<D> candidateCall, D substitutedDescriptor) {
boolean result = checkValueArgumentTypes(scope, candidateCall);
// result &= checkReceiver(task, candidateCall, tracing, substitutedDescriptor);
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
ReceiverDescriptor receiverParameter = candidateCall.getResultingDescriptor().getReceiverParameter();
boolean safeAccess = task.getCall().getCallOperationNode() == JetTokens.SAFE_ACCESS;
if (receiverParameter.exists() && receiverArgument.exists()) {
JetType receiverArgumentType = receiverArgument.getType();
if (!safeAccess && !receiverParameter.getType().isNullable() && receiverArgumentType.isNullable()) {
tracing.unsafeCall(candidateCall.getTrace(), receiverArgumentType);
result = false;
}
else if (!semanticServices.getTypeChecker().isSubtypeOf(receiverArgument.getType(), receiverParameter.getType())) {
tracing.wrongReceiverType(candidateCall.getTrace(), receiverParameter, receiverArgument);
return false;
}
if (safeAccess && (receiverParameter.getType().isNullable() || !receiverArgumentType.isNullable())) {
tracing.unnecessarySafeCall(candidateCall.getTrace(), receiverArgumentType);
}
}
return result;
}
private <D extends CallableDescriptor> boolean checkValueArgumentTypes(JetScope scope, ResolvedCall<D> candidateCall) {
boolean result = true;
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
ValueParameterDescriptor parameterDescriptor = entry.getKey();
@@ -557,59 +607,40 @@ public class CallResolver {
}
}
}
// for (Map.Entry<ValueArgument, ValueParameterDescriptor> entry : argumentsToParameters.entrySet()) {
// ValueArgument valueArgument = entry.getKey();
// ValueParameterDescriptor valueParameterDescriptor = entry.getValue();
//
// ValueParameterDescriptor substitutedParameter = parameterMap.apply(valueParameterDescriptor);
//
// assert substitutedParameter != null;
//
// JetType parameterType = substitutedParameter.getOutType();
// JetExpression argumentExpression = valueArgument.getArgumentExpression();
// if (argumentExpression != null) {
// JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace);
// JetType type = temporaryServices.getType(scope, argumentExpression, parameterType);
// if (type == null) {
// dirty.set(true);
// }
// else if (!semanticServices.getTypeChecker().isSubtypeOf(type, parameterType)) {
// result = false;
// }
// }
// }
return result;
}
private <D extends CallableDescriptor> boolean checkReceiver(ResolvedCall<D> resolvedCall, TracingStrategy tracing, D candidate) {
if (!checkReceiverAbsence(resolvedCall, tracing, candidate)) return false;
ReceiverDescriptor receiver = resolvedCall.getReceiverParameter();
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
if (receiver.exists()
&& candidateReceiver.exists()
&& !semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), candidateReceiver.getType())) {
tracing.missingReceiver(resolvedCall.getTrace(), candidateReceiver);
return false;
}
return true;
}
private <D extends CallableDescriptor> boolean checkReceiverAbsence(ResolvedCall<D> resolvedCall, TracingStrategy tracing, D candidate) {
ReceiverDescriptor receiver = resolvedCall.getReceiverParameter();
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
if (receiver.exists()) {
if (!candidateReceiver.exists()) {
tracing.noReceiverAllowed(resolvedCall.getTrace());
return false;
}
}
else if (candidateReceiver.exists()) {
tracing.missingReceiver(resolvedCall.getTrace(), candidateReceiver);
return false;
}
return true;
}
// private <D extends CallableDescriptor> boolean checkReceiver(ResolutionTask<D> task, ResolvedCall<D> resolvedCall, TracingStrategy tracing, D candidate) {
// if (!checkReceiverAbsence(resolvedCall, tracing, candidate)) return false;
// ReceiverDescriptor actualReceiver = resolvedCall.getReceiverArgument();
// ReceiverDescriptor expectedReceiver = candidate.getReceiverParameter();
//
// if (actualReceiver.exists()
// && expectedReceiver.exists()) {
// if (!semanticServices.getTypeChecker().isSubtypeOf(actualReceiver.getType(), expectedReceiver.getType())) {
// tracing.missingReceiver(resolvedCall.getTrace(), expectedReceiver);
// return false;
// }
// }
// return true;
// }
//
// private <D extends CallableDescriptor> boolean checkReceiverAbsence(ResolvedCall<D> resolvedCall, TracingStrategy tracing, D candidate) {
// ReceiverDescriptor receiver = resolvedCall.getReceiverArgument();
// ReceiverDescriptor candidateReceiver = candidate.getReceiverParameter();
// if (receiver.exists()) {
// if (!candidateReceiver.exists()) {
// tracing.noReceiverAllowed(resolvedCall.getTrace());
// return false;
// }
// }
// else if (candidateReceiver.exists()) {
// tracing.missingReceiver(resolvedCall.getTrace(), candidateReceiver);
// return false;
// }
// return true;
// }
//
@NotNull
private <D extends CallableDescriptor> OverloadResolutionResults<D> computeResultAndReportErrors(
BindingTrace trace,
@@ -747,7 +778,7 @@ public class CallResolver {
boolean found = false;
for (ResolvedCall<FunctionDescriptor> resolvedCall : candidates) {
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
if (functionDescriptor.getReceiver().exists()) continue;
if (functionDescriptor.getReceiverParameter().exists()) continue;
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
if (!checkValueParameters(functionDescriptor, parameterTypes)) continue;
result.add(resolvedCall);
@@ -760,7 +791,7 @@ public class CallResolver {
boolean found = false;
for (ResolvedCall<FunctionDescriptor> resolvedCall : candidates) {
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
ReceiverDescriptor functionReceiver = functionDescriptor.getReceiver();
ReceiverDescriptor functionReceiver = functionDescriptor.getReceiverParameter();
if (!functionReceiver.exists()) continue;
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
if (!semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), functionReceiver.getType())) continue;
@@ -72,9 +72,9 @@ public class OverloadingConflictResolver {
if (OverridingUtil.overrides(f, g)) return true;
if (OverridingUtil.overrides(g, f)) return false;
ReceiverDescriptor receiverOfF = f.getReceiver();
ReceiverDescriptor receiverOfG = g.getReceiver();
if (f.getReceiver().exists() && g.getReceiver().exists()) {
ReceiverDescriptor receiverOfF = f.getReceiverParameter();
ReceiverDescriptor receiverOfG = g.getReceiverParameter();
if (f.getReceiverParameter().exists() && g.getReceiverParameter().exists()) {
if (!typeMoreSpecific(receiverOfF.getType(), receiverOfG.getType())) return false;
}
@@ -3,45 +3,29 @@ package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetTypeProjection;
import org.jetbrains.jet.lang.psi.ValueArgument;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.types.DataFlowInfo;
import java.util.Collection;
import java.util.List;
/**
* @author abreslav
*/
/*package*/ class ResolutionTask<D extends CallableDescriptor> {
private final Call call;
private final Collection<ResolvedCall<D>> candidates;
private final List<JetTypeProjection> typeArguments;
private final List<? extends ValueArgument> valueArguments;
private final List<JetExpression> functionLiteralArguments;
private final DataFlowInfo dataFlowInfo;
private DescriptorCheckStrategy checkingStrategy;
public ResolutionTask(
@NotNull Collection<ResolvedCall<D>> candidates,
@NotNull List<JetTypeProjection> typeArguments,
@NotNull List<? extends ValueArgument> valueArguments,
@NotNull List<JetExpression> functionLiteralArguments,
@NotNull DataFlowInfo dataFlowInfo) {
this.candidates = candidates;
this.typeArguments = typeArguments;
this.valueArguments = valueArguments;
this.functionLiteralArguments = functionLiteralArguments;
this.dataFlowInfo = dataFlowInfo;
}
public ResolutionTask(
@NotNull Collection<ResolvedCall<D>> candidates,
@NotNull Call call,
@NotNull DataFlowInfo dataFlowInfo
) {
this(candidates, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments(), dataFlowInfo);
this.candidates = candidates;
this.call = call;
this.dataFlowInfo = dataFlowInfo;
}
@NotNull
@@ -55,20 +39,10 @@ import java.util.List;
}
@NotNull
public List<JetTypeProjection> getTypeArguments() {
return typeArguments;
public Call getCall() {
return call;
}
@NotNull
public List<? extends ValueArgument> getValueArguments() {
return valueArguments;
}
@NotNull
public List<JetExpression> getFunctionLiteralArguments() {
return functionLiteralArguments;
}
public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
checkingStrategy = strategy;
}
@@ -4,9 +4,8 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
@@ -53,7 +52,7 @@ public class ResolvedCall<D extends CallableDescriptor> {
private final D candidateDescriptor;
private D resultingDescriptor; // Probably substituted
private ReceiverDescriptor thisObject = NO_RECEIVER; // receiver object of a method
private ReceiverDescriptor receiverParameter = NO_RECEIVER; // receiver of an extension function
private ReceiverDescriptor receiverArgument = NO_RECEIVER; // receiver of an extension function
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap();
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newHashMap();
@@ -104,12 +103,12 @@ public class ResolvedCall<D extends CallableDescriptor> {
}
@NotNull
public ReceiverDescriptor getReceiverParameter() {
return receiverParameter;
public ReceiverDescriptor getReceiverArgument() {
return receiverArgument;
}
public void setReceiverParameter(@NotNull ReceiverDescriptor receiverParameter) {
this.receiverParameter = receiverParameter;
public void setReceiverArgument(@NotNull ReceiverDescriptor receiverParameter) {
this.receiverArgument = receiverParameter;
}
@NotNull
@@ -133,4 +132,9 @@ public class ResolvedCall<D extends CallableDescriptor> {
public boolean isDirty() {
return someArgumentHasNoType;
}
@NotNull
public ReceiverDescriptor getExpectedThisObject() {
return DescriptorUtils.getExpectedThisObject(getResultingDescriptor());
}
}
@@ -5,10 +5,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.DataFlowInfo;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeChecker;
import org.jetbrains.jet.lang.types.NamespaceType;
import java.util.Collection;
import java.util.Collections;
@@ -65,16 +68,14 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
return false;
}
// public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull String name) {
// List<ResolutionTask<D>> result = Lists.newArrayList();
// doComputeTasks(scope, receiver, call, name, result);
// return result;
// }
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull Call call, @NotNull String name, @NotNull BindingContext bindingContext, @NotNull DataFlowInfo dataFlowInfo) {
List<ResolutionTask<D>> result = Lists.newArrayList();
ReceiverDescriptor explicitReceiver = call.getExplicitReceiver();
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
scope = explicitReceiver.getType().getMemberScope();
explicitReceiver = NO_RECEIVER;
}
doComputeTasks(scope, explicitReceiver, call, name, result, NO_AUTO_CASTS);
ReceiverDescriptor receiverToCast = explicitReceiver.exists() ? explicitReceiver : scope.getImplicitReceiver();
@@ -121,15 +122,15 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
}
};
private void doComputeTasks(JetScope scope, ReceiverDescriptor explicitReceiver, Call call, String name, List<ResolutionTask<D>> result, @NotNull AutoCastService autoCastService) {
private void doComputeTasks(JetScope scope, ReceiverDescriptor receiver, Call call, String name, List<ResolutionTask<D>> result, @NotNull AutoCastService autoCastService) {
DataFlowInfo dataFlowInfo = autoCastService.getDataFlowInfo();
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(implicitReceivers);
// AutoCastUtils.getAutoCastVariants(bindingContext, dataFlowInfo, receiverToCast)
if (explicitReceiver.exists()) {
List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(explicitReceiver);
if (receiver.exists()) {
List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver);
Collection<ResolvedCall<D>> extensionFunctions = convertWithImpliedThis(variantsForExplicitReceiver, getExtensionsByName(scope, name));
Collection<ResolvedCall<D>> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, getExtensionsByName(scope, name));
List<ResolvedCall<D>> nonlocals = Lists.newArrayList();
List<ResolvedCall<D>> locals = Lists.newArrayList();
//noinspection unchecked,RedundantTypeArguments
@@ -153,7 +154,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
addTask(result, call, nonlocals, dataFlowInfo);
}
else {
Collection<ResolvedCall<D>> functions = convertWithImpliedThis(Collections.singletonList(explicitReceiver), getNonExtensionsByName(scope, name));
Collection<ResolvedCall<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), getNonExtensionsByName(scope, name));
List<ResolvedCall<D>> nonlocals = Lists.newArrayList();
List<ResolvedCall<D>> locals = Lists.newArrayList();
@@ -183,7 +184,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
for (D extension : descriptors) {
ResolvedCall<D> resolvedCall = ResolvedCall.create(extension);
resolvedCall.setThisObject(thisObject);
resolvedCall.setReceiverParameter(receiverParameter);
resolvedCall.setReceiverArgument(receiverParameter);
result.add(resolvedCall);
}
}
@@ -191,33 +192,36 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
// return result;
}
private Collection<ResolvedCall<D>> convertWithImpliedThis(Iterable<ReceiverDescriptor> receiverParameters, Collection<D> descriptors) {
public static <D extends CallableDescriptor> Collection<ResolvedCall<D>> convertWithImpliedThis(JetScope scope, Iterable<ReceiverDescriptor> receiverParameters, Collection<D> descriptors) {
Collection<ResolvedCall<D>> result = Lists.newArrayList();
for (ReceiverDescriptor receiverParameter : receiverParameters) {
for (D extension : descriptors) {
ResolvedCall<D> resolvedCall = ResolvedCall.create(extension);
resolvedCall.setReceiverParameter(receiverParameter);
setImpliedThis(resolvedCall);
result.add(resolvedCall);
resolvedCall.setReceiverArgument(receiverParameter);
if (setImpliedThis(scope, resolvedCall)) {
result.add(resolvedCall);
}
}
}
return result;
}
private void setImpliedThis(ResolvedCall<D> resolvedCall) {
ReceiverDescriptor thisObject;
DeclarationDescriptor containingDeclaration = resolvedCall.getCandidateDescriptor().getContainingDeclaration();
if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
thisObject = classDescriptor.getImplicitReceiver();
private static <D extends CallableDescriptor> boolean setImpliedThis(@NotNull JetScope scope, ResolvedCall<D> resolvedCall) {
ReceiverDescriptor expectedThisObject = DescriptorUtils.getExpectedThisObject(resolvedCall.getCandidateDescriptor());
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);
return true;
}
}
else {
thisObject = NO_RECEIVER;
}
resolvedCall.setThisObject(thisObject);
return false;
}
private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull Call call, @NotNull Collection<ResolvedCall<D>> candidates, @NotNull DataFlowInfo dataFlowInfo) {
private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull Call call, @NotNull Collection<ResolvedCall<D>> candidates, @NotNull DataFlowInfo dataFlowInfo) {
if (candidates.isEmpty()) return;
result.add(new ResolutionTask<D>(candidates, call, dataFlowInfo));
}
@@ -27,7 +27,7 @@ public class TaskPrioritizers {
Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctions(name));
for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor functionDescriptor = iterator.next();
if (functionDescriptor.getReceiver().exists()) {
if (functionDescriptor.getReceiverParameter().exists()) {
iterator.remove();
}
}
@@ -53,7 +53,7 @@ public class TaskPrioritizers {
Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctions(name));
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor descriptor = iterator.next();
if (!descriptor.getReceiver().exists()) {
if (!descriptor.getReceiverParameter().exists()) {
iterator.remove();
}
}
@@ -71,11 +71,11 @@ public class TaskPrioritizers {
private void addVariableAsFunction(JetScope scope, String name, Set<FunctionDescriptor> functions, boolean receiverNeeded) {
VariableDescriptor variable = scope.getVariable(name);
if (variable != null && !variable.getReceiver().exists()) {
if (variable != null && !variable.getReceiverParameter().exists()) {
JetType outType = variable.getOutType();
if (outType != null && JetStandardClasses.isFunctionType(outType)) {
VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable);
if ((functionDescriptor.getReceiver().exists()) == receiverNeeded) {
if ((functionDescriptor.getReceiverParameter().exists()) == receiverNeeded) {
functions.add(functionDescriptor);
}
}
@@ -89,7 +89,7 @@ public class TaskPrioritizers {
@Override
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
VariableDescriptor variable = scope.getVariable(name);
if (variable != null && !variable.getReceiver().exists()) {
if (variable != null && !variable.getReceiverParameter().exists()) {
return Collections.singleton(variable);
}
return Collections.emptyList();
@@ -109,7 +109,7 @@ public class TaskPrioritizers {
@Override
protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
VariableDescriptor variable = scope.getVariable(name);
if (variable != null && variable.getReceiver().exists()) {
if (variable != null && variable.getReceiverParameter().exists()) {
return Collections.singleton(variable);
}
return Collections.emptyList();
@@ -5,6 +5,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection;
import java.util.Set;
@@ -26,6 +27,9 @@ import java.util.Set;
@Override
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {}
@Override
public void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiverParameter, @NotNull ReceiverDescriptor receiverArgument) {}
@Override
public void noReceiverAllowed(@NotNull BindingTrace trace) {}
@@ -46,6 +50,12 @@ import java.util.Set;
@Override
public void typeInferenceFailed(@NotNull BindingTrace trace) {}
@Override
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {}
@Override
public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {}
};
<D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall);
@@ -56,6 +66,8 @@ import java.util.Set;
void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver);
void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiverParameter, @NotNull ReceiverDescriptor receiverArgument);
void noReceiverAllowed(@NotNull BindingTrace trace);
void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter);
@@ -69,4 +81,8 @@ import java.util.Set;
void instantiationOfAbstractClass(@NotNull BindingTrace trace);
void typeInferenceFailed(@NotNull BindingTrace trace);
void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
}
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.CallMaker;
import java.util.List;
@@ -38,7 +39,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
parameterByName.put(valueParameter.getName(), valueParameter);
}
List<? extends ValueArgument> valueArguments = task.getValueArguments();
List<? extends ValueArgument> valueArguments = task.getCall().getValueArguments();
boolean error = false;
boolean someNamed = false;
@@ -103,7 +104,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
}
}
List<JetExpression> functionLiteralArguments = task.getFunctionLiteralArguments();
List<JetExpression> functionLiteralArguments = task.getCall().getFunctionLiteralArguments();
if (!functionLiteralArguments.isEmpty()) {
JetExpression possiblyLabeledFunctionLiteral = functionLiteralArguments.get(0);
@@ -164,6 +165,20 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
}
}
}
ReceiverDescriptor receiverParameter = candidate.getReceiverParameter();
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
if (receiverParameter.exists() &&!receiverArgument.exists()) {
tracing.missingReceiver(temporaryTrace, receiverParameter);
error = true;
}
if (!receiverParameter.exists() && receiverArgument.exists()) {
tracing.noReceiverAllowed(temporaryTrace);
error = true;
}
assert candidateCall.getThisObject().exists() == candidateCall.getExpectedThisObject().exists() : "Shouldn't happen because of TaskPrioritizer: " + candidateCall.getCandidateDescriptor();
return error;
}
@@ -127,6 +127,10 @@ public class CallMaker {
return null;
}
@Override
public String toString() {
return getCallNode().getText();
}
}
public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression, @NotNull List<JetExpression> argumentExpressions) {
@@ -222,7 +222,7 @@ public class JetTypeInferrer {
// if (receiverType != null && callee != null) {
// boolean namespaceType = receiverType instanceof NamespaceType;
// boolean nullableReceiver = !namespaceType && receiverType.isNullable();
// ReceiverDescriptor calleeReceiver = callee.getReceiver();
// ReceiverDescriptor calleeReceiver = callee.getReceiverParameter();
// boolean calleeForbidsNullableReceiver = !calleeReceiver.exists() || !calleeReceiver.getType().isNullable();
//
// IElementType operationSign = operationTokenNode.getElementType();
@@ -1275,7 +1275,7 @@ public class JetTypeInferrer {
}
else if (declarationDescriptor instanceof FunctionDescriptor) {
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
thisReceiver = functionDescriptor.getReceiver();
thisReceiver = functionDescriptor.getReceiverParameter();
}
else {
throw new UnsupportedOperationException(); // TODO
@@ -1289,7 +1289,7 @@ public class JetTypeInferrer {
if (psiElement instanceof JetFunctionLiteralExpression) {
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
if (declarationDescriptor instanceof FunctionDescriptor) {
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiver();
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiverParameter();
if (thisReceiver.exists()) {
context.trace.record(REFERENCE_TARGET, targetLabel, declarationDescriptor);
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
@@ -186,7 +186,7 @@ public class DescriptorRenderer implements Renderer {
renderModality(descriptor.getModality(), builder);
String typeString = renderPropertyPrefixAndComputeTypeString(
builder, descriptor.getTypeParameters(),
descriptor.getReceiver(),
descriptor.getReceiverParameter(),
descriptor.getOutType(),
descriptor.getInType());
renderName(descriptor, builder);
@@ -215,7 +215,7 @@ public class DescriptorRenderer implements Renderer {
builder.append(renderKeyword("fun")).append(" ");
renderTypeParameters(descriptor.getTypeParameters(), builder);
ReceiverDescriptor receiver = descriptor.getReceiver();
ReceiverDescriptor receiver = descriptor.getReceiverParameter();
if (receiver.exists()) {
builder.append(escape(renderType(receiver.getType()))).append(".");
}