@@ -40,12 +40,15 @@ enum Shadowing {
40
40
Unrestricted ,
41
41
}
42
42
43
- impl < ' ra , ' tcx > Resolver < ' ra , ' tcx > {
43
+ pub ( crate ) trait ScopeVisitor < ' ra , ' tcx >
44
+ where
45
+ Self : AsRef < Resolver < ' ra , ' tcx > > + Sized ,
46
+ {
44
47
/// A generic scope visitor.
45
48
/// Visits scopes in order to resolve some identifier in them or perform other actions.
46
49
/// If the callback returns `Some` result, we stop visiting scopes and return it.
47
- pub ( crate ) fn visit_scopes < T > (
48
- & mut self ,
50
+ fn visit_scopes < T > (
51
+ mut self ,
49
52
scope_set : ScopeSet < ' ra > ,
50
53
parent_scope : & ParentScope < ' ra > ,
51
54
ctxt : SyntaxContext ,
@@ -127,7 +130,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
127
130
// As another consequence of this optimization visitors never observe invocation
128
131
// scopes for macros that were already expanded.
129
132
while let MacroRulesScope :: Invocation ( invoc_id) = macro_rules_scope. get ( ) {
130
- if let Some ( next_scope) = self . output_macro_rules_scopes . get ( & invoc_id) {
133
+ if let Some ( next_scope) =
134
+ self . as_ref ( ) . output_macro_rules_scopes . get ( & invoc_id)
135
+ {
131
136
macro_rules_scope. set ( next_scope. get ( ) ) ;
132
137
} else {
133
138
break ;
@@ -146,7 +151,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
146
151
147
152
if visit {
148
153
let use_prelude = if use_prelude { UsePrelude :: Yes } else { UsePrelude :: No } ;
149
- if let break_result @ Some ( ..) = visitor ( self , scope, use_prelude, ctxt) {
154
+ if let break_result @ Some ( ..) = visitor ( & mut self , scope, use_prelude, ctxt) {
150
155
return break_result;
151
156
}
152
157
}
@@ -169,9 +174,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
169
174
MacroRulesScope :: Binding ( binding) => {
170
175
Scope :: MacroRules ( binding. parent_macro_rules_scope )
171
176
}
172
- MacroRulesScope :: Invocation ( invoc_id) => {
173
- Scope :: MacroRules ( self . invocation_parent_scopes [ & invoc_id] . macro_rules )
174
- }
177
+ MacroRulesScope :: Invocation ( invoc_id) => Scope :: MacroRules (
178
+ self . as_ref ( ) . invocation_parent_scopes [ & invoc_id] . macro_rules ,
179
+ ) ,
175
180
MacroRulesScope :: Empty => Scope :: Module ( module, None ) ,
176
181
} ,
177
182
Scope :: Module ( ..) if module_and_extern_prelude => match ns {
@@ -187,7 +192,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
187
192
ScopeSet :: Late ( .., lint_id) => lint_id,
188
193
_ => None ,
189
194
} ;
190
- match self . hygienic_lexical_parent ( module, & mut ctxt, derive_fallback_lint_id) {
195
+ match self . as_ref ( ) . hygienic_lexical_parent (
196
+ module,
197
+ & mut ctxt,
198
+ derive_fallback_lint_id,
199
+ ) {
191
200
Some ( ( parent_module, lint_id) ) => {
192
201
Scope :: Module ( parent_module, lint_id. or ( prev_lint_id) )
193
202
}
@@ -217,7 +226,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
217
226
218
227
None
219
228
}
229
+ }
230
+
231
+ impl < ' ra , ' tcx > ScopeVisitor < ' ra , ' tcx > for & mut Resolver < ' ra , ' tcx > { }
232
+ impl < ' r , ' ra , ' tcx > ScopeVisitor < ' ra , ' tcx > for SmartResolver < ' r , ' ra , ' tcx > { }
220
233
234
+ impl < ' ra , ' tcx > Resolver < ' ra , ' tcx > {
221
235
fn hygienic_lexical_parent (
222
236
& self ,
223
237
module : Module < ' ra > ,
@@ -421,183 +435,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
421
435
}
422
436
423
437
impl < ' r , ' ra , ' tcx > SmartResolver < ' r , ' ra , ' tcx > {
424
- /// A generic scope visitor.
425
- /// Visits scopes in order to resolve some identifier in them or perform other actions.
426
- /// If the callback returns `Some` result, we stop visiting scopes and return it.
427
- pub ( crate ) fn visit_scopes < T > (
428
- mut self ,
429
- scope_set : ScopeSet < ' ra > ,
430
- parent_scope : & ParentScope < ' ra > ,
431
- ctxt : SyntaxContext ,
432
- mut visitor : impl FnMut ( & mut Self , Scope < ' ra > , UsePrelude , SyntaxContext ) -> Option < T > ,
433
- ) -> Option < T > {
434
- // General principles:
435
- // 1. Not controlled (user-defined) names should have higher priority than controlled names
436
- // built into the language or standard library. This way we can add new names into the
437
- // language or standard library without breaking user code.
438
- // 2. "Closed set" below means new names cannot appear after the current resolution attempt.
439
- // Places to search (in order of decreasing priority):
440
- // (Type NS)
441
- // 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet
442
- // (open set, not controlled).
443
- // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
444
- // (open, not controlled).
445
- // 3. Extern prelude (open, the open part is from macro expansions, not controlled).
446
- // 4. Tool modules (closed, controlled right now, but not in the future).
447
- // 5. Standard library prelude (de-facto closed, controlled).
448
- // 6. Language prelude (closed, controlled).
449
- // (Value NS)
450
- // 1. FIXME: Ribs (local variables), there's no necessary infrastructure yet
451
- // (open set, not controlled).
452
- // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
453
- // (open, not controlled).
454
- // 3. Standard library prelude (de-facto closed, controlled).
455
- // (Macro NS)
456
- // 1-3. Derive helpers (open, not controlled). All ambiguities with other names
457
- // are currently reported as errors. They should be higher in priority than preludes
458
- // and probably even names in modules according to the "general principles" above. They
459
- // also should be subject to restricted shadowing because are effectively produced by
460
- // derives (you need to resolve the derive first to add helpers into scope), but they
461
- // should be available before the derive is expanded for compatibility.
462
- // It's mess in general, so we are being conservative for now.
463
- // 1-3. `macro_rules` (open, not controlled), loop through `macro_rules` scopes. Have higher
464
- // priority than prelude macros, but create ambiguities with macros in modules.
465
- // 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
466
- // (open, not controlled). Have higher priority than prelude macros, but create
467
- // ambiguities with `macro_rules`.
468
- // 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
469
- // 4a. User-defined prelude from macro-use
470
- // (open, the open part is from macro expansions, not controlled).
471
- // 4b. "Standard library prelude" part implemented through `macro-use` (closed, controlled).
472
- // 4c. Standard library prelude (de-facto closed, controlled).
473
- // 6. Language prelude: builtin attributes (closed, controlled).
474
-
475
- let rust_2015 = ctxt. edition ( ) . is_rust_2015 ( ) ;
476
- let ( ns, macro_kind) = match scope_set {
477
- ScopeSet :: All ( ns)
478
- | ScopeSet :: ModuleAndExternPrelude ( ns, _)
479
- | ScopeSet :: Late ( ns, ..) => ( ns, None ) ,
480
- ScopeSet :: Macro ( macro_kind) => ( MacroNS , Some ( macro_kind) ) ,
481
- } ;
482
- let module = match scope_set {
483
- // Start with the specified module.
484
- ScopeSet :: Late ( _, module, _) | ScopeSet :: ModuleAndExternPrelude ( _, module) => module,
485
- // Jump out of trait or enum modules, they do not act as scopes.
486
- _ => parent_scope. module . nearest_item_scope ( ) ,
487
- } ;
488
- let module_and_extern_prelude = matches ! ( scope_set, ScopeSet :: ModuleAndExternPrelude ( ..) ) ;
489
- let mut scope = match ns {
490
- _ if module_and_extern_prelude => Scope :: Module ( module, None ) ,
491
- TypeNS | ValueNS => Scope :: Module ( module, None ) ,
492
- MacroNS => Scope :: DeriveHelpers ( parent_scope. expansion ) ,
493
- } ;
494
- let mut ctxt = ctxt. normalize_to_macros_2_0 ( ) ;
495
- let mut use_prelude = !module. no_implicit_prelude ;
496
-
497
- loop {
498
- let visit = match scope {
499
- // Derive helpers are not in scope when resolving derives in the same container.
500
- Scope :: DeriveHelpers ( expn_id) => {
501
- !( expn_id == parent_scope. expansion && macro_kind == Some ( MacroKind :: Derive ) )
502
- }
503
- Scope :: DeriveHelpersCompat => true ,
504
- Scope :: MacroRules ( macro_rules_scope) => {
505
- // Use "path compression" on `macro_rules` scope chains. This is an optimization
506
- // used to avoid long scope chains, see the comments on `MacroRulesScopeRef`.
507
- // As another consequence of this optimization visitors never observe invocation
508
- // scopes for macros that were already expanded.
509
- while let MacroRulesScope :: Invocation ( invoc_id) = macro_rules_scope. get ( ) {
510
- if let Some ( next_scope) = self . output_macro_rules_scopes . get ( & invoc_id) {
511
- macro_rules_scope. set ( next_scope. get ( ) ) ;
512
- } else {
513
- break ;
514
- }
515
- }
516
- true
517
- }
518
- Scope :: Module ( ..) => true ,
519
- Scope :: MacroUsePrelude => use_prelude || rust_2015,
520
- Scope :: BuiltinAttrs => true ,
521
- Scope :: ExternPrelude => use_prelude || module_and_extern_prelude,
522
- Scope :: ToolPrelude => use_prelude,
523
- Scope :: StdLibPrelude => use_prelude || ns == MacroNS ,
524
- Scope :: BuiltinTypes => true ,
525
- } ;
526
-
527
- if visit {
528
- let use_prelude = if use_prelude { UsePrelude :: Yes } else { UsePrelude :: No } ;
529
- if let break_result @ Some ( ..) = visitor ( & mut self , scope, use_prelude, ctxt) {
530
- return break_result;
531
- }
532
- }
533
-
534
- scope = match scope {
535
- Scope :: DeriveHelpers ( LocalExpnId :: ROOT ) => Scope :: DeriveHelpersCompat ,
536
- Scope :: DeriveHelpers ( expn_id) => {
537
- // Derive helpers are not visible to code generated by bang or derive macros.
538
- let expn_data = expn_id. expn_data ( ) ;
539
- match expn_data. kind {
540
- ExpnKind :: Root
541
- | ExpnKind :: Macro ( MacroKind :: Bang | MacroKind :: Derive , _) => {
542
- Scope :: DeriveHelpersCompat
543
- }
544
- _ => Scope :: DeriveHelpers ( expn_data. parent . expect_local ( ) ) ,
545
- }
546
- }
547
- Scope :: DeriveHelpersCompat => Scope :: MacroRules ( parent_scope. macro_rules ) ,
548
- Scope :: MacroRules ( macro_rules_scope) => match macro_rules_scope. get ( ) {
549
- MacroRulesScope :: Binding ( binding) => {
550
- Scope :: MacroRules ( binding. parent_macro_rules_scope )
551
- }
552
- MacroRulesScope :: Invocation ( invoc_id) => {
553
- Scope :: MacroRules ( self . invocation_parent_scopes [ & invoc_id] . macro_rules )
554
- }
555
- MacroRulesScope :: Empty => Scope :: Module ( module, None ) ,
556
- } ,
557
- Scope :: Module ( ..) if module_and_extern_prelude => match ns {
558
- TypeNS => {
559
- ctxt. adjust ( ExpnId :: root ( ) ) ;
560
- Scope :: ExternPrelude
561
- }
562
- ValueNS | MacroNS => break ,
563
- } ,
564
- Scope :: Module ( module, prev_lint_id) => {
565
- use_prelude = !module. no_implicit_prelude ;
566
- let derive_fallback_lint_id = match scope_set {
567
- ScopeSet :: Late ( .., lint_id) => lint_id,
568
- _ => None ,
569
- } ;
570
- match self . hygienic_lexical_parent ( module, & mut ctxt, derive_fallback_lint_id) {
571
- Some ( ( parent_module, lint_id) ) => {
572
- Scope :: Module ( parent_module, lint_id. or ( prev_lint_id) )
573
- }
574
- None => {
575
- ctxt. adjust ( ExpnId :: root ( ) ) ;
576
- match ns {
577
- TypeNS => Scope :: ExternPrelude ,
578
- ValueNS => Scope :: StdLibPrelude ,
579
- MacroNS => Scope :: MacroUsePrelude ,
580
- }
581
- }
582
- }
583
- }
584
- Scope :: MacroUsePrelude => Scope :: StdLibPrelude ,
585
- Scope :: BuiltinAttrs => break , // nowhere else to search
586
- Scope :: ExternPrelude if module_and_extern_prelude => break ,
587
- Scope :: ExternPrelude => Scope :: ToolPrelude ,
588
- Scope :: ToolPrelude => Scope :: StdLibPrelude ,
589
- Scope :: StdLibPrelude => match ns {
590
- TypeNS => Scope :: BuiltinTypes ,
591
- ValueNS => break , // nowhere else to search
592
- MacroNS => Scope :: BuiltinAttrs ,
593
- } ,
594
- Scope :: BuiltinTypes => break , // nowhere else to search
595
- } ;
596
- }
597
-
598
- None
599
- }
600
-
601
438
/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
602
439
/// More specifically, we proceed up the hierarchy of scopes and return the binding for
603
440
/// `ident` in the first scope that defines it (or None if no scopes define it).
0 commit comments