001/* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.jetbrains.jet.lang.resolve.calls; 018 019import com.google.common.collect.ImmutableSet; 020import com.google.common.collect.Lists; 021import com.intellij.openapi.progress.ProgressIndicatorProvider; 022import com.intellij.psi.PsiElement; 023import org.jetbrains.annotations.NotNull; 024import org.jetbrains.annotations.Nullable; 025import org.jetbrains.jet.lang.descriptors.*; 026import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorImpl; 027import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorUtil; 028import org.jetbrains.jet.lang.psi.*; 029import org.jetbrains.jet.lang.resolve.*; 030import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; 031import org.jetbrains.jet.lang.resolve.calls.context.*; 032import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl; 033import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace; 034import org.jetbrains.jet.lang.resolve.calls.results.*; 035import org.jetbrains.jet.lang.resolve.calls.tasks.*; 036import org.jetbrains.jet.lang.resolve.calls.util.DelegatingCall; 037import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor; 038import org.jetbrains.jet.lang.resolve.calls.util.JetFakeReference; 039import org.jetbrains.jet.lang.resolve.name.Name; 040import org.jetbrains.jet.lang.resolve.scopes.JetScope; 041import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 042import org.jetbrains.jet.lang.types.ErrorUtils; 043import org.jetbrains.jet.lang.types.JetType; 044import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; 045import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils; 046import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 047import org.jetbrains.jet.lexer.JetTokens; 048 049import javax.inject.Inject; 050import java.util.Collection; 051import java.util.Collections; 052import java.util.List; 053 054import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER; 055import static org.jetbrains.jet.lang.diagnostics.Errors.*; 056import static org.jetbrains.jet.lang.resolve.BindingContext.NON_DEFAULT_EXPRESSION_DATA_FLOW; 057import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLUTION_SCOPE; 058import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS; 059import static org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults.Code.*; 060import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; 061import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; 062 063public class CallResolver { 064 @NotNull 065 private ExpressionTypingServices expressionTypingServices; 066 @NotNull 067 private TypeResolver typeResolver; 068 @NotNull 069 private CandidateResolver candidateResolver; 070 @NotNull 071 private ArgumentTypeResolver argumentTypeResolver; 072 @Nullable 073 private CallResolverExtension extension; 074 075 @Inject 076 public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) { 077 this.expressionTypingServices = expressionTypingServices; 078 } 079 080 @Inject 081 public void setTypeResolver(@NotNull TypeResolver typeResolver) { 082 this.typeResolver = typeResolver; 083 } 084 085 @Inject 086 public void setCandidateResolver(@NotNull CandidateResolver candidateResolver) { 087 this.candidateResolver = candidateResolver; 088 } 089 090 @Inject 091 public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) { 092 this.argumentTypeResolver = argumentTypeResolver; 093 } 094 095 @Inject 096 public void setExtension(@NotNull CallResolverExtension extension) { 097 this.extension = extension; 098 } 099 100 @NotNull 101 public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) { 102 JetExpression calleeExpression = context.call.getCalleeExpression(); 103 assert calleeExpression instanceof JetSimpleNameExpression; 104 JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression; 105 Name referencedName = nameExpression.getReferencedNameAsName(); 106 List<CallableDescriptorCollector<? extends VariableDescriptor>> callableDescriptorCollectors = Lists.newArrayList(); 107 if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) { 108 referencedName = Name.identifier(referencedName.asString().substring(1)); 109 callableDescriptorCollectors.add(CallableDescriptorCollectors.PROPERTIES); 110 } 111 else { 112 callableDescriptorCollectors.add(CallableDescriptorCollectors.VARIABLES); 113 } 114 List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks = 115 TaskPrioritizer.<VariableDescriptor, VariableDescriptor>computePrioritizedTasks(context, referencedName, nameExpression, 116 callableDescriptorCollectors); 117 return doResolveCallOrGetCachedResults(ResolutionResultsCache.PROPERTY_MEMBER_TYPE, 118 context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, nameExpression); 119 } 120 121 @NotNull 122 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName( 123 @NotNull BasicCallResolutionContext context, 124 @NotNull JetReferenceExpression functionReference, 125 @NotNull Name name) { 126 List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks = 127 TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES); 128 return doResolveCallOrGetCachedResults(ResolutionResultsCache.FUNCTION_MEMBER_TYPE, 129 context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference); 130 } 131 132 @NotNull 133 public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall( 134 @NotNull BindingTrace trace, 135 @NotNull JetScope scope, 136 @NotNull Call call, 137 @NotNull JetType expectedType, 138 @NotNull DataFlowInfo dataFlowInfo 139 ) { 140 return resolveFunctionCall(BasicCallResolutionContext.create( 141 trace, scope, call, expectedType, dataFlowInfo, ResolveMode.TOP_LEVEL_CALL, CheckValueArgumentsMode.ENABLED, 142 ExpressionPosition.FREE, ResolutionResultsCache.create())); 143 } 144 145 @NotNull 146 /*package*/ OverloadResolutionResultsImpl<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) { 147 148 ProgressIndicatorProvider.checkCanceled(); 149 150 List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> prioritizedTasks; 151 152 JetExpression calleeExpression = context.call.getCalleeExpression(); 153 JetReferenceExpression functionReference; 154 if (calleeExpression instanceof JetSimpleNameExpression) { 155 JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression; 156 functionReference = expression; 157 158 ExpressionTypingUtils.checkCapturingInClosure(expression, context.trace, context.scope); 159 160 Name name = expression.getReferencedNameAsName(); 161 162 prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES); 163 ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() { 164 @Override 165 public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) { 166 if (descriptor instanceof ConstructorDescriptor) { 167 Modality modality = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getModality(); 168 if (modality == Modality.ABSTRACT) { 169 tracing.instantiationOfAbstractClass(trace); 170 return false; 171 } 172 } 173 return true; 174 } 175 }; 176 for (ResolutionTask task : prioritizedTasks) { 177 task.setCheckingStrategy(abstractConstructorCheck); 178 } 179 } 180 else { 181 JetValueArgumentList valueArgumentList = context.call.getValueArgumentList(); 182 PsiElement reportAbsenceOn = valueArgumentList == null ? context.call.getCallElement() : valueArgumentList; 183 if (calleeExpression instanceof JetConstructorCalleeExpression) { 184 assert !context.call.getExplicitReceiver().exists(); 185 186 JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression; 187 functionReference = expression.getConstructorReferenceExpression(); 188 if (functionReference == null) { 189 return checkArgumentTypesAndFail(context); // No type there 190 } 191 JetTypeReference typeReference = expression.getTypeReference(); 192 assert typeReference != null; 193 JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true); 194 195 if (ErrorUtils.isErrorType(constructedType)) { 196 return checkArgumentTypesAndFail(context); 197 } 198 199 DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor(); 200 if (declarationDescriptor instanceof ClassDescriptor) { 201 ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; 202 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors(); 203 if (constructors.isEmpty()) { 204 context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); 205 return checkArgumentTypesAndFail(context); 206 } 207 Collection<ResolutionCandidate<CallableDescriptor>> candidates = TaskPrioritizer.<CallableDescriptor>convertWithImpliedThis(context.scope, Collections.<ReceiverValue>singletonList(NO_RECEIVER), constructors); 208 prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates( 209 context, functionReference, candidates); 210 } 211 else { 212 context.trace.report(NOT_A_CLASS.on(calleeExpression)); 213 return checkArgumentTypesAndFail(context); 214 } 215 } 216 else if (calleeExpression instanceof JetThisReferenceExpression) { 217 functionReference = (JetThisReferenceExpression) calleeExpression; 218 DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration(); 219 if (containingDeclaration instanceof ConstructorDescriptor) { 220 containingDeclaration = containingDeclaration.getContainingDeclaration(); 221 } 222 assert containingDeclaration instanceof ClassDescriptor; 223 ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; 224 225 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors(); 226 if (constructors.isEmpty()) { 227 context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); 228 return checkArgumentTypesAndFail(context); 229 } 230 List<ResolutionCandidate<CallableDescriptor>> candidates = ResolutionCandidate.<CallableDescriptor>convertCollection(constructors, JetPsiUtil.isSafeCall(context.call)); 231 prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY 232 } 233 else if (calleeExpression != null) { 234 // Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2) 235 JetType calleeType = expressionTypingServices.safeGetType(context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace); // We are actually expecting a function, but there seems to be no easy way of expressing this 236 237 if (!KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(calleeType)) { 238// checkTypesWithNoCallee(trace, scope, call); 239 if (!ErrorUtils.isErrorType(calleeType)) { 240 context.trace.report(CALLEE_NOT_A_FUNCTION.on(calleeExpression, calleeType)); 241 } 242 return checkArgumentTypesAndFail(context); 243 } 244 245 FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), Name.special("<for expression " + calleeExpression.getText() + ">")); 246 FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER_PARAMETER, Modality.FINAL, 247 Visibilities.LOCAL); 248 ResolutionCandidate<CallableDescriptor> resolutionCandidate = ResolutionCandidate.<CallableDescriptor>create(functionDescriptor, JetPsiUtil.isSafeCall(context.call)); 249 resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver()); 250 resolutionCandidate.setExplicitReceiverKind(ExplicitReceiverKind.RECEIVER_ARGUMENT); 251 252 // strictly speaking, this is a hack: 253 // we need to pass a reference, but there's no reference in the PSI, 254 // so we wrap what we have into a fake reference and pass it on (unwrap on the other end) 255 functionReference = new JetFakeReference(calleeExpression); 256 257 prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(Collections.singleton(resolutionCandidate), functionReference, context)); 258 } 259 else { 260// checkTypesWithNoCallee(trace, scope, call); 261 return checkArgumentTypesAndFail(context); 262 } 263 } 264 265 return doResolveCallOrGetCachedResults(ResolutionResultsCache.FUNCTION_MEMBER_TYPE, context, prioritizedTasks, 266 CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference); 267 } 268 269 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults( 270 @NotNull ResolutionResultsCache.MemberType<F> memberType, 271 @NotNull BasicCallResolutionContext context, 272 @NotNull List<ResolutionTask<D, F>> prioritizedTasks, 273 @NotNull CallTransformer<D, F> callTransformer, 274 @NotNull JetReferenceExpression reference 275 ) { 276 OverloadResolutionResultsImpl<F> results = null; 277 TracingStrategy tracing = prioritizedTasks.isEmpty() ? TracingStrategy.EMPTY : prioritizedTasks.iterator().next().tracing; 278 TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call); 279 CallKey callKey = CallResolverUtil.createCallKey(context); 280 if (callKey != null) { 281 OverloadResolutionResultsImpl<F> cachedResults = context.resolutionResultsCache.getResolutionResults(callKey, memberType); 282 if (cachedResults != null) { 283 DelegatingBindingTrace deltasTraceForResolve = context.resolutionResultsCache.getResolutionTrace(callKey); 284 assert deltasTraceForResolve != null; 285 deltasTraceForResolve.addAllMyDataTo(traceToResolveCall); 286 results = cachedResults; 287 } 288 } 289 if (results == null) { 290 BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall); 291 results = doResolveCall(newContext, prioritizedTasks, callTransformer, reference); 292 DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace(); 293 if (deltasTraceForTypeInference != null) { 294 deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall); 295 } 296 completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing); 297 cacheResults(memberType, context, results, traceToResolveCall, tracing); 298 } 299 traceToResolveCall.commit(); 300 301 if (prioritizedTasks.isEmpty() || context.resolveMode == ResolveMode.NESTED_CALL) { 302 //do nothing 303 } else { 304 results = completeTypeInferenceDependentOnExpectedType(context, results, tracing); 305 } 306 307 if (extension != null) { 308 extension.run(results, context); 309 } 310 311 return results; 312 } 313 314 private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals( 315 @NotNull BasicCallResolutionContext context, 316 @NotNull OverloadResolutionResultsImpl<D> results, 317 @NotNull TracingStrategy tracing 318 ) { 319 if (!results.isSingleResult()) { 320 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) { 321 argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS); 322 } 323 return; 324 } 325 CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed( 326 results.getResultingCall().getCallToCompleteTypeArgumentInference(), context, tracing); 327 candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext); 328 } 329 330 private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> completeTypeInferenceDependentOnExpectedType( 331 @NotNull BasicCallResolutionContext context, 332 @NotNull OverloadResolutionResultsImpl<D> results, 333 @NotNull TracingStrategy tracing 334 ) { 335 if (results.isSingleResult()) { 336 argumentTypeResolver.checkUnmappedArgumentTypes( 337 context, results.getResultingCall().getCallToCompleteTypeArgumentInference().getUnmappedArguments()); 338 } 339 340 if (!results.isSingleResult()) return results; 341 342 ResolvedCallImpl<D> resolvedCall = results.getResultingCall().getCallToCompleteTypeArgumentInference(); 343 344 if (!resolvedCall.hasIncompleteTypeParameters()) { 345 CallCandidateResolutionContext<D> callCandidateResolutionContext = 346 CallCandidateResolutionContext.createForCallBeingAnalyzed(resolvedCall, context, tracing); 347 candidateResolver.completeNestedCallsInference(callCandidateResolutionContext); 348 candidateResolver.checkValueArgumentTypes(callCandidateResolutionContext); 349 return results; 350 } 351 ResolvedCallImpl<D> copy = CallResolverUtil.copy(resolvedCall, context); 352 CallCandidateResolutionContext<D> callCandidateResolutionContext = 353 CallCandidateResolutionContext.createForCallBeingAnalyzed(copy, context, tracing); 354 candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext, false); 355 356 if (copy.getStatus().isSuccess()) { 357 return OverloadResolutionResultsImpl.success(copy); 358 } 359 return OverloadResolutionResultsImpl.incompleteTypeInference(copy); 360 } 361 362 private static <F extends CallableDescriptor> void cacheResults( 363 @NotNull ResolutionResultsCache.MemberType<F> memberType, 364 @NotNull BasicCallResolutionContext context, 365 @NotNull OverloadResolutionResultsImpl<F> results, 366 @NotNull DelegatingBindingTrace traceToResolveCall, 367 @NotNull TracingStrategy tracing 368 ) { 369 CallKey callKey = CallResolverUtil.createCallKey(context); 370 if (callKey == null) return; 371 372 DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace( 373 new BindingTraceContext().getBindingContext(), "delta trace for caching resolve of", context.call); 374 traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve); 375 376 context.resolutionResultsCache.recordResolutionResults(callKey, memberType, results); 377 context.resolutionResultsCache.recordResolutionTrace(callKey, deltasTraceToCacheResolve); 378 379 if (results.isSingleResult() && memberType == ResolutionResultsCache.FUNCTION_MEMBER_TYPE) { 380 CallCandidateResolutionContext<F> callCandidateResolutionContext = CallCandidateResolutionContext.createForCallBeingAnalyzed( 381 results.getResultingCall().getCallToCompleteTypeArgumentInference(), context, tracing); 382 context.resolutionResultsCache.recordDeferredComputationForCall(callKey, callCandidateResolutionContext, memberType); 383 } 384 } 385 386 private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) { 387 argumentTypeResolver.checkTypesWithNoCallee(context); 388 return OverloadResolutionResultsImpl.nameNotFound(); 389 } 390 391 @NotNull 392 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCall( 393 @NotNull BasicCallResolutionContext context, 394 @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority 395 @NotNull CallTransformer<D, F> callTransformer, 396 @NotNull JetReferenceExpression reference) { 397 398 ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create(); 399 context.trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo); 400 context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope); 401 402 if (context.dataFlowInfo.hasTypeInfoConstraints()) { 403 context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, context.call.getCalleeExpression(), context.dataFlowInfo); 404 } 405 406 debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks); 407 408 TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null; 409 OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null; 410 for (ResolutionTask<D, F> task : prioritizedTasks) { 411 TemporaryBindingTrace taskTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.reference); 412 OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments( 413 task.replaceBindingTrace(taskTrace), callTransformer); 414 if (results.isSuccess() || results.isAmbiguity()) { 415 taskTrace.commit(); 416 417 if (results.isSuccess()) { 418 debugInfo.set(ResolutionDebugInfo.RESULT, results.getResultingCall()); 419 } 420 421 resolveFunctionArguments(context, results); 422 return results; 423 } 424 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) { 425 results.setTrace(taskTrace); 426 return results; 427 } 428 boolean updateResults = traceForFirstNonemptyCandidateSet == null 429 || (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER && 430 results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER); 431 if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) { 432 traceForFirstNonemptyCandidateSet = taskTrace; 433 resultsForFirstNonemptyCandidateSet = results; 434 } 435 } 436 if (traceForFirstNonemptyCandidateSet != null) { 437 traceForFirstNonemptyCandidateSet.commit(); 438 if (resultsForFirstNonemptyCandidateSet.isSingleResult()) { 439 440 debugInfo.set(ResolutionDebugInfo.RESULT, resultsForFirstNonemptyCandidateSet.getResultingCall()); 441 } 442 resolveFunctionArguments(context, resultsForFirstNonemptyCandidateSet); 443 } 444 else { 445 context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference)); 446 argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS); 447 } 448 return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.<F>nameNotFound(); 449 } 450 451 private <D extends CallableDescriptor> OverloadResolutionResults<D> resolveFunctionArguments( 452 @NotNull BasicCallResolutionContext context, 453 @NotNull OverloadResolutionResultsImpl<D> results 454 ) { 455 if (results.isSingleResult()) { 456 argumentTypeResolver.checkTypesForFunctionArguments(context, results.getResultingCall().getCallToCompleteTypeArgumentInference()); 457 } 458 else { 459 argumentTypeResolver.checkTypesForFunctionArgumentsWithNoCallee(context); 460 } 461 return results; 462 } 463 464////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 465 466 @NotNull 467 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolutionGuardedForExtraFunctionLiteralArguments( 468 @NotNull ResolutionTask<D, F> task, 469 @NotNull CallTransformer<D, F> callTransformer 470 ) { 471 OverloadResolutionResultsImpl<F> results = performResolution(task, callTransformer); 472 473 // If resolution fails, we should check for some of the following situations: 474 // class A { 475 // val foo = Bar() // The following is intended to be an anonymous initializer, 476 // // but is treated as a function literal argument 477 // { 478 // ... 479 // } 480 // } 481 // 482 // fun foo() { 483 // bar { 484 // buzz() 485 // {...} // intended to be a returned from the outer literal 486 // } 487 // } 488 ImmutableSet<OverloadResolutionResults.Code> someFailed = ImmutableSet.of(MANY_FAILED_CANDIDATES, 489 SINGLE_CANDIDATE_ARGUMENT_MISMATCH); 490 if (someFailed.contains(results.getResultCode()) && !task.call.getFunctionLiteralArguments().isEmpty() 491 && task.resolveMode == ResolveMode.TOP_LEVEL_CALL) { //For nested calls there are no such cases 492 // We have some candidates that failed for some reason 493 // And we have a suspect: the function literal argument 494 // Now, we try to remove this argument and see if it helps 495 DelegatingCall callWithoutFLArgs = new DelegatingCall(task.call) { 496 @NotNull 497 @Override 498 public List<JetExpression> getFunctionLiteralArguments() { 499 return Collections.emptyList(); 500 } 501 }; 502 TemporaryBindingTrace temporaryTrace = 503 TemporaryBindingTrace.create(task.trace, "trace for resolution guarded for extra function literal arguments"); 504 ResolutionTask<D, F> newTask = task.replaceBindingTrace(temporaryTrace).replaceCall(callWithoutFLArgs); 505 506 OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped = performResolution(newTask, callTransformer); 507 if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) { 508 task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments()); 509 } 510 } 511 512 return results; 513 } 514 515 @NotNull 516 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution( 517 @NotNull ResolutionTask<D, F> task, 518 @NotNull CallTransformer<D, F> callTransformer 519 ) { 520 521 for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) { 522 TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create( 523 task.trace, "trace to resolve candidate"); 524 Collection<CallCandidateResolutionContext<D>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace); 525 for (CallCandidateResolutionContext<D> context : contexts) { 526 527 candidateResolver.performResolutionForCandidateCall(context, task); 528 529 /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten) 530 to have a binding to variable while 'invoke' call resolve */ 531 task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall); 532 533 Collection<ResolvedCallWithTrace<F>> calls = callTransformer.transformCall(context, this, task); 534 535 for (ResolvedCallWithTrace<F> call : calls) { 536 task.tracing.bindReference(call.getTrace(), call); 537 task.tracing.bindResolvedCall(call.getTrace(), call); 538 task.getResolvedCalls().add(call); 539 } 540 } 541 } 542 543 OverloadResolutionResultsImpl<F> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors( 544 task.trace, task.tracing, task.getResolvedCalls()); 545 if (!results.isSingleResult() && !results.isIncomplete()) { 546 argumentTypeResolver.checkTypesWithNoCallee(task.toBasic()); 547 } 548 return results; 549 } 550}