@@ -355,34 +355,61 @@ class TypeRefinementContextBuilder : private ASTWalker {
355
355
356
356
private:
357
357
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
+ }
359
364
360
- if (DeclTRC) {
365
+ // Adds in a TRC that covers the entire declaration.
366
+ if (auto DeclTRC = getNewContextForSignatureOfDecl (D)) {
361
367
pushContext (DeclTRC, D);
362
368
}
363
369
364
370
return true ;
365
371
}
366
372
367
373
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) {
369
377
ContextStack.pop_back ();
370
378
}
371
379
return true ;
372
380
}
373
381
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) {
377
383
if (auto accessor = dyn_cast<AccessorDecl>(D)) {
378
384
// Use TRC of the storage rather the current TRC when walking this
379
385
// function.
386
+ // FIXME: Can we assert that we won't process storage later that should
387
+ // have been returned now?
380
388
auto it = StorageContexts.find (accessor->getStorage ());
381
389
if (it != StorageContexts.end ()) {
382
390
return it->second ;
383
391
}
384
392
}
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) {
386
413
if (declarationIntroducesNewContext (D)) {
387
414
return buildDeclarationRefinementContext (D);
388
415
}
@@ -414,15 +441,10 @@ class TypeRefinementContextBuilder : private ASTWalker {
414
441
ExplicitDeclInfo,
415
442
refinementSourceRangeForDecl (D));
416
443
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
+
426
448
return NewTRC;
427
449
}
428
450
@@ -460,6 +482,16 @@ class TypeRefinementContextBuilder : private ASTWalker {
460
482
// Use the declaration's availability for the context when checking
461
483
// the bodies of its accessors.
462
484
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
+
463
495
// HACK: For synthesized trivial accessors we may have not a valid
464
496
// location for the end of the braces, so in that case we will fall back
465
497
// to using the range for the storage declaration. The right fix here is
@@ -468,18 +500,11 @@ class TypeRefinementContextBuilder : private ASTWalker {
468
500
// locations.
469
501
SourceLoc BracesEnd = storageDecl->getBracesRange ().End ;
470
502
if (storageDecl->hasParsedAccessors () && BracesEnd.isValid ()) {
471
- return SourceRange (storageDecl ->getStartLoc (),
503
+ return SourceRange (locDecl ->getStartLoc (),
472
504
BracesEnd);
473
505
}
474
506
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 ();
483
508
}
484
509
485
510
return D->getSourceRange ();
0 commit comments