Skip to content

Commit 634d886

Browse files
committed
resolve: Support resolving identifier macros without their own ID
Invocation/expansion ID (aka `Mark`) is not really necessary for resolving a macro path. What is really necessary is its parent module, parent expansion and parent legacy scope. This is required for validation resolutions of built-in attributes, which don't get their own `Mark`s
1 parent 66d02fa commit 634d886

File tree

3 files changed

+48
-46
lines changed

3 files changed

+48
-46
lines changed

src/librustc_resolve/lib.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ use std::mem::replace;
8181
use rustc_data_structures::sync::Lrc;
8282

8383
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
84-
use macros::{InvocationData, LegacyBinding};
84+
use macros::{InvocationData, LegacyBinding, LegacyScope};
8585

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

10121012
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
1013-
legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, MacroKind, Option<Def>)>>,
1013+
legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, Mark, LegacyScope<'a>, Option<Def>)>>,
10141014
macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
10151015

10161016
// Macro invocations that can expand into items in this module.
@@ -1270,17 +1270,16 @@ impl<'a> NameBinding<'a> {
12701270
if self.is_extern_crate() { "extern crate" } else { self.def().kind_name() }
12711271
}
12721272

1273-
// Suppose that we resolved macro invocation with `invoc_id` to binding `binding` at some
1274-
// expansion round `max(invoc_id, binding)` when they both emerged from macros.
1273+
// Suppose that we resolved macro invocation with `invoc_parent_expansion` to binding `binding`
1274+
// at some expansion round `max(invoc, binding)` when they both emerged from macros.
12751275
// Then this function returns `true` if `self` may emerge from a macro *after* that
12761276
// in some later round and screw up our previously found resolution.
1277-
fn may_appear_after(&self, invoc_id: Mark, binding: &NameBinding) -> bool {
1278-
// self > max(invoc_id, binding) => !(self <= invoc_id || self <= binding)
1277+
fn may_appear_after(&self, invoc_parent_expansion: Mark, binding: &NameBinding) -> bool {
1278+
// self > max(invoc, binding) => !(self <= invoc || self <= binding)
12791279
// Expansions are partially ordered, so "may appear after" is an inversion of
12801280
// "certainly appears before or simultaneously" and includes unordered cases.
12811281
let self_parent_expansion = self.expansion;
12821282
let other_parent_expansion = binding.expansion;
1283-
let invoc_parent_expansion = invoc_id.parent();
12841283
let certainly_before_other_or_simultaneously =
12851284
other_parent_expansion.is_descendant_of(self_parent_expansion);
12861285
let certainly_before_invoc_or_simultaneously =
@@ -3483,16 +3482,16 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
34833482
path_span: Span,
34843483
crate_lint: CrateLint,
34853484
) -> PathResult<'a> {
3486-
self.resolve_path_with_invoc_id(base_module, path, opt_ns, Mark::root(),
3487-
record_used, path_span, crate_lint)
3485+
self.resolve_path_with_parent_expansion(base_module, path, opt_ns, Mark::root(),
3486+
record_used, path_span, crate_lint)
34883487
}
34893488

