Skip to content

Commit 5806389

Browse files
committed
Auto merge of #53913 - petrochenkov:biattr4, r=alexcrichton
resolve: Future proof resolutions for potentially built-in attributes This is not full "pass all attributes through name resolution", but a more conservative solution. If built-in attribute is ambiguous with any other macro in scope, then an error is reported. What complications arise with the full solution - #53913 (comment). cc #50911 (comment) cc #52269 Closes #53531
2 parents 2f1547c + de153d6 commit 5806389

12 files changed

+353
-71
lines changed

src/librustc_resolve/build_reduced_graph.rs

+10
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use syntax::ext::base::{MacroKind, SyntaxExtension};
3939
use syntax::ext::base::Determinacy::Undetermined;
4040
use syntax::ext::hygiene::Mark;
4141
use syntax::ext::tt::macro_rules;
42+
use syntax::feature_gate::is_builtin_attr;
4243
use syntax::parse::token::{self, Token};
4344
use syntax::std_inject::injected_crate_name;
4445
use syntax::symbol::keywords;
@@ -1057,4 +1058,13 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> {
10571058
}
10581059
}
10591060
}
1061+
1062+
fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
1063+
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
1066+
));
1067+
}
1068+
visit::walk_attribute(self, attr);
1069+
}
10601070
}

src/librustc_resolve/lib.rs

+15-13
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,8 +1010,9 @@ 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)>>,
1015+
builtin_attrs: RefCell<Vec<(Ident, Mark, LegacyScope<'a>)>>,
10151016

10161017
// Macro invocations that can expand into items in this module.
10171018
unresolved_invocations: RefCell<FxHashSet<Mark>>,
@@ -1050,6 +1051,7 @@ impl<'a> ModuleData<'a> {
10501051
resolutions: RefCell::new(FxHashMap()),
10511052
legacy_macro_resolutions: RefCell::new(Vec::new()),
10521053
macro_resolutions: RefCell::new(Vec::new()),
1054+
builtin_attrs: RefCell::new(Vec::new()),
10531055
unresolved_invocations: RefCell::new(FxHashSet()),
10541056
no_implicit_prelude: false,
10551057
glob_importers: RefCell::new(Vec::new()),
@@ -1268,6 +1270,7 @@ impl<'a> NameBinding<'a> {
12681270
fn macro_kind(&self) -> Option<MacroKind> {
12691271
match self.def_ignoring_ambiguity() {
12701272
Def::Macro(_, kind) => Some(kind),
1273+
Def::NonMacroAttr(..) => Some(MacroKind::Attr),
12711274
_ => None,
12721275
}
12731276
}
@@ -1276,19 +1279,18 @@ impl<'a> NameBinding<'a> {
12761279
if self.is_extern_crate() { "extern crate" } else { self.def().kind_name() }
12771280
}
12781281

1279-
// Suppose that we resolved macro invocation with `invoc_id` to binding `binding` at some
1280-
// expansion round `max(invoc_id, binding)` when they both emerged from macros.
1282+
// Suppose that we resolved macro invocation with `invoc_parent_expansion` to binding `binding`
1283+
// at some expansion round `max(invoc, binding)` when they both emerged from macros.
12811284
// Then this function returns `true` if `self` may emerge from a macro *after* that
12821285
// in some later round and screw up our previously found resolution.
12831286
// See more detailed explanation in
12841287
// https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049
1285-
fn may_appear_after(&self, invoc_id: Mark, binding: &NameBinding) -> bool {
1286-
// self > max(invoc_id, binding) => !(self <= invoc_id || self <= binding)
1288+
fn may_appear_after(&self, invoc_parent_expansion: Mark, binding: &NameBinding) -> bool {
1289+
// self > max(invoc, binding) => !(self <= invoc || self <= binding)
12871290
// Expansions are partially ordered, so "may appear after" is an inversion of
12881291
// "certainly appears before or simultaneously" and includes unordered cases.
12891292
let self_parent_expansion = self.expansion;
12901293
let other_parent_expansion = binding.expansion;
1291-
let invoc_parent_expansion = invoc_id.parent();
12921294
let certainly_before_other_or_simultaneously =
12931295
other_parent_expansion.is_descendant_of(self_parent_expansion);
12941296
let certainly_before_invoc_or_simultaneously =
@@ -3493,16 +3495,16 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
34933495
path_span: Span,
34943496
crate_lint: CrateLint,
34953497
) -> PathResult<'a> {
3496-
self.resolve_path_with_invoc_id(base_module, path, opt_ns, Mark::root(),
3497-
record_used, path_span, crate_lint)
3498+
self.resolve_path_with_parent_expansion(base_module, path, opt_ns, Mark::root(),
3499+
record_used, path_span, crate_lint)
34983500
}
34993501

3500-
fn resolve_path_with_invoc_id(
3502+
fn resolve_path_with_parent_expansion(
35013503
&mut self,
35023504
base_module: Option<ModuleOrUniformRoot<'a>>,
35033505
path: &[Ident],
35043506
opt_ns: Option<Namespace>, // `None` indicates a module path
3505-
invoc_id: Mark,
3507+
parent_expansion: Mark,
35063508
record_used: bool,
35073509
path_span: Span,
35083510
crate_lint: CrateLint,
@@ -3595,8 +3597,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
35953597
self.resolve_ident_in_module(module, ident, ns, record_used, path_span)
35963598
} else if opt_ns == Some(MacroNS) {
35973599
assert!(ns == TypeNS);
3598-
self.resolve_lexical_macro_path_segment(ident, ns, invoc_id, record_used,
3599-
record_used, false, path_span)
3600+
self.resolve_lexical_macro_path_segment(ident, ns, None, parent_expansion,
3601+
record_used, record_used, path_span)
36003602
.map(|(binding, _)| binding)
36013603
} else {
36023604
let record_used_id =

0 commit comments

Comments
 (0)