Skip to content

Commit bcc0707

Browse files
committed
Auto merge of #52234 - petrochenkov:macuse2, r=<try>
[Experiment] resolve: Modularize crate-local `#[macro_export] macro_rules` Based on #50911, cc #50911 (comment) `#[macro_export] macro_rules` items are collected from the whole crate and are planted into the root module as items, so the external view of the crate is symmetric with its internal view and something like `$crate::my_macro` where `my_macro` is `#[macro_export] macro_rules` works both locally and from other crates.
2 parents e5f6498 + ee16ce1 commit bcc0707

File tree

59 files changed

+461
-322
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+461
-322
lines changed

src/doc/unstable-book/src/language-features/proc-macro.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ The two new procedural macro kinds are:
1717
* Attribute-like procedural macros which can be applied to any item which built-in attributes can
1818
be applied to, and which can take arguments in their invocation as well.
1919

20-
Additionally, this feature flag implicitly enables the [`use_extern_macros`](language-features/use-extern-macros.html) feature,
21-
which allows macros to be imported like any other item with `use` statements, as compared to
20+
Procedural macros can be imported like any other item with `use` statements, as compared to
2221
applying `#[macro_use]` to an `extern crate` declaration. It is important to note that procedural macros may
2322
**only** be imported in this manner, and will throw an error otherwise.
2423

src/librustc_resolve/build_reduced_graph.rs