3490-
fn resolve_path_with_invoc_id(
3489+
fn resolve_path_with_parent_expansion(
34913490
&mut self,
34923491
base_module: Option<ModuleOrUniformRoot<'a>>,
34933492
path: &[Ident],
34943493
opt_ns: Option<Namespace>, // `None` indicates a module path
3495-
invoc_id: Mark,
3494+
parent_expansion: Mark,
34963495
record_used: bool,
34973496
path_span: Span,
34983497
crate_lint: CrateLint,
@@ -3585,7 +3584,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
35853584
self.resolve_ident_in_module(module, ident, ns, record_used, path_span)
35863585
} else if opt_ns == Some(MacroNS) {
35873586
assert!(ns == TypeNS);
3588-
self.resolve_lexical_macro_path_segment(ident, ns, invoc_id, record_used,
3587+
self.resolve_lexical_macro_path_segment(ident, ns, parent_expansion, record_used,
35893588
record_used, false, path_span)
35903589
.map(|(binding, _)| binding)
35913590
} else {

src/librustc_resolve/macros.rs

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
309309
None
310310
}
311311

312-
fn resolve_macro_invocation(&mut self, invoc: &Invocation, scope: Mark, force: bool)
312+
fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
313313
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
314314
let (path, kind, derives_in_scope) = match invoc.kind {
315315
InvocationKind::Attr { attr: None, .. } =>
@@ -322,7 +322,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
322322
(path, MacroKind::Derive, &[][..]),
323323
};
324324

325-
let (def, ext) = self.resolve_macro_to_def(path, kind, scope, derives_in_scope, force)?;
325+
let (def, ext) = self.resolve_macro_to_def(path, kind, invoc_id, derives_in_scope, force)?;
326326

327327
if let Def::Macro(def_id, _) = def {
328328
self.macro_defs.insert(invoc.expansion_data.mark, def_id);
@@ -337,10 +337,10 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
337337
Ok(Some(ext))
338338
}
339339

340-
fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
340+
fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
341341
derives_in_scope: &[ast::Path], force: bool)
342342
-> Result<Lrc<SyntaxExtension>, Determinacy> {
343-
Ok(self.resolve_macro_to_def(path, kind, scope, derives_in_scope, force)?.1)
343+
Ok(self.resolve_macro_to_def(path, kind, invoc_id, derives_in_scope, force)?.1)
344344
}
345345

346346
fn check_unused_macros(&self) {
@@ -362,10 +362,10 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
362362
}
363363

364364
impl<'a, 'cl> Resolver<'a, 'cl> {
365-
fn resolve_macro_to_def(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
365+
fn resolve_macro_to_def(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
366366
derives_in_scope: &[ast::Path], force: bool)
367367
-> Result<(Def, Lrc<SyntaxExtension>), Determinacy> {
368-
let def = self.resolve_macro_to_def_inner(path, kind, scope, derives_in_scope, force);
368+
let def = self.resolve_macro_to_def_inner(path, kind, invoc_id, derives_in_scope, force);
369369

370370
// Report errors and enforce feature gates for the resolved macro.
371371
if def != Err(Determinacy::Undetermined) {
@@ -435,8 +435,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
435435
let ast::Path { ref segments, span } = *path;
436436
let mut path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
437437
let invocation = self.invocations[&invoc_id];
438-
let module = invocation.module.get();
439-
self.current_module = if module.is_trait() { module.parent.unwrap() } else { module };
438+
let parent_expansion = invoc_id.parent();
439+
let parent_legacy_scope = invocation.parent_legacy_scope.get();
440+
self.current_module = invocation.module.get().nearest_item_scope();
440441

441442
// Possibly apply the macro helper hack
442443
if kind == MacroKind::Bang && path.len() == 1 &&
@@ -446,8 +447,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
446447
}
447448

448449
if path.len() > 1 {
449-
let def = match self.resolve_path_with_invoc_id(None, &path, Some(MacroNS), invoc_id,
450-
false, span, CrateLint::No) {
450+
let def = match self.resolve_path_with_parent_expansion(None, &path, Some(MacroNS),
451+
parent_expansion, false, span,
452+
CrateLint::No) {
451453
PathResult::NonModule(path_res) => match path_res.base_def() {
452454
Def::Err => Err(Determinacy::Determined),
453455
def @ _ => {
@@ -467,19 +469,19 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
467469
Err(Determinacy::Determined)
468470
},
469471
};
470-
self.current_module.nearest_item_scope().macro_resolutions.borrow_mut()
472+
self.current_module.macro_resolutions.borrow_mut()
471473
.push((path.into_boxed_slice(), span));
472474
return def;
473475
}
474476

475477
let legacy_resolution = self.resolve_legacy_scope(
476-
path[0], invoc_id, invocation.parent_legacy_scope.get(), false
478+
path[0], parent_expansion, parent_legacy_scope, false
477479
);
478480
let result = if let Some(legacy_binding) = legacy_resolution {
479481
Ok(legacy_binding.def())
480482
} else {
481-
match self.resolve_lexical_macro_path_segment(path[0], MacroNS, invoc_id, false, force,
482-
kind == MacroKind::Attr, span) {
483+
match self.resolve_lexical_macro_path_segment(path[0], MacroNS, parent_expansion, false,
484+
force, kind == MacroKind::Attr, span) {
483485
Ok((binding, _)) => Ok(binding.def_ignoring_ambiguity()),
484486
Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
485487
Err(Determinacy::Determined) => {
@@ -489,8 +491,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
489491
}
490492
};
491493

492-
self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut()
493-
.push((invoc_id, path[0], kind, result.ok()));
494+
self.current_module.legacy_macro_resolutions.borrow_mut()
495+
.push((path[0], kind, parent_expansion, parent_legacy_scope, result.ok()));
494496

495497
if let Ok(Def::NonMacroAttr(NonMacroAttrKind::Custom)) = result {} else {
496498
return result;
@@ -537,7 +539,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
537539
&mut self,
538540
mut ident: Ident,
539541
ns: Namespace,
540-
invoc_id: Mark,
542+
parent_expansion: Mark,
541543
record_used: bool,
542544
force: bool,
543545
is_attr: bool,
@@ -732,7 +734,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
732734
// Found another solution, if the first one was "weak", report an error.
733735
if result.0.def() != innermost_result.0.def() &&
734736
(innermost_result.0.is_glob_import() ||
735-
innermost_result.0.may_appear_after(invoc_id, result.0)) {
737+
innermost_result.0.may_appear_after(parent_expansion, result.0)) {
736738
self.ambiguity_errors.push(AmbiguityError {
737739
span: path_span,
738740
name: ident.name,
@@ -777,8 +779,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
777779

778780
fn resolve_legacy_scope(&mut self,
779781
ident: Ident,
780-
invoc_id: Mark,
781-
invoc_parent_legacy_scope: LegacyScope<'a>,
782+
parent_expansion: Mark,
783+
parent_legacy_scope: LegacyScope<'a>,
782784
record_used: bool)
783785
-> Option<&'a NameBinding<'a>> {
784786
let ident = ident.modern();
@@ -797,7 +799,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
797799
let mut innermost_result: Option<&NameBinding> = None;
798800

799801
// Go through all the scopes and try to resolve the name.
800-
let mut where_to_resolve = invoc_parent_legacy_scope;
802+
let mut where_to_resolve = parent_legacy_scope;
801803
loop {
802804
let result = match where_to_resolve {
803805
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
@@ -825,7 +827,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
825827
if let Some(innermost_result) = innermost_result {
826828
// Found another solution, if the first one was "weak", report an error.
827829
if result.def() != innermost_result.def() &&
828-
innermost_result.may_appear_after(invoc_id, result) {
830+
innermost_result.may_appear_after(parent_expansion, result) {
829831
self.ambiguity_errors.push(AmbiguityError {
830832
span: ident.span,
831833
name: ident.name,
@@ -863,14 +865,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
863865
}
864866
}
865867

866-
for &(invoc_id, ident, kind, def) in module.legacy_macro_resolutions.borrow().iter() {
868+
for &(ident, kind, parent_expansion, parent_legacy_scope, def)
869+
in module.legacy_macro_resolutions.borrow().iter() {
867870
let span = ident.span;
868-
let invocation = self.invocations[&invoc_id];
869871
let legacy_resolution = self.resolve_legacy_scope(
870-
ident, invoc_id, invocation.parent_legacy_scope.get(), true
872+
ident, parent_expansion, parent_legacy_scope, true
871873
);
872874
let resolution = self.resolve_lexical_macro_path_segment(
873-
ident, MacroNS, invoc_id, true, true, kind == MacroKind::Attr, span
875+
ident, MacroNS, parent_expansion, true, true, kind == MacroKind::Attr, span
874876
);
875877

876878
let check_consistency = |this: &Self, new_def: Def| {
@@ -904,12 +906,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
904906
err.emit();
905907
},
906908
(Some(legacy_binding), Ok((binding, FromPrelude(from_prelude))))
907-
if !from_prelude || legacy_binding.may_appear_after(invoc_id, binding) => {
908-
if legacy_binding.def_ignoring_ambiguity() != binding.def_ignoring_ambiguity() {
909-
self.report_ambiguity_error(ident.name, span, legacy_binding, binding);
910-
}
909+
if legacy_binding.def() != binding.def_ignoring_ambiguity() &&
910+
(!from_prelude ||
911+
legacy_binding.may_appear_after(parent_expansion, binding)) => {
912+
self.report_ambiguity_error(ident.name, span, legacy_binding, binding);
911913
},
912914
// OK, non-macro-expanded legacy wins over prelude even if defs are different
915+
// Also, legacy and modern can co-exist if their defs are same
913916
(Some(legacy_binding), Ok(_)) |
914917
// OK, unambiguous resolution
915918
(Some(legacy_binding), Err(_)) => {

src/libsyntax/ext/base.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -727,9 +727,9 @@ pub trait Resolver {
727727
fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>, allow_derive: bool)
728728
-> Option<Attribute>;
729729

730-
fn resolve_macro_invocation(&mut self, invoc: &Invocation, scope: Mark, force: bool)
730+
fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
731731
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy>;
732-
fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
732+
fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
733733
derives_in_scope: &[ast::Path], force: bool)
734734
-> Result<Lrc<SyntaxExtension>, Determinacy>;
735735

@@ -763,11 +763,11 @@ impl Resolver for DummyResolver {
763763
fn resolve_imports(&mut self) {}
764764
fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>, _allow_derive: bool)
765765
-> Option<Attribute> { None }
766-
fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _scope: Mark, _force: bool)
766+
fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _invoc_id: Mark, _force: bool)
767767
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
768768
Err(Determinacy::Determined)
769769
}
770-
fn resolve_macro_path(&mut self, _path: &ast::Path, _kind: MacroKind, _scope: Mark,
770+
fn resolve_macro_path(&mut self, _path: &ast::Path, _kind: MacroKind, _invoc_id: Mark,
771771
_derives_in_scope: &[ast::Path], _force: bool)
772772
-> Result<Lrc<SyntaxExtension>, Determinacy> {
773773
Err(Determinacy::Determined)

0 commit comments

Comments
 (0)