From 24082a67d795d6a7ac5a154923c313a156ed85b2 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 30 Apr 2012 15:32:14 +0400 Subject: [PATCH] correspondence between CallableDescriptorCollector and CallTransformer (special treatment only for function invocations) --- .../jet/lang/resolve/calls/CallResolver.java | 146 +++++++++--------- .../resolve/calls/ResolutionDebugInfo.java | 2 +- .../resolve/calls/ResolutionTaskHolder.java | 8 +- 3 files changed, 80 insertions(+), 76 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 219f06d9156..1e699b0ca63 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -102,16 +102,16 @@ public class CallResolver { if (referencedName == null) { return OverloadResolutionResultsImpl.nameNotFound(); } - List> memberPrioritizers = Lists.newArrayList(); + List> callableDescriptorCollectors = Lists.newArrayList(); if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) { referencedName = referencedName.substring(1); - memberPrioritizers.add(MemberPrioritizers.PROPERTY_TASK_PRIORITIZER); + callableDescriptorCollectors.add(CallableDescriptorCollectors.PROPERTIES); } else { - memberPrioritizers.add(MemberPrioritizers.VARIABLE_TASK_PRIORITIZER); + callableDescriptorCollectors.add(CallableDescriptorCollectors.VARIABLES); } - List> prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, referencedName, nameExpression, memberPrioritizers); - return doResolveCall(context, prioritizedTasks, CallTransformationStrategy.PROPERTY_CALL_TRANSFORMATION_STRATEGY, nameExpression); + List> prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, referencedName, nameExpression, callableDescriptorCollectors); + return doResolveCall(context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, nameExpression); } @NotNull @@ -119,9 +119,8 @@ public class CallResolver { @NotNull BasicResolutionContext context, @NotNull final JetReferenceExpression functionReference, @NotNull String name) { - List> tasks = TaskPrioritizer.computePrioritizedTasks( - context, name, functionReference, Collections.singletonList(MemberPrioritizers.FUNCTION_TASK_PRIORITIZER)); - return doResolveCall(context, tasks, CallTransformationStrategy.FUNCTION_CALL_TRANSFORMATION_STRATEGY, functionReference); + List> tasks = TaskPrioritizer.computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES); + return doResolveCall(context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference); } @NotNull @@ -131,7 +130,7 @@ public class CallResolver { @NotNull public OverloadResolutionResults resolveFunctionCall(@NotNull BasicResolutionContext context) { - List> prioritizedTasks; + List> prioritizedTasks; JetExpression calleeExpression = context.call.getCalleeExpression(); final JetReferenceExpression functionReference; @@ -142,7 +141,7 @@ public class CallResolver { String name = expression.getReferencedName(); if (name == null) return checkArgumentTypesAndFail(context); - prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, name, functionReference, Collections.singletonList(MemberPrioritizers.FUNCTION_TASK_PRIORITIZER)); + prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES); ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() { @Override public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) { @@ -184,8 +183,8 @@ public class CallResolver { context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); return checkArgumentTypesAndFail(context); } - Collection> candidates = TaskPrioritizer.convertWithImpliedThis(context.scope, Collections.singletonList(NO_RECEIVER), constructors); - prioritizedTasks.add(new ResolutionTask(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY + Collection> candidates = TaskPrioritizer.convertWithImpliedThis(context.scope, Collections.singletonList(NO_RECEIVER), constructors); + prioritizedTasks.add(new ResolutionTask(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY } else { context.trace.report(NOT_A_CLASS.on(calleeExpression)); @@ -206,8 +205,8 @@ public class CallResolver { context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); return checkArgumentTypesAndFail(context); } - List> candidates = ResolutionCandidate.convertCollection(constructors); - prioritizedTasks = Collections.singletonList(new ResolutionTask(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY + List> candidates = ResolutionCandidate.convertCollection(constructors); + prioritizedTasks = Collections.singletonList(new ResolutionTask(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY } else if (calleeExpression != null) { // Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2) @@ -223,7 +222,7 @@ public class CallResolver { FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]"); FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER); - ResolutionCandidate resolutionCandidate = ResolutionCandidate.create(functionDescriptor); + ResolutionCandidate resolutionCandidate = ResolutionCandidate.create(functionDescriptor); resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver()); // strictly speaking, this is a hack: @@ -231,7 +230,7 @@ public class CallResolver { // so we wrap what we have into a fake reference and pass it on (unwrap on the other end) functionReference = new JetFakeReference(calleeExpression); - prioritizedTasks = Collections.singletonList(new ResolutionTask(Collections.singleton(resolutionCandidate), functionReference, context)); + prioritizedTasks = Collections.singletonList(new ResolutionTask(Collections.singleton(resolutionCandidate), functionReference, context)); } else { // checkTypesWithNoCallee(trace, scope, call); @@ -239,7 +238,7 @@ public class CallResolver { } } - return doResolveCall(context, prioritizedTasks, CallTransformationStrategy.FUNCTION_CALL_TRANSFORMATION_STRATEGY, functionReference); + return doResolveCall(context, prioritizedTasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference); } private OverloadResolutionResults checkArgumentTypesAndFail(BasicResolutionContext context) { @@ -248,10 +247,10 @@ public class CallResolver { } @NotNull - private OverloadResolutionResults doResolveCall( + private OverloadResolutionResults doResolveCall( @NotNull final BasicResolutionContext context, - @NotNull final List> prioritizedTasks, // high to low priority - @NotNull CallTransformationStrategy callTransformationStrategy, + @NotNull final List> prioritizedTasks, // high to low priority + @NotNull CallTransformer callTransformer, @NotNull final JetReferenceExpression reference) { ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create(); @@ -265,10 +264,11 @@ public class CallResolver { debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks); TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null; - OverloadResolutionResultsImpl resultsForFirstNonemptyCandidateSet = null; - for (ResolutionTask task : prioritizedTasks) { + OverloadResolutionResultsImpl resultsForFirstNonemptyCandidateSet = null; + for (ResolutionTask task : prioritizedTasks) { TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace); - OverloadResolutionResultsImpl results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace), callTransformationStrategy); + OverloadResolutionResultsImpl results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace), + callTransformer); if (results.isSuccess() || results.isAmbiguity()) { temporaryTrace.commit(); @@ -294,15 +294,15 @@ public class CallResolver { context.trace.report(UNRESOLVED_REFERENCE.on(reference)); checkTypesWithNoCallee(context); } - return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.nameNotFound(); + return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.nameNotFound(); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @NotNull - private OverloadResolutionResultsImpl performResolutionGuardedForExtraFunctionLiteralArguments(@NotNull ResolutionTask task, - @NotNull CallTransformationStrategy callTransformationStrategy) { - OverloadResolutionResultsImpl results = performResolution(task, callTransformationStrategy); + private OverloadResolutionResultsImpl performResolutionGuardedForExtraFunctionLiteralArguments(@NotNull ResolutionTask task, + @NotNull CallTransformer callTransformer) { + OverloadResolutionResultsImpl results = performResolution(task, callTransformer); // If resolution fails, we should check for some of the following situations: // class A { @@ -329,14 +329,14 @@ public class CallResolver { for (ResolutionCandidate candidate : task.getCandidates()) { newCandidates.add(ResolutionCandidate.create(candidate.getDescriptor())); } - ResolutionTask newContext = new ResolutionTask(newCandidates, task.reference, TemporaryBindingTrace.create(task.trace), task.scope, new DelegatingCall(task.call) { + ResolutionTask newContext = new ResolutionTask(newCandidates, task.reference, TemporaryBindingTrace.create(task.trace), task.scope, new DelegatingCall(task.call) { @NotNull @Override public List getFunctionLiteralArguments() { return Collections.emptyList(); } }, task.expectedType, task.dataFlowInfo); - OverloadResolutionResultsImpl resultsWithFunctionLiteralsStripped = performResolution(newContext, callTransformationStrategy); + OverloadResolutionResultsImpl resultsWithFunctionLiteralsStripped = performResolution(newContext, callTransformer); if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) { task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments()); } @@ -346,23 +346,28 @@ public class CallResolver { } @NotNull - private OverloadResolutionResultsImpl performResolution(@NotNull ResolutionTask task, - @NotNull CallTransformationStrategy callTransformationStrategy) { + private OverloadResolutionResultsImpl performResolution(@NotNull ResolutionTask task, + @NotNull CallTransformer callTransformer) { for (ResolutionCandidate resolutionCandidate : task.getCandidates()) { TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(task.trace); - CallResolutionContext context = callTransformationStrategy.createCallContext(resolutionCandidate, task, temporaryTrace, task.tracing); - performResolutionForCandidateCall(context, task, temporaryTrace); + Collection> contexts = callTransformer.createCallContexts(resolutionCandidate, task, temporaryTrace); + Collection> calls = Lists.newArrayList(); + for (CallResolutionContext context : contexts) { - Collection> calls = callTransformationStrategy.transformResultCall(context, this, task); - for (ResolvedCallImpl call : calls) { - task.getResolvedCallMap().put(resolutionCandidate, call); + performResolutionForCandidateCall(context, task); + calls.addAll(callTransformer.transformCall(context, this, task)); + } + for (ResolvedCallWithTrace call : calls) { + + task.tracing.bindResolvedCall(call.getTrace(), call); + task.getResolvedCalls().add(call); } } - Set> successfulCandidates = Sets.newLinkedHashSet(); - Set> failedCandidates = Sets.newLinkedHashSet(); - for (ResolvedCallImpl candidateCall : task.getResolvedCallMap().values()) { + Set> successfulCandidates = Sets.newLinkedHashSet(); + Set> failedCandidates = Sets.newLinkedHashSet(); + for (ResolvedCallWithTrace candidateCall : task.getResolvedCalls()) { ResolutionStatus status = candidateCall.getStatus(); if (status.isSuccess()) { successfulCandidates.add(candidateCall); @@ -373,23 +378,19 @@ public class CallResolver { } } - OverloadResolutionResultsImpl results = computeResultAndReportErrors(task.trace, task.tracing, successfulCandidates, failedCandidates); + OverloadResolutionResultsImpl results = computeResultAndReportErrors(task.trace, task.tracing, successfulCandidates, failedCandidates); if (!results.isSingleResult()) { checkTypesWithNoCallee(task.toBasic()); } return results; } - private void performResolutionForCandidateCall(@NotNull CallResolutionContext context, - @NotNull ResolutionTask task, - @NotNull TemporaryBindingTrace temporaryTrace) { + private void performResolutionForCandidateCall(@NotNull CallResolutionContext context, + @NotNull ResolutionTask task) { + ResolvedCallImpl candidateCall = context.candidateCall; - - candidateCall.setTrace(temporaryTrace); D candidate = candidateCall.getCandidateDescriptor(); - context.tracing.bindReference(context.trace, candidateCall); - if (ErrorUtils.isError(candidate)) { candidateCall.addStatus(SUCCESS); checkTypesWithNoCallee(context.toBasic()); @@ -477,7 +478,7 @@ public class CallResolver { recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace()); } - private ResolutionStatus inferTypeArguments(CallResolutionContext context) { + private ResolutionStatus inferTypeArguments(CallResolutionContext context) { ResolvedCallImpl candidateCall = context.candidateCall; D candidate = candidateCall.getCandidateDescriptor(); @@ -624,7 +625,7 @@ public class CallResolver { } } - private ResolutionStatus checkAllValueArguments(CallResolutionContext context) { + private ResolutionStatus checkAllValueArguments(CallResolutionContext context) { ResolutionStatus result = checkValueArgumentTypes(context); ResolvedCall candidateCall = context.candidateCall; result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument())); @@ -632,7 +633,7 @@ public class CallResolver { return result; } - private ResolutionStatus checkReceiver(CallResolutionContext context, ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument) { + private ResolutionStatus checkReceiver(CallResolutionContext context, ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument) { ResolutionStatus result = SUCCESS; if (receiverParameter.exists() && receiverArgument.exists()) { ASTNode callOperationNode = context.call.getCallOperationNode(); @@ -660,7 +661,7 @@ public class CallResolver { return result; } - private ResolutionStatus checkValueArgumentTypes(CallResolutionContext context) { + private ResolutionStatus checkValueArgumentTypes(CallResolutionContext context) { ResolutionStatus result = SUCCESS; for (Map.Entry entry : context.candidateCall.getValueArguments().entrySet()) { ValueParameterDescriptor parameterDescriptor = entry.getKey(); @@ -734,8 +735,8 @@ public class CallResolver { private OverloadResolutionResultsImpl computeResultAndReportErrors( BindingTrace trace, TracingStrategy tracing, - Set> successfulCandidates, - Set> failedCandidates) { + Set> successfulCandidates, + Set> failedCandidates) { // TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific if (successfulCandidates.size() > 0) { @@ -756,8 +757,8 @@ public class CallResolver { // and some are not OK at all. In this case we'd like to say "unsafe call" rather than "none applicable" // Used to be: weak errors. Generalized for future extensions for (EnumSet severityLevel : SEVERITY_LEVELS) { - Set> thisLevel = Sets.newLinkedHashSet(); - for (ResolvedCallImpl candidate : failedCandidates) { + Set> thisLevel = Sets.newLinkedHashSet(); + for (ResolvedCallWithTrace candidate : failedCandidates) { if (severityLevel.contains(candidate.getStatus())) { thisLevel.add(candidate); } @@ -777,7 +778,7 @@ public class CallResolver { assert false : "Should not be reachable, cause every status must belong to some level"; - Set> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE); + Set> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE); if (noOverrides.size() != 1) { tracing.noneApplicable(trace, noOverrides); tracing.recordAmbiguity(trace, noOverrides); @@ -787,7 +788,7 @@ public class CallResolver { failedCandidates = noOverrides; } - ResolvedCallImpl failed = failedCandidates.iterator().next(); + ResolvedCallWithTrace failed = failedCandidates.iterator().next(); failed.getTrace().commit(); return OverloadResolutionResultsImpl.singleFailedCandidate(failed); } @@ -797,18 +798,18 @@ public class CallResolver { } } - private static boolean allClean(Collection> results) { - for (ResolvedCallImpl result : results) { + private static boolean allClean(Collection> results) { + for (ResolvedCallWithTrace result : results) { if (result.isDirty()) return false; } return true; } - private OverloadResolutionResultsImpl chooseAndReportMaximallySpecific(Set> candidates, boolean discriminateGenerics) { + private OverloadResolutionResultsImpl chooseAndReportMaximallySpecific(Set> candidates, boolean discriminateGenerics) { if (candidates.size() != 1) { - Set> cleanCandidates = Sets.newLinkedHashSet(candidates); - for (Iterator> iterator = cleanCandidates.iterator(); iterator.hasNext(); ) { - ResolvedCallImpl candidate = iterator.next(); + Set> cleanCandidates = Sets.newLinkedHashSet(candidates); + for (Iterator> iterator = cleanCandidates.iterator(); iterator.hasNext(); ) { + ResolvedCallWithTrace candidate = iterator.next(); if (candidate.isDirty()) { iterator.remove(); } @@ -817,27 +818,31 @@ public class CallResolver { if (cleanCandidates.isEmpty()) { cleanCandidates = candidates; } - ResolvedCallImpl maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, false); + ResolvedCallWithTrace maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, false); if (maximallySpecific != null) { return OverloadResolutionResultsImpl.success(maximallySpecific); } if (discriminateGenerics) { - ResolvedCallImpl maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, true); + ResolvedCallWithTrace maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, true); if (maximallySpecificGenericsDiscriminated != null) { return OverloadResolutionResultsImpl.success(maximallySpecificGenericsDiscriminated); } } - Set> noOverrides = OverridingUtil.filterOverrides(candidates, MAP_TO_RESULT); + Set> noOverrides = OverridingUtil.filterOverrides(candidates, MAP_TO_RESULT); return OverloadResolutionResultsImpl.ambiguity(noOverrides); } else { - ResolvedCallImpl result = candidates.iterator().next(); + ResolvedCallWithTrace result = candidates.iterator().next(); TemporaryBindingTrace temporaryTrace = result.getTrace(); temporaryTrace.commit(); + + if (result instanceof VariableAsFunctionResolvedCall) { + ((VariableAsFunctionResolvedCall)result).getVariableCall().getTrace().commit(); + } return OverloadResolutionResultsImpl.success(result); } } @@ -868,13 +873,12 @@ public class CallResolver { BindingTraceContext trace = new BindingTraceContext(); TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace); - Set> calls = Sets.newLinkedHashSet(); + Set> calls = Sets.newLinkedHashSet(); for (ResolutionCandidate candidate : candidates) { - ResolvedCallImpl call = ResolvedCallImpl.create(candidate); - call.setTrace(temporaryBindingTrace); + ResolvedCallImpl call = ResolvedCallImpl.create(candidate, temporaryBindingTrace); calls.add(call); } - return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, calls, Collections.>emptySet()); + return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, calls, Collections.>emptySet()); } private List> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java index b61c04a5c65..b3c6b1d7839 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java @@ -34,7 +34,7 @@ import java.util.Map; * @author abreslav */ public class ResolutionDebugInfo { - public static final WritableSlice>> TASKS = Slices.createSimpleSlice(); + public static final WritableSlice>> TASKS = Slices.createSimpleSlice(); public static final WritableSlice> RESULT = Slices.createSimpleSlice(); public static final WritableSlice, StringBuilder> ERRORS = Slices.createSimpleSlice(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTaskHolder.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTaskHolder.java index 4e39c8ccfde..5054e683c22 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTaskHolder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTaskHolder.java @@ -31,7 +31,7 @@ import java.util.List; /** * @author svtk */ -public class ResolutionTaskHolder { +public class ResolutionTaskHolder { private final JetReferenceExpression reference; private final BasicResolutionContext basicResolutionContext; private final Predicate> visibleStrategy; @@ -40,7 +40,7 @@ public class ResolutionTaskHolder { private final Collection>> members = Sets.newLinkedHashSet(); private final Collection>> nonLocalExtensions = Sets.newLinkedHashSet(); - private List> tasks = null; + private List> tasks = null; public ResolutionTaskHolder(@NotNull JetReferenceExpression reference, @NotNull BasicResolutionContext basicResolutionContext, @@ -68,7 +68,7 @@ public class ResolutionTaskHolder { } } - public List> getTasks() { + public List> getTasks() { if (tasks == null) { tasks = Lists.newArrayList(); List>> candidateList = Lists.newArrayList(); @@ -89,7 +89,7 @@ public class ResolutionTaskHolder { for (Collection> candidates : candidateList) { Collection> filteredCandidates = Collections2.filter(candidates, visibilityStrategy); if (!filteredCandidates.isEmpty()) { - tasks.add(new ResolutionTask(filteredCandidates, reference, basicResolutionContext)); + tasks.add(new ResolutionTask(filteredCandidates, reference, basicResolutionContext)); } } }