Skip to content

Commit 1b6be5a

Browse files
committed
resolve: Put different parent scopes into a single structure
1 parent f2302da commit 1b6be5a

File tree

6 files changed

+108
-72
lines changed

6 files changed

+108
-72
lines changed

src/librustc_resolve/build_reduced_graph.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
//! Here we build the "reduced graph": the graph of the module tree without
1414
//! any imports resolved.
1515
16-
use macros::{InvocationData, LegacyScope};
16+
use macros::{InvocationData, ParentScope, LegacyScope};
1717
use resolve_imports::ImportDirective;
1818
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
1919
use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
@@ -1061,8 +1061,15 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> {
10611061

10621062
fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
10631063
if !attr.is_sugared_doc && is_builtin_attr(attr) {
1064-
self.resolver.current_module.builtin_attrs.borrow_mut().push((
1065-
attr.path.segments[0].ident, self.expansion, self.current_legacy_scope
1064+
let parent_scope = ParentScope {
1065+
module: self.resolver.current_module.nearest_item_scope(),
1066+
expansion: self.expansion,
1067+
legacy: self.current_legacy_scope,
1068+
// Let's hope discerning built-in attributes from derive helpers is not necessary
1069+
derives: Vec::new(),
1070+
};
1071+
parent_scope.module.builtin_attrs.borrow_mut().push((
1072+
attr.path.segments[0].ident, parent_scope
10661073
));
10671074
}
10681075
visit::walk_attribute(self, attr);

src/librustc_resolve/lib.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ use std::mem::replace;
8080
use rustc_data_structures::sync::Lrc;
8181

8282
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
83-
use macros::{InvocationData, LegacyBinding, LegacyScope};
83+
use macros::{InvocationData, LegacyBinding, ParentScope};
8484

8585
// NB: This module needs to be declared first so diagnostics are
8686
// registered before they are used.
@@ -1009,9 +1009,9 @@ pub struct ModuleData<'a> {
10091009
normal_ancestor_id: DefId,
10101010

10111011
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
1012-
legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, Mark, LegacyScope<'a>, Option<Def>)>>,
1012+
legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>, Option<Def>)>>,
10131013
macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
1014-
builtin_attrs: RefCell<Vec<(Ident, Mark, LegacyScope<'a>)>>,
1014+
builtin_attrs: RefCell<Vec<(Ident, ParentScope<'a>)>>,
10151015

10161016
// Macro invocations that can expand into items in this module.
10171017
unresolved_invocations: RefCell<FxHashSet<Mark>>,
@@ -3494,23 +3494,25 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
34943494
path_span: Span,
34953495
crate_lint: CrateLint,
34963496
) -> PathResult<'a> {
3497-
self.resolve_path_with_parent_expansion(base_module, path, opt_ns, Mark::root(),
3498-
record_used, path_span, crate_lint)
3497+
let parent_scope = ParentScope { module: self.current_module, ..self.dummy_parent_scope() };
3498+
self.resolve_path_with_parent_scope(base_module, path, opt_ns, &parent_scope,
3499+
record_used, path_span, crate_lint)
34993500
}
35003501

3501-
fn resolve_path_with_parent_expansion(
3502+
fn resolve_path_with_parent_scope(
35023503
&mut self,
35033504
base_module: Option<ModuleOrUniformRoot<'a>>,
35043505
path: &[Ident],
35053506
opt_ns: Option<Namespace>, // `None` indicates a module path
3506-
parent_expansion: Mark,
3507+
parent_scope: &ParentScope<'a>,
35073508
record_used: bool,
35083509
path_span: Span,
35093510
crate_lint: CrateLint,
35103511
) -> PathResult<'a> {
35113512
let mut module = base_module;
35123513
let mut allow_super = true;
35133514
let mut second_binding = None;
3515+
self.current_module = parent_scope.module;
35143516

35153517
debug!(
35163518
"resolve_path(path={:?}, opt_ns={:?}, record_used={:?}, \
@@ -3596,9 +3598,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
35963598
self.resolve_ident_in_module(module, ident, ns, record_used, path_span)
35973599
} else if opt_ns == Some(MacroNS) {
35983600
assert!(ns == TypeNS);
3599-
self.resolve_lexical_macro_path_segment(ident, ns, None, parent_expansion,
3600-
record_used, record_used, path_span)
3601-
.map(|(binding, _)| binding)
3601+
self.resolve_lexical_macro_path_segment(ident, ns, None, parent_scope, record_used,
3602+
record_used, path_span).map(|(b, _)| b)
36023603
} else {
36033604
let record_used_id =
36043605
if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };

src/librustc_resolve/macros.rs

+81-53
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ pub enum LegacyScope<'a> {
101101
Invocation(&'a InvocationData<'a>),
102102
}
103103

104+
/// Everything you need to resolve a macro path.
105+
#[derive(Clone)]
106+
pub struct ParentScope<'a> {
107+
crate module: Module<'a>,
108+
crate expansion: Mark,
109+
crate legacy: LegacyScope<'a>,
110+
crate derives: Vec<ast::Path>,
111+
}
112+
104113
pub struct ProcMacError {
105114
crate_name: Symbol,
106115
name: Symbol,
@@ -326,14 +335,15 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
326335
InvocationKind::Attr { attr: None, .. } =>
327336
return Ok(None),
328337
InvocationKind::Attr { attr: Some(ref attr), ref traits, .. } =>
329-
(&attr.path, MacroKind::Attr, &traits[..]),
338+
(&attr.path, MacroKind::Attr, traits.clone()),
330339
InvocationKind::Bang { ref mac, .. } =>
331-
(&mac.node.path, MacroKind::Bang, &[][..]),
340+
(&mac.node.path, MacroKind::Bang, Vec::new()),
332341
InvocationKind::Derive { ref path, .. } =>
333-
(path, MacroKind::Derive, &[][..]),
342+
(path, MacroKind::Derive, Vec::new()),
334343
};
335344

336-
let (def, ext) = self.resolve_macro_to_def(path, kind, invoc_id, derives_in_scope, force)?;
345+
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
346+
let (def, ext) = self.resolve_macro_to_def(path, kind, &parent_scope, force)?;
337347

338348
if let Def::Macro(def_id, _) = def {
339349
self.macro_defs.insert(invoc.expansion_data.mark, def_id);
@@ -349,9 +359,10 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
349359
}
350360

351361
fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
352-
derives_in_scope: &[ast::Path], force: bool)
362+
derives_in_scope: Vec<ast::Path>, force: bool)
353363
-> Result<Lrc<SyntaxExtension>, Determinacy> {
354-
Ok(self.resolve_macro_to_def(path, kind, invoc_id, derives_in_scope, force)?.1)
364+
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
365+
Ok(self.resolve_macro_to_def(path, kind, &parent_scope, force)?.1)
355366
}
356367

