Skip to content

Commit 3ab8e2f

Browse files
Extract visit_scopes for Resolver and SmartResolver.
1 parent 92ff367 commit 3ab8e2f

File tree

3 files changed

+26
-186
lines changed

3 files changed

+26
-186
lines changed

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use crate::errors::{
3939
ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition,
4040
MaybeMissingMacroRulesName,
4141
};
42+
use crate::ident::ScopeVisitor as _;
4243
use crate::imports::{Import, ImportKind};
4344
use crate::late::{PatternSource, Rib};
4445
use crate::{

compiler/rustc_resolve/src/ident.rs

Lines changed: 23 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -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

423437
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-
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).

compiler/rustc_resolve/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ pub mod rustdoc;
9292

9393
pub use macros::registered_tools_ast;
9494

95+
use crate::ident::ScopeVisitor as _;
96+
9597
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
9698

9799
#[derive(Debug)]

0 commit comments

Comments
 (0)