+17-10
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) {
5252
vis: self.1,
5353
span: self.2,
5454
expansion: self.3,
55+
is_macro_export: false,
5556
})
5657
}
5758
}
@@ -63,6 +64,19 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) {
6364
vis: self.1,
6465
span: self.2,
6566
expansion: self.3,
67+
is_macro_export: false,
68+
})
69+
}
70+
}
71+
72+
impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark, bool) {
73+
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
74+
arenas.alloc_name_binding(NameBinding {
75+
kind: NameBindingKind::Def(self.0),
76+
vis: self.1,
77+
span: self.2,
78+
expansion: self.3,
79+
is_macro_export: self.4,
6680
})
6781
}
6882
}
@@ -641,19 +655,12 @@ impl<'a> Resolver<'a> {
641655
-> bool {
642656
let allow_shadowing = expansion == Mark::root();
643657
let legacy_imports = self.legacy_macro_imports(&item.attrs);
644-
let mut used = legacy_imports != LegacyMacroImports::default();
658+
let used = legacy_imports != LegacyMacroImports::default();
645659

646660
// `#[macro_use]` is only allowed at the crate root.
647661
if self.current_module.parent.is_some() && used {
648662
span_err!(self.session, item.span, E0468,
649663
"an `extern crate` loading macros must be at the crate root");
650-
} else if !self.use_extern_macros && !used &&
651-
self.cstore.dep_kind_untracked(module.def_id().unwrap().krate)
652-
.macros_only() {
653-
let msg = "proc macro crates and `#[no_link]` crates have no effect without \
654-
`#[macro_use]`";
655-
self.session.span_warn(item.span, msg);
656-
used = true; // Avoid the normal unused extern crate warning
657664
}
658665

659666
let (graph_root, arenas) = (self.graph_root, self.arenas);
@@ -681,8 +688,7 @@ impl<'a> Resolver<'a> {
681688
} else {
682689
for (name, span) in legacy_imports.imports {
683690
let ident = Ident::with_empty_ctxt(name);
684-
let result = self.resolve_ident_in_module(module, ident, MacroNS,
685-
false, false, span);
691+
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, span);
686692
if let Ok(binding) = result {
687693
let directive = macro_use_directive(span);
688694
self.potentially_unused_imports.push(directive);
@@ -750,6 +756,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
750756
fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
751757
let mark = id.placeholder_to_mark();
752758
self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark);
759+
self.resolver.unresolved_invocations_macro_export.insert(mark);
753760
let invocation = self.resolver.invocations[&mark];
754761
invocation.module.set(self.resolver.current_module);
755762
invocation.legacy_scope.set(self.legacy_scope);

src/librustc_resolve/lib.rs

+24-21
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,7 @@ impl<'a> fmt::Debug for ModuleData<'a> {
11001100
pub struct NameBinding<'a> {
11011101
kind: NameBindingKind<'a>,
11021102
expansion: Mark,
1103+
is_macro_export: bool,
11031104
span: Span,
11041105
vis: ty::Visibility,
11051106
}
@@ -1141,12 +1142,20 @@ struct UseError<'a> {
11411142
better: bool,
11421143
}
11431144

1145+
#[derive(Clone, Copy, Debug)]
1146+
enum AmbiguityErrorKind {
1147+
RecordUse,
1148+
ResolveLexical,
1149+
ResolveInModule,
1150+
}
1151+
11441152
struct AmbiguityError<'a> {
11451153
span: Span,
11461154
name: Name,
11471155
lexical: bool,
11481156
b1: &'a NameBinding<'a>,
11491157
b2: &'a NameBinding<'a>,
1158+
kind: AmbiguityErrorKind,
11501159
}
11511160

11521161
impl<'a> NameBinding<'a> {
@@ -1380,13 +1389,10 @@ pub struct Resolver<'a> {
13801389
/// `use` injections for proc macros wrongly imported with #[macro_use]
13811390
proc_mac_errors: Vec<macros::ProcMacError>,
13821391

1383-
gated_errors: FxHashSet<Span>,
13841392
disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
13851393

13861394
arenas: &'a ResolverArenas<'a>,
13871395
dummy_binding: &'a NameBinding<'a>,
1388-
/// true if `#![feature(use_extern_macros)]`
1389-
use_extern_macros: bool,
13901396

13911397
crate_loader: &'a mut CrateLoader,
13921398
macro_names: FxHashSet<Ident>,
@@ -1396,7 +1402,6 @@ pub struct Resolver<'a> {
13961402
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
13971403
macro_defs: FxHashMap<Mark, DefId>,
13981404
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
1399-
macro_exports: Vec<Export>,
14001405
pub whitelisted_legacy_custom_derives: Vec<Name>,
14011406
pub found_unresolved_macro: bool,
14021407

@@ -1429,6 +1434,9 @@ pub struct Resolver<'a> {
14291434

14301435
/// Only supposed to be used by rustdoc, otherwise should be false.
14311436
pub ignore_extern_prelude_feature: bool,
1437+
1438+
/// Macro invocations in the whole crate that can expand into a `#[macro_export] macro_rules`.
1439+
unresolved_invocations_macro_export: FxHashSet<Mark>,
14321440
}
14331441

14341442
/// Nothing really interesting here, it just provides memory for the rest of the crate.
@@ -1698,7 +1706,6 @@ impl<'a> Resolver<'a> {
16981706
ambiguity_errors: Vec::new(),
16991707
use_injections: Vec::new(),
17001708
proc_mac_errors: Vec::new(),
1701-
gated_errors: FxHashSet(),
17021709
disallowed_shadowing: Vec::new(),
17031710

17041711
arenas,
@@ -1707,19 +1714,15 @@ impl<'a> Resolver<'a> {
17071714
expansion: Mark::root(),
17081715
span: DUMMY_SP,
17091716
vis: ty::Visibility::Public,
1717+
is_macro_export: false,
17101718
}),
17111719

1712-
// The `proc_macro` and `decl_macro` features imply `use_extern_macros`
1713-
use_extern_macros:
1714-
features.use_extern_macros || features.proc_macro || features.decl_macro,
1715-
17161720
crate_loader,
17171721
macro_names: FxHashSet(),
17181722
global_macros: FxHashMap(),
17191723
all_macros: FxHashMap(),
17201724
lexical_macro_resolutions: Vec::new(),
17211725
macro_map: FxHashMap(),
1722-
macro_exports: Vec::new(),
17231726
invocations,
17241727
macro_defs,
17251728
local_macro_def_scopes: FxHashMap(),
@@ -1734,6 +1737,7 @@ impl<'a> Resolver<'a> {
17341737
current_type_ascription: Vec::new(),
17351738
injected_crate: None,
17361739
ignore_extern_prelude_feature: false,
1740+
unresolved_invocations_macro_export: FxHashSet(),
17371741
}
17381742
}
17391743

@@ -1753,9 +1757,7 @@ impl<'a> Resolver<'a> {
17531757
fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
17541758
f(self, TypeNS);
17551759
f(self, ValueNS);
1756-
if self.use_extern_macros {
1757-
f(self, MacroNS);
1758-
}
1760+
f(self, MacroNS);
17591761
}
17601762

