@@ -282,11 +282,17 @@ class CursorInfoTypeCheckSolutionCallback : public TypeCheckCompletionCallback {
282282 bool IsDynamicRef;
283283 // / The declaration that is being referenced. Will never be \c nullptr.
284284 ValueDecl *ReferencedDecl;
285+ // / The interface type of the referenced declaration. This might not be
286+ // / stored in `ReferencedDecl->getInterfaceType()` if the declaration's
287+ // / type hasn't been applied to the AST.
288+ Type SolutionSpecificInterfaceType;
285289
286290 bool operator ==(const CursorInfoDeclReference &Other) const {
287291 return nullableTypesEqual (BaseType, Other.BaseType ) &&
288292 IsDynamicRef == Other.IsDynamicRef &&
289- ReferencedDecl == Other.ReferencedDecl ;
293+ ReferencedDecl == Other.ReferencedDecl &&
294+ nullableTypesEqual (SolutionSpecificInterfaceType,
295+ Other.SolutionSpecificInterfaceType );
290296 }
291297 };
292298
@@ -302,24 +308,43 @@ class CursorInfoTypeCheckSolutionCallback : public TypeCheckCompletionCallback {
302308
303309 SmallVector<CursorInfoDeclReference, 1 > Results;
304310
305- Expr * getExprToResolve () {
311+ void sawSolutionImpl ( const Solution &S) override {
306312 NodeFinder Finder (DC, ResolveLoc);
307313 Finder.resolve ();
308314 auto Result = Finder.takeResult ();
309- if (!Result || Result->getKind () != NodeFinderResultKind::Expr) {
310- return nullptr ;
315+ if (!Result) {
316+ return ;
317+ }
318+ switch (Result->getKind ()) {
319+ case NodeFinderResultKind::Decl: {
320+ ValueDecl *DeclToResolve =
321+ cast<NodeFinderDeclResult>(Result.get ())->getDecl ();
322+ addCursorInfoResultForDecl (DeclToResolve, S);
323+ break ;
324+ }
325+ case NodeFinderResultKind::Expr: {
326+ Expr *ExprToResolve = cast<NodeFinderExprResult>(Result.get ())->getExpr ();
327+ addCursorInfoResultForExpr (ExprToResolve, S);
328+ break ;
329+ }
311330 }
312- return cast<NodeFinderExprResult>(Result.get ())->getExpr ();
313331 }
314332
315- void sawSolutionImpl (const Solution &S) override {
316- auto &CS = S.getConstraintSystem ();
317- auto ResolveExpr = getExprToResolve ();
318- if (!ResolveExpr) {
333+ void addCursorInfoResultForDecl (ValueDecl *DeclToResolve, const Solution &S) {
334+ if (!S.hasType (DeclToResolve)) {
319335 return ;
320336 }
337+ Type SolutionInterfaceTy =
338+ S.simplifyType (S.getType (DeclToResolve))->mapTypeOutOfContext ();
339+
340+ addResult ({/* BaseType=*/ nullptr , /* IsDynamicRef=*/ false , DeclToResolve,
341+ SolutionInterfaceTy});
342+ }
343+
344+ void addCursorInfoResultForExpr (Expr *ExprToResolve, const Solution &S) {
345+ auto &CS = S.getConstraintSystem ();
321346
322- auto Locator = CS.getConstraintLocator (ResolveExpr );
347+ auto Locator = CS.getConstraintLocator (ExprToResolve );
323348 auto CalleeLocator = S.getCalleeLocator (Locator);
324349 auto OverloadInfo = getSelectedOverloadInfo (S, CalleeLocator);
325350 if (!OverloadInfo.ValueRef ) {
@@ -337,9 +362,11 @@ class CursorInfoTypeCheckSolutionCallback : public TypeCheckCompletionCallback {
337362 [&S](Expr *E) { return S.getResolvedType (E); });
338363 }
339364
340- CursorInfoDeclReference NewResult = {OverloadInfo.BaseTy , IsDynamicRef,
341- OverloadInfo.getValue ()};
365+ addResult ({OverloadInfo.BaseTy , IsDynamicRef, OverloadInfo.getValue (),
366+ /* SolutionSpecificInterfaceType=*/ Type ()});
367+ }
342368
369+ void addResult (const CursorInfoDeclReference &NewResult) {
343370 if (llvm::any_of (Results, [&](const CursorInfoDeclReference &R) {
344371 return R == NewResult;
345372 })) {
@@ -367,47 +394,38 @@ class CursorInfoDoneParsingCallback : public DoneParsingCallback {
367394 SourceLoc RequestedLoc)
368395 : DoneParsingCallback(), Consumer(Consumer), RequestedLoc(RequestedLoc) {}
369396
370- std::vector<ResolvedCursorInfoPtr>
371- getDeclResult (NodeFinderDeclResult *DeclResult, SourceFile *SrcFile,
372- NodeFinder &Finder) const {
373- typeCheckDeclAndParentClosures (DeclResult->getDecl ());
374- auto CursorInfo = new ResolvedValueRefCursorInfo (
375- SrcFile, RequestedLoc, DeclResult->getDecl (),
376- /* CtorTyRef=*/ nullptr ,
377- /* ExtTyRef=*/ nullptr , /* IsRef=*/ false , /* Ty=*/ Type (),
378- /* ContainerType=*/ Type (),
379- /* CustomAttrRef=*/ std::nullopt ,
380- /* IsKeywordArgument=*/ false ,
381- /* IsDynamic=*/ false ,
382- /* ReceiverTypes=*/ {},
383- Finder.getShorthandShadowedDecls (DeclResult->getDecl ()));
384- return {CursorInfo};
385- }
386-
387- std::vector<ResolvedCursorInfoPtr>
388- getExprResult (NodeFinderExprResult *ExprResult, SourceFile *SrcFile,
389- NodeFinder &Finder) const {
390- Expr *E = ExprResult->getExpr ();
391- DeclContext *DC = ExprResult->getDeclContext ();
392-
397+ private:
398+ // / Shared core of `getExprResult` and `getDeclResult`.
399+ std::vector<ResolvedCursorInfoPtr> getResult (ASTNode Node, DeclContext *DC,
400+ SourceFile *SrcFile,
401+ NodeFinder &Finder) const {
393402 // Type check the statemnt containing E and listen for solutions.
394403 CursorInfoTypeCheckSolutionCallback Callback (*DC, RequestedLoc);
395404 {
396405 llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
397406 DC->getASTContext ().SolutionCallback , &Callback);
398- typeCheckASTNodeAtLoc (TypeCheckASTNodeAtLocContext::declContext (DC),
399- E->getLoc ());
407+ if (ValueDecl *VD = getAsDecl<ValueDecl>(Node)) {
408+ typeCheckDeclAndParentClosures (VD);
409+ } else {
410+ typeCheckASTNodeAtLoc (TypeCheckASTNodeAtLocContext::declContext (DC),
411+ Node.getStartLoc ());
412+ }
400413 }
401414
402415 if (Callback.getResults ().empty ()) {
403416 // No results.
404417 return {};
405418 }
406419
407- for (auto Info : Callback.getResults ()) {
408- // Type check the referenced decls so that all their parent closures are
409- // type-checked (see comment in typeCheckDeclAndParentClosures).
410- typeCheckDeclAndParentClosures (Info.ReferencedDecl );
420+ if (Node.is <Expr *>()) {
421+ // If we are performing cursor info on an expression, type check the
422+ // referenced decls so that all their parent closures are type-checked
423+ // (see comment in typeCheckDeclAndParentClosures).
424+ // When doing cursor info on a declaration, we already type checked the
425+ // decl above while listening to the solution callbacks.
426+ for (auto Info : Callback.getResults ()) {
427+ typeCheckDeclAndParentClosures (Info.ReferencedDecl );
428+ }
411429 }
412430
413431 // Deliver results
@@ -434,7 +452,8 @@ class CursorInfoDoneParsingCallback : public DoneParsingCallback {
434452 auto CursorInfo = new ResolvedValueRefCursorInfo (
435453 SrcFile, RequestedLoc, Res.ReferencedDecl ,
436454 /* CtorTyRef=*/ nullptr ,
437- /* ExtTyRef=*/ nullptr , /* IsRef=*/ true , /* Ty=*/ Type (),
455+ /* ExtTyRef=*/ nullptr , /* IsRef=*/ true ,
456+ Res.SolutionSpecificInterfaceType ,
438457 /* ContainerType=*/ Res.BaseType ,
439458 /* CustomAttrRef=*/ std::nullopt ,
440459 /* IsKeywordArgument=*/ false , Res.IsDynamicRef , ReceiverTypes,
@@ -444,6 +463,43 @@ class CursorInfoDoneParsingCallback : public DoneParsingCallback {
444463 return Results;
445464 }
446465
466+ public:
467+ std::vector<ResolvedCursorInfoPtr>
468+ getDeclResult (NodeFinderDeclResult *DeclResult, SourceFile *SrcFile,
469+ NodeFinder &Finder) const {
470+ std::vector<ResolvedCursorInfoPtr> Results =
471+ getResult (DeclResult->getDecl (),
472+ DeclResult->getDecl ()->getDeclContext (), SrcFile, Finder);
473+
474+ if (!Results.empty ()) {
475+ return Results;
476+ }
477+
478+ // If we didn't get any solution from the constraint system, try getting the
479+ // type from the decl itself. This may happen if the decl is in an inactive
480+ // branch of a `#if` clause.
481+ auto CursorInfo = new ResolvedValueRefCursorInfo (
482+ SrcFile, RequestedLoc, DeclResult->getDecl (),
483+ /* CtorTyRef=*/ nullptr ,
484+ /* ExtTyRef=*/ nullptr ,
485+ /* IsRef=*/ false ,
486+ /* SolutionSpecificInterfaceType=*/ Type (),
487+ /* ContainerType=*/ Type (),
488+ /* CustomAttrRef=*/ std::nullopt ,
489+ /* IsKeywordArgument=*/ false ,
490+ /* IsDynamic=*/ false ,
491+ /* ReceiverTypes=*/ {},
492+ Finder.getShorthandShadowedDecls (DeclResult->getDecl ()));
493+ return {CursorInfo};
494+ }
495+
496+ std::vector<ResolvedCursorInfoPtr>
497+ getExprResult (NodeFinderExprResult *ExprResult, SourceFile *SrcFile,
498+ NodeFinder &Finder) const {
499+ return getResult (ExprResult->getExpr (), ExprResult->getDeclContext (),
500+ SrcFile, Finder);
501+ }
502+
447503 void doneParsing (SourceFile *SrcFile) override {
448504 if (!SrcFile) {
449505 return ;
0 commit comments