357368
fn check_unused_macros(&self) {
@@ -373,10 +384,28 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
373384
}
374385

375386
impl<'a, 'cl> Resolver<'a, 'cl> {
376-
fn resolve_macro_to_def(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
377-
derives_in_scope: &[ast::Path], force: bool)
378-
-> Result<(Def, Lrc<SyntaxExtension>), Determinacy> {
379-
let def = self.resolve_macro_to_def_inner(path, kind, invoc_id, derives_in_scope, force);
387+
pub fn dummy_parent_scope(&mut self) -> ParentScope<'a> {
388+
self.invoc_parent_scope(Mark::root(), Vec::new())
389+
}
390+
391+
fn invoc_parent_scope(&mut self, invoc_id: Mark, derives: Vec<ast::Path>) -> ParentScope<'a> {
392+
let invoc = self.invocations[&invoc_id];
393+
ParentScope {
394+
module: invoc.module.get().nearest_item_scope(),
395+
expansion: invoc_id.parent(),
396+
legacy: invoc.parent_legacy_scope.get(),
397+
derives,
398+
}
399+
}
400+
401+
fn resolve_macro_to_def(
402+
&mut self,
403+
path: &ast::Path,
404+
kind: MacroKind,
405+
parent_scope: &ParentScope<'a>,
406+
force: bool,
407+
) -> Result<(Def, Lrc<SyntaxExtension>), Determinacy> {
408+
let def = self.resolve_macro_to_def_inner(path, kind, parent_scope, force);
380409

381410
// Report errors and enforce feature gates for the resolved macro.
382411
if def != Err(Determinacy::Undetermined) {
@@ -440,15 +469,15 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
440469
Ok((def, self.get_macro(def)))
441470
}
442471

443-
pub fn resolve_macro_to_def_inner(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
444-
derives_in_scope: &[ast::Path], force: bool)
445-
-> Result<Def, Determinacy> {
472+
pub fn resolve_macro_to_def_inner(
473+
&mut self,
474+
path: &ast::Path,
475+
kind: MacroKind,
476+
parent_scope: &ParentScope<'a>,
477+
force: bool,
478+
) -> Result<Def, Determinacy> {
446479
let ast::Path { ref segments, span } = *path;
447480
let mut path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
448-
let invocation = self.invocations[&invoc_id];
449-
let parent_expansion = invoc_id.parent();
450-
let parent_legacy_scope = invocation.parent_legacy_scope.get();
451-
self.current_module = invocation.module.get().nearest_item_scope();
452481

453482
// Possibly apply the macro helper hack
454483
if kind == MacroKind::Bang && path.len() == 1 &&
@@ -458,9 +487,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
458487
}
459488

460489
if path.len() > 1 {
461-
let def = match self.resolve_path_with_parent_expansion(None, &path, Some(MacroNS),
462-
parent_expansion, false, span,
463-
CrateLint::No) {
490+
let def = match self.resolve_path_with_parent_scope(None, &path, Some(MacroNS),
491+
parent_scope, false, span,
492+
CrateLint::No) {
464493
PathResult::NonModule(path_res) => match path_res.base_def() {
465494
Def::Err => Err(Determinacy::Determined),
466495
def @ _ => {
@@ -480,19 +509,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
480509
Err(Determinacy::Determined)
481510
},
482511
};
483-
self.current_module.macro_resolutions.borrow_mut()
512+
parent_scope.module.macro_resolutions.borrow_mut()
484513
.push((path.into_boxed_slice(), span));
485514
return def;
486515
}
487516

488-
let legacy_resolution = self.resolve_legacy_scope(
489-
path[0], Some(kind), parent_expansion, parent_legacy_scope, false
490-
);
491-
let result = if let Some(legacy_binding) = legacy_resolution {
517+
let result = if let Some(legacy_binding) = self.resolve_legacy_scope(path[0], Some(kind),
518+
parent_scope, false) {
492519
Ok(legacy_binding.def())
493520
} else {
494521
match self.resolve_lexical_macro_path_segment(path[0], MacroNS, Some(kind),
495-
parent_expansion, false, force, span) {
522+
parent_scope, false, force, span) {
496523
Ok((binding, _)) => Ok(binding.def_ignoring_ambiguity()),
497524
Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
498525
Err(Determinacy::Determined) => {
@@ -502,8 +529,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
502529
}
503530
};
504531

505-
self.current_module.legacy_macro_resolutions.borrow_mut()
506-
.push((path[0], kind, parent_expansion, parent_legacy_scope, result.ok()));
532+
parent_scope.module.legacy_macro_resolutions.borrow_mut()
533+
.push((path[0], kind, parent_scope.clone(), result.ok()));
507534

508535
if let Ok(Def::NonMacroAttr(NonMacroAttrKind::Custom)) = result {} else {
509536
return result;
@@ -521,9 +548,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
521548
assert!(kind == MacroKind::Attr);
522549
enum ConvertToDeriveHelper { Yes, No, DontKnow }
523550
let mut convert_to_derive_helper = ConvertToDeriveHelper::No;
524-
for derive in derives_in_scope {
525-
match self.resolve_macro_path(derive, MacroKind::Derive, invoc_id, &[], force) {
526-
Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext {
551+
for derive in &parent_scope.derives {
552+
match self.resolve_macro_to_def(derive, MacroKind::Derive, parent_scope, force) {
553+
Ok((_, ext)) => if let SyntaxExtension::ProcMacroDerive(_, inert_attrs, _) = &*ext {
527554
if inert_attrs.contains(&path[0].name) {
528555
convert_to_derive_helper = ConvertToDeriveHelper::Yes;
529556
break
@@ -551,7 +578,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
551578
mut ident: Ident,
552579
ns: Namespace,
553580
kind: Option<MacroKind>,
554-
parent_expansion: Mark,
581+
parent_scope: &ParentScope<'a>,
555582
record_used: bool,
556583
force: bool,
557584
path_span: Span,
@@ -610,8 +637,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
610637
}
611638

612639
// Go through all the scopes and try to resolve the name.
613-
let mut where_to_resolve = WhereToResolve::Module(self.current_module);
614-
let mut use_prelude = !self.current_module.no_implicit_prelude;
640+
let mut where_to_resolve = WhereToResolve::Module(parent_scope.module);
641+
let mut use_prelude = !parent_scope.module.no_implicit_prelude;
615642
loop {
616643
let result = match where_to_resolve {
617644
WhereToResolve::Module(module) => {
@@ -755,7 +782,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
755782
// Found another solution, if the first one was "weak", report an error.
756783
if result.0.def() != innermost_result.0.def() &&
757784
(innermost_result.0.is_glob_import() ||
758-
innermost_result.0.may_appear_after(parent_expansion, result.0)) {
785+
innermost_result.0.may_appear_after(parent_scope.expansion, result.0)) {
759786
self.ambiguity_errors.push(AmbiguityError {
760787
ident,
761788
b1: innermost_result.0,
@@ -797,13 +824,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
797824
}
798825
}
799826

800-
fn resolve_legacy_scope(&mut self,
801-
ident: Ident,
802-
kind: Option<MacroKind>,
803-
parent_expansion: Mark,
804-
parent_legacy_scope: LegacyScope<'a>,
805-
record_used: bool)
806-
-> Option<&'a NameBinding<'a>> {
827+
fn resolve_legacy_scope(
828+
&mut self,
829+
ident: Ident,
830+
kind: Option<MacroKind>,
831+
parent_scope: &ParentScope<'a>,
832+
record_used: bool,
833+
) -> Option<&'a NameBinding<'a>> {
807834
if macro_kind_mismatch(ident.name, kind, Some(MacroKind::Bang)) {
808835
return None;
809836
}
@@ -824,7 +851,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
824851
let mut innermost_result: Option<&NameBinding> = None;
825852

826853
// Go through all the scopes and try to resolve the name.
827-
let mut where_to_resolve = parent_legacy_scope;
854+
let mut where_to_resolve = parent_scope.legacy;
828855
loop {
829856
let result = match where_to_resolve {
830857
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
@@ -852,7 +879,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
852879
if let Some(innermost_result) = innermost_result {
853880
// Found another solution, if the first one was "weak", report an error.
854881
if result.def() != innermost_result.def() &&
855-
innermost_result.may_appear_after(parent_expansion, result) {
882+
innermost_result.may_appear_after(parent_scope.expansion, result) {
856883
self.ambiguity_errors.push(AmbiguityError {
857884
ident,
858885
b1: innermost_result,
@@ -889,14 +916,15 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
889916
}
890917
}
891918

892-
for &(ident, kind, parent_expansion, parent_legacy_scope, def)
893-
in module.legacy_macro_resolutions.borrow().iter() {
919+
let legacy_macro_resolutions =
920+
mem::replace(&mut *module.legacy_macro_resolutions.borrow_mut(), Vec::new());
921+
for (ident, kind, parent_scope, def) in legacy_macro_resolutions {
894922
let span = ident.span;
895923
let legacy_resolution = self.resolve_legacy_scope(
896-
ident, Some(kind), parent_expansion, parent_legacy_scope, true
924+
ident, Some(kind), &parent_scope, true
897925
);
898926
let resolution = self.resolve_lexical_macro_path_segment(
899-
ident, MacroNS, Some(kind), parent_expansion, true, true, span
927+
ident, MacroNS, Some(kind), &parent_scope, true, true, span
900928
);
901929

902930
let check_consistency = |this: &Self, new_def: Def| {
@@ -932,7 +960,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
932960
(Some(legacy_binding), Ok((binding, FromPrelude(from_prelude))))
933961
if legacy_binding.def() != binding.def_ignoring_ambiguity() &&
934962
(!from_prelude ||
935-
legacy_binding.may_appear_after(parent_expansion, binding)) => {
963+
legacy_binding.may_appear_after(parent_scope.expansion, binding)) => {
936964
self.report_ambiguity_error(ident, legacy_binding, binding);
937965
},
938966
// OK, non-macro-expanded legacy wins over prelude even if defs are different
@@ -953,13 +981,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
953981
};
954982
}
955983

956-
for &(ident, parent_expansion, parent_legacy_scope)
957-
in module.builtin_attrs.borrow().iter() {
984+
let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new());
985+
for (ident, parent_scope) in builtin_attrs {
958986
let resolve_legacy = |this: &mut Self| this.resolve_legacy_scope(
959-
ident, Some(MacroKind::Attr), parent_expansion, parent_legacy_scope, true
987+
ident, Some(MacroKind::Attr), &parent_scope, true
960988
);
961989
let resolve_modern = |this: &mut Self| this.resolve_lexical_macro_path_segment(
962-
ident, MacroNS, Some(MacroKind::Attr), parent_expansion, true, true, ident.span
990+
ident, MacroNS, Some(MacroKind::Attr), &parent_scope, true, true, ident.span
963991
).map(|(binding, _)| binding).ok();
964992

965993
if let Some(binding) = resolve_legacy(self).or_else(|| resolve_modern(self)) {

src/librustdoc/passes/collect_intra_doc_links.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -398,12 +398,12 @@ impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for LinkCollector<'a, 'tcx, 'rcx, 'cstor
398398
/// Resolve a string as a macro
399399
fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
400400
use syntax::ext::base::{MacroKind, SyntaxExtension};
401-
use syntax::ext::hygiene::Mark;
402401
let segment = ast::PathSegment::from_ident(Ident::from_str(path_str));
403402
let path = ast::Path { segments: vec![segment], span: DUMMY_SP };
404403
let mut resolver = cx.resolver.borrow_mut();
405-
let mark = Mark::root();
406-
if let Ok(def) = resolver.resolve_macro_to_def_inner(&path, MacroKind::Bang, mark, &[], false) {
404+
let parent_scope = resolver.dummy_parent_scope();
405+
if let Ok(def) = resolver.resolve_macro_to_def_inner(&path, MacroKind::Bang,
406+
&parent_scope, false) {
407407
if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) {
408408
return Some(def);
409409
}

0 commit comments

Comments
 (0)