17611763
fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
@@ -1807,6 +1809,7 @@ impl<'a> Resolver<'a> {
18071809
NameBindingKind::Ambiguity { b1, b2 } => {
18081810
self.ambiguity_errors.push(AmbiguityError {
18091811
span, name: ident.name, lexical: false, b1, b2,
1812+
kind: AmbiguityErrorKind::RecordUse
18101813
});
18111814
true
18121815
}
@@ -1967,7 +1970,6 @@ impl<'a> Resolver<'a> {
19671970
module: Module<'a>,
19681971
mut ident: Ident,
19691972
ns: Namespace,
1970-
ignore_unresolved_invocations: bool,
19711973
record_used: bool,
19721974
span: Span)
19731975
-> Result<&'a NameBinding<'a>, Determinacy> {
@@ -1977,7 +1979,7 @@ impl<'a> Resolver<'a> {
19771979
self.current_module = self.macro_def_scope(def);
19781980
}
19791981
let result = self.resolve_ident_in_module_unadjusted(
1980-
module, ident, ns, ignore_unresolved_invocations, record_used, span,
1982+
module, ident, ns, false, record_used, span,
19811983
);
19821984
self.current_module = orig_current_module;
19831985
result
@@ -2470,7 +2472,7 @@ impl<'a> Resolver<'a> {
24702472
// If there is a TraitRef in scope for an impl, then the method must be in the
24712473
// trait.
24722474
if let Some((module, _)) = self.current_trait_ref {
2473-
if self.resolve_ident_in_module(module, ident, ns, false, false, span).is_err() {
2475+
if self.resolve_ident_in_module(module, ident, ns, false, span).is_err() {
24742476
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
24752477
resolve_error(self, span, err(ident.name, &path_names_to_string(path)));
24762478
}
@@ -3420,7 +3422,7 @@ impl<'a> Resolver<'a> {
34203422
}
34213423

34223424
let binding = if let Some(module) = module {
3423-
self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span)
3425+
self.resolve_ident_in_module(module, ident, ns, record_used, path_span)
34243426
} else if opt_ns == Some(MacroNS) {
34253427
self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span)
34263428
.map(MacroBinding::binding)
@@ -3714,7 +3716,7 @@ impl<'a> Resolver<'a> {
37143716
// Look for associated items in the current trait.
37153717
if let Some((module, _)) = self.current_trait_ref {
37163718
if let Ok(binding) =
3717-
self.resolve_ident_in_module(module, ident, ns, false, false, module.span) {
3719+
self.resolve_ident_in_module(module, ident, ns, false, module.span) {
37183720
let def = binding.def();
37193721
if filter_fn(def) {
37203722
return Some(if self.has_self.contains(&def.def_id()) {
@@ -4027,7 +4029,7 @@ impl<'a> Resolver<'a> {
40274029
let mut found_traits = Vec::new();
40284030
// Look for the current trait.
40294031
if let Some((module, _)) = self.current_trait_ref {
4030-
if self.resolve_ident_in_module(module, ident, ns, false, false, module.span).is_ok() {
4032+
if self.resolve_ident_in_module(module, ident, ns, false, module.span).is_ok() {
40314033
let def_id = module.def_id().unwrap();
40324034
found_traits.push(TraitCandidate { def_id: def_id, import_id: None });
40334035
}
@@ -4300,7 +4302,7 @@ impl<'a> Resolver<'a> {
43004302
self.report_proc_macro_import(krate);
43014303
let mut reported_spans = FxHashSet();
43024304

4303-
for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors {
4305+
for &AmbiguityError { span, name, b1, b2, lexical, kind } in &self.ambiguity_errors {
43044306
if !reported_spans.insert(span) { continue }
43054307
let participle = |binding: &NameBinding| {
43064308
if binding.is_import() { "imported" } else { "defined" }
@@ -4317,7 +4319,8 @@ impl<'a> Resolver<'a> {
43174319
if b1.is_import() { "imports" } else { "items" })
43184320
};
43194321

4320-
let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name);
4322+
let mut err = struct_span_err!(self.session, span, E0659,
4323+
"`{}` is ambiguous {:?}", name, kind);
43214324
err.span_note(b1.span, &msg1);
43224325
match b2.def() {
43234326
Def::Macro(..) if b2.span.is_dummy() =>

0 commit comments

Comments
 (0)