Skip to content

Commit dd0a766

Browse files
committed
Prohibit using macro-expanded macro_export macros through module-relative paths
1 parent e7ee6fb commit dd0a766

File tree

7 files changed

+98
-11
lines changed

7 files changed

+98
-11
lines changed

src/librustc_resolve/build_reduced_graph.rs

-1
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,6 @@ impl<'a, 'b, 'cl> BuildReducedGraphVisitor<'a, 'b, 'cl> {
789789
fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
790790
let mark = id.placeholder_to_mark();
791791
self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark);
792-
self.resolver.unresolved_invocations_macro_export.insert(mark);
793792
let invocation = self.resolver.invocations[&mark];
794793
invocation.module.set(self.resolver.current_module);
795794
invocation.legacy_scope.set(self.legacy_scope);

src/librustc_resolve/lib.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,8 @@ pub struct Resolver<'a, 'b: 'a> {
13851385
use_injections: Vec<UseError<'a>>,
13861386
/// `use` injections for proc macros wrongly imported with #[macro_use]
13871387
proc_mac_errors: Vec<macros::ProcMacError>,
1388+
/// crate-local macro expanded `macro_export` referred to by a module-relative path
1389+
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
13881390

13891391
gated_errors: FxHashSet<Span>,
13901392
disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
@@ -1432,9 +1434,6 @@ pub struct Resolver<'a, 'b: 'a> {
14321434

14331435
/// Only supposed to be used by rustdoc, otherwise should be false.
14341436
pub ignore_extern_prelude_feature: bool,
1435-
1436-
/// Macro invocations in the whole crate that can expand into a `#[macro_export] macro_rules`.
1437-
unresolved_invocations_macro_export: FxHashSet<Mark>,
14381437
}
14391438

14401439
/// Nothing really interesting here, it just provides memory for the rest of the crate.
@@ -1706,6 +1705,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
17061705
proc_mac_errors: Vec::new(),
17071706
gated_errors: FxHashSet(),
17081707
disallowed_shadowing: Vec::new(),
1708+
macro_expanded_macro_export_errors: BTreeSet::new(),
17091709

17101710
arenas,
17111711
dummy_binding: arenas.alloc_name_binding(NameBinding {
@@ -1737,7 +1737,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
17371737
current_type_ascription: Vec::new(),
17381738
injected_crate: None,
17391739
ignore_extern_prelude_feature: false,
1740-
unresolved_invocations_macro_export: FxHashSet(),
17411740
}
17421741
}
17431742

