@@ -355,34 +355,61 @@ class TypeRefinementContextBuilder : private ASTWalker {
355355
356356private:
357357 bool walkToDeclPre (Decl *D) override {
358- TypeRefinementContext *DeclTRC = getNewContextForWalkOfDecl (D);
358+ // Adds in a parent TRC for decls which are syntatically nested but are not
359+ // represented that way in the AST. (Particularly, AbstractStorageDecl
360+ // parents for AccessorDecl children.)
361+ if (auto ParentTRC = getEffectiveParentContextForDecl (D)) {
362+ pushContext (ParentTRC, D);
363+ }
359364
360- if (DeclTRC) {
365+ // Adds in a TRC that covers the entire declaration.
366+ if (auto DeclTRC = getNewContextForSignatureOfDecl (D)) {
361367 pushContext (DeclTRC, D);
362368 }
363369
364370 return true ;
365371 }
366372
367373 bool walkToDeclPost (Decl *D) override {
368- if (ContextStack.back ().ScopeNode .getAsDecl () == D) {
374+ // As seen above, we could have up to two TRCs in the stack for a single
375+ // declaration.
376+ while (ContextStack.back ().ScopeNode .getAsDecl () == D) {
369377 ContextStack.pop_back ();
370378 }
371379 return true ;
372380 }
373381
374- // / Returns a new context to be introduced for the declaration, or nullptr
375- // / if no new context should be introduced.
376- TypeRefinementContext *getNewContextForWalkOfDecl (Decl *D) {
382+ TypeRefinementContext *getEffectiveParentContextForDecl (Decl *D) {
377383 if (auto accessor = dyn_cast<AccessorDecl>(D)) {
378384 // Use TRC of the storage rather the current TRC when walking this
379385 // function.
386+ // FIXME: Can we assert that we won't process storage later that should
387+ // have been returned now?
380388 auto it = StorageContexts.find (accessor->getStorage ());
381389 if (it != StorageContexts.end ()) {
382390 return it->second ;
383391 }
384392 }
385-
393+ return nullptr ;
394+ }
395+
396+ // / If necessary, records a TRC so it can be returned by subsequent calls to
397+ // / `getEffectiveParentContextForDecl()`.
398+ void recordEffectiveParentContext (Decl *D, TypeRefinementContext *NewTRC) {
399+ // Record the TRC for this storage declaration so that
400+ // when we process the accessor, we can use this TRC as the
401+ // parent in `getEffectiveParentContextForDecl()`.
402+ if (auto *StorageDecl = dyn_cast<AbstractStorageDecl>(D)) {
403+ if (StorageDecl->hasParsedAccessors ()) {
404+ // FIXME: Can we assert that we've never queried for this storage?
405+ StorageContexts[StorageDecl] = NewTRC;
406+ }
407+ }
408+ }
409+
410+ // / Returns a new context to be introduced for the declaration, or nullptr
411+ // / if no new context should be introduced.
412+ TypeRefinementContext *getNewContextForSignatureOfDecl (Decl *D) {
386413 if (declarationIntroducesNewContext (D)) {
387414 return buildDeclarationRefinementContext (D);
388415 }
@@ -414,15 +441,10 @@ class TypeRefinementContextBuilder : private ASTWalker {
414441 ExplicitDeclInfo,
415442 refinementSourceRangeForDecl (D));
416443
417- // Record the TRC for this storage declaration so that
418- // when we process the accessor, we can use this TRC as the
419- // parent.
420- if (auto *StorageDecl = dyn_cast<AbstractStorageDecl>(D)) {
421- if (StorageDecl->hasParsedAccessors ()) {
422- StorageContexts[StorageDecl] = NewTRC;
423- }
424- }
425-
444+
445+ // Possibly use this as an effective parent context later.
446+ recordEffectiveParentContext (D, NewTRC);
447+
426448 return NewTRC;
427449 }
428450
@@ -460,6 +482,16 @@ class TypeRefinementContextBuilder : private ASTWalker {
460482 // Use the declaration's availability for the context when checking
461483 // the bodies of its accessors.
462484
485+ Decl *locDecl = D;
486+ // For a variable declaration (without accessors) we use the range of the
487+ // containing pattern binding declaration to make sure that we include
488+ // any type annotation in the type refinement context range.
489+ if (auto varDecl = dyn_cast<VarDecl>(storageDecl)) {
490+ auto *PBD = varDecl->getParentPatternBinding ();
491+ if (PBD)
492+ locDecl = PBD;
493+ }
494+
463495 // HACK: For synthesized trivial accessors we may have not a valid
464496 // location for the end of the braces, so in that case we will fall back
465497 // to using the range for the storage declaration. The right fix here is
@@ -468,18 +500,11 @@ class TypeRefinementContextBuilder : private ASTWalker {
468500 // locations.
469501 SourceLoc BracesEnd = storageDecl->getBracesRange ().End ;
470502 if (storageDecl->hasParsedAccessors () && BracesEnd.isValid ()) {
471- return SourceRange (storageDecl ->getStartLoc (),
503+ return SourceRange (locDecl ->getStartLoc (),
472504 BracesEnd);
473505 }
474506
475- // For a variable declaration (without accessors) we use the range of the
476- // containing pattern binding declaration to make sure that we include
477- // any type annotation in the type refinement context range.
478- if (auto varDecl = dyn_cast<VarDecl>(storageDecl)) {
479- auto *PBD = varDecl->getParentPatternBinding ();
480- if (PBD)
481- return PBD->getSourceRange ();
482- }
507+ return locDecl->getSourceRange ();
483508 }
484509
485510 return D->getSourceRange ();
0 commit comments