@@ -40,12 +40,15 @@ enum Shadowing {
4040 Unrestricted ,
4141}
4242
43- impl < ' ra , ' tcx > Resolver < ' ra , ' tcx > {
43+ pub ( crate ) trait ScopeVisitor < ' ra , ' tcx >
44+ where
45+ Self : AsRef < Resolver < ' ra , ' tcx > > + Sized ,
46+ {
4447 /// A generic scope visitor.
4548 /// Visits scopes in order to resolve some identifier in them or perform other actions.
4649 /// 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 ,
4952 scope_set : ScopeSet < ' ra > ,
5053 parent_scope : & ParentScope < ' ra > ,
5154 ctxt : SyntaxContext ,
@@ -127,7 +130,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
127130 // As another consequence of this optimization visitors never observe invocation
128131 // scopes for macros that were already expanded.
129132 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+ {
131136 macro_rules_scope. set ( next_scope. get ( ) ) ;
132137 } else {
133138 break ;
@@ -146,7 +151,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
146151
147152 if visit {
148153 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) {
150155 return break_result;
151156 }
152157 }
@@ -169,9 +174,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
169174 MacroRulesScope :: Binding ( binding) => {
170175 Scope :: MacroRules ( binding. parent_macro_rules_scope )
171176 }
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+ ) ,
175180 MacroRulesScope :: Empty => Scope :: Module ( module, None ) ,
176181 } ,
177182 Scope :: Module ( ..) if module_and_extern_prelude => match ns {
@@ -187,7 +192,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
187192 ScopeSet :: Late ( .., lint_id) => lint_id,
188193 _ => None ,
189194 } ;
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+ ) {
191200 Some ( ( parent_module, lint_id) ) => {
192201 Scope :: Module ( parent_module, lint_id. or ( prev_lint_id) )
193202 }
@@ -217,7 +226,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
217226
218227 None
219228 }
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 > { }
220233
234+ impl < ' ra , ' tcx > Resolver < ' ra , ' tcx > {
221235 fn hygienic_lexical_parent (
222236 & self ,
223237 module : Module < ' ra > ,
@@ -421,183 +435,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
421435}
422436
423437impl < ' 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-
601438 /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
602439 /// More specifically, we proceed up the hierarchy of scopes and return the binding for
603440 /// `ident` in the first scope that defines it (or None if no scopes define it).
0 commit comments