@@ -4126,6 +4125,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
41264125
ns: Namespace,
41274126
module: Module<'a>,
41284127
found_traits: &mut Vec<TraitCandidate>) {
4128+
assert!(ns == TypeNS || ns == ValueNS);
41294129
let mut traits = module.traits.borrow_mut();
41304130
if traits.is_none() {
41314131
let mut collected_traits = Vec::new();
@@ -4371,6 +4371,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
43714371
self.report_proc_macro_import(krate);
43724372
let mut reported_spans = FxHashSet();
43734373

4374+
for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
4375+
let msg = "macro-expanded `macro_export` macros from the current crate \
4376+
cannot be referred to by absolute paths";
4377+
self.session.struct_span_err(span_use, msg)
4378+
.span_note(span_def, "the macro is defined here")
4379+
.emit();
4380+
}
4381+
43744382
for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors {
43754383
if !reported_spans.insert(span) { continue }
43764384
let participle = |binding: &NameBinding| {

src/librustc_resolve/macros.rs

-2
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
196196

197197
self.current_module = invocation.module.get();
198198
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
199-
self.unresolved_invocations_macro_export.remove(&mark);
200199
self.current_module.unresolved_invocations.borrow_mut().extend(derives);
201-
self.unresolved_invocations_macro_export.extend(derives);
202200
for &derive in derives {
203201
self.invocations.insert(derive, invocation);
204202
}

src/librustc_resolve/resolve_imports.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,14 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
146146
.try_borrow_mut()
147147
.map_err(|_| Determined)?; // This happens when there is a cycle of imports
148148

149+
if let Some(binding) = resolution.binding {
150+
if !restricted_shadowing && binding.expansion != Mark::root() {
151+
if let NameBindingKind::Def(_, true) = binding.kind {
152+
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
153+
}
154+
}
155+
}
156+
149157
if record_used {
150158
if let Some(binding) = resolution.binding {
151159
if let Some(shadowed_glob) = resolution.shadowed_glob {
@@ -211,9 +219,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
211219
// if it cannot be shadowed by some new item/import expanded from a macro.
212220
// This happens either if there are no unexpanded macros, or expanded names cannot
213221
// shadow globs (that happens in macro namespace or with restricted shadowing).
214-
let unexpanded_macros = !module.unresolved_invocations.borrow().is_empty() ||
215-
(ns == MacroNS && ptr::eq(module, self.graph_root) &&
216-
!self.unresolved_invocations_macro_export.is_empty());
222+
//
223+
// Additionally, any macro in any module can plant names in the root module if it creates
224+
// `macro_export` macros, so the root module effectively has unresolved invocations if any
225+
// module has unresolved invocations.
226+
// However, it causes resolution/expansion to stuck too often (#53144), so, to make
227+
// progress, we have to ignore those potential unresolved invocations from other modules
228+
// and prohibit access to macro-expanded `macro_export` macros instead (unless restricted
229+
// shadowing is enabled, see `macro_expanded_macro_export_errors`).
230+
let unexpanded_macros = !module.unresolved_invocations.borrow().is_empty();
217231
if let Some(binding) = resolution.binding {
218232
if !unexpanded_macros || ns == MacroNS || restricted_shadowing {
219233
return check_usable(self, binding);

src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ extern crate derive_b;
2121
#[C] //~ ERROR: The attribute `C` is currently unknown to the compiler
2222
#[B(D)]
2323
#[B(E = "foo")]
24-
#[B arbitrary tokens] //~ expected one of `(` or `=`, found `arbitrary`
24+
#[B arbitrary tokens] //~ ERROR arbitrary tokens in non-macro attributes are unstable
2525
struct B;
2626

2727
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Crate-local macro expanded `macro_export` macros cannot be accessed with module-relative paths.
12+
13+
#![feature(use_extern_macros)]
14+
15+
macro_rules! define_exported { () => {
16+
#[macro_export]
17+
macro_rules! exported {
18+
() => ()
19+
}
20+
}}
21+
22+
define_exported!();
23+
24+
mod m {
25+
use exported;
26+
//~^ ERROR macro-expanded `macro_export` macros from the current crate cannot
27+
}
28+
29+
fn main() {
30+
::exported!();
31+
//~^ ERROR macro-expanded `macro_export` macros from the current crate cannot
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
2+
--> $DIR/local-modularized-tricky-fail-3.rs:25:9
3+
|
4+
LL | use exported;
5+
| ^^^^^^^^
6+
|
7+
note: the macro is defined here
8+
--> $DIR/local-modularized-tricky-fail-3.rs:17:5
9+
|
10+
LL | / macro_rules! exported {
11+
LL | | () => ()
12+
LL | | }
13+
| |_____^
14+
...
15+
LL | define_exported!();
16+
| ------------------- in this macro invocation
17+
18+
error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
19+
--> $DIR/local-modularized-tricky-fail-3.rs:30:5
20+
|
21+
LL | ::exported!();
22+
| ^^^^^^^^^^
23+
|
24+
note: the macro is defined here
25+
--> $DIR/local-modularized-tricky-fail-3.rs:17:5
26+
|
27+
LL | / macro_rules! exported {
28+
LL | | () => ()
29+
LL | | }
30+
| |_____^
31+
...
32+
LL | define_exported!();
33+
| ------------------- in this macro invocation
34+
35+
error: aborting due to 2 previous errors
36+

0 commit comments

Comments
 (0)