Skip to content

Commit 83a51de

Browse files
committed
resolve: Model resolve_legacy_scope after resolve_lexical_macro_path_segment
1 parent 4e5e045 commit 83a51de

File tree

6 files changed

+121
-60
lines changed

6 files changed

+121
-60
lines changed

src/librustc_resolve/lib.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,8 +1402,6 @@ pub struct Resolver<'a, 'b: 'a> {
14021402
proc_mac_errors: Vec<macros::ProcMacError>,
14031403
/// crate-local macro expanded `macro_export` referred to by a module-relative path
14041404
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
1405-
/// macro-expanded `macro_rules` shadowing existing macros
1406-
disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
14071405

14081406
arenas: &'a ResolverArenas<'a>,
14091407
dummy_binding: &'a NameBinding<'a>,
@@ -1715,7 +1713,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
17151713
ambiguity_errors: Vec::new(),
17161714
use_injections: Vec::new(),
17171715
proc_mac_errors: Vec::new(),
1718-
disallowed_shadowing: Vec::new(),
17191716
macro_expanded_macro_export_errors: BTreeSet::new(),
17201717

17211718
arenas,
@@ -4534,7 +4531,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
45344531
}
45354532

45364533
fn report_errors(&mut self, krate: &Crate) {
4537-
self.report_shadowing_errors();
45384534
self.report_with_use_injections(krate);
45394535
self.report_proc_macro_import(krate);
45404536
let mut reported_spans = FxHashSet();
@@ -4572,20 +4568,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
45724568
}
45734569
}
45744570

4575-
fn report_shadowing_errors(&mut self) {
4576-
let mut reported_errors = FxHashSet();
4577-
for binding in replace(&mut self.disallowed_shadowing, Vec::new()) {
4578-
if self.resolve_legacy_scope(&binding.parent, binding.ident, false).is_some() &&
4579-
reported_errors.insert((binding.ident, binding.binding.span)) {
4580-
let msg = format!("`{}` is already in scope", binding.ident);
4581-
self.session.struct_span_err(binding.binding.span, &msg)
4582-
.note("macro-expanded `macro_rules!`s may not shadow \
4583-
existing macros (see RFC 1560)")
4584-
.emit();
4585-
}
4586-
}
4587-
}
4588-
45894571
fn report_conflict<'b>(&mut self,
45904572
parent: Module,
45914573
ident: Ident,

src/librustc_resolve/macros.rs

Lines changed: 91 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ pub enum LegacyScope<'a> {
8181
// Binding produced by a `macro_rules` item.
8282
// Not modularized, can shadow previous legacy bindings, etc.
8383
pub struct LegacyBinding<'a> {
84-
pub binding: &'a NameBinding<'a>,
85-
pub parent: Cell<LegacyScope<'a>>,
86-
pub ident: Ident,
84+
binding: &'a NameBinding<'a>,
85+
parent: Cell<LegacyScope<'a>>,
86+
ident: Ident,
8787
}
8888

8989
pub struct ProcMacError {
@@ -784,42 +784,101 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
784784
}
785785
}
786786

787-
crate fn resolve_legacy_scope(&mut self,
788-
mut scope: &'a Cell<LegacyScope<'a>>,
789-
ident: Ident,
790-
record_used: bool)
791-
-> Option<(&'a NameBinding<'a>, FromExpansion)> {
787+
fn resolve_legacy_scope(&mut self,
788+
scope: &'a Cell<LegacyScope<'a>>,
789+
ident: Ident,
790+
record_used: bool)
791+
-> Option<(&'a NameBinding<'a>, FromExpansion)> {
792792
let ident = ident.modern();
793-
let mut relative_depth: u32 = 0;
793+
794+
// Names from inner scope that can't shadow names from outer scopes, e.g.
795+
// macro_rules! mac { ... }
796+
// {
797+
// define_mac!(); // if this generates another `macro_rules! mac`, then it can't shadow
798+
// // the outer `mac` and we have and ambiguity error
799+
// mac!();
800+
// }
801+
let mut potentially_ambiguous_result: Option<(&NameBinding, FromExpansion)> = None;
802+
803+
// Go through all the scopes and try to resolve the name.
804+
let mut where_to_resolve = scope;
805+
let mut relative_depth = 0u32;
794806
loop {
795-
match scope.get() {
796-
LegacyScope::Empty => break,
797-
LegacyScope::Expansion(invocation) => {
798-
match invocation.expansion.get() {
799-
LegacyScope::Invocation(_) => scope.set(invocation.legacy_scope.get()),
800-
LegacyScope::Empty => {
801-
scope = &invocation.legacy_scope;
802-
}
803-
_ => {
807+
let result = match where_to_resolve.get() {
808+
LegacyScope::Binding(legacy_binding) => if ident == legacy_binding.ident {
809+
Some((legacy_binding.binding, FromExpansion(relative_depth > 0)))
810+
} else {
811+
None
812+
}
813+
_ => None,
814+
};
815+
816+
macro_rules! continue_search { () => {
817+
where_to_resolve = match where_to_resolve.get() {
818+
LegacyScope::Binding(binding) => &binding.parent,
819+
LegacyScope::Invocation(invocation) => {
820+
relative_depth = relative_depth.saturating_sub(1);
821+
&invocation.legacy_scope
822+
}
823+
LegacyScope::Expansion(invocation) => match invocation.expansion.get() {
824+
LegacyScope::Empty => &invocation.legacy_scope,
825+
LegacyScope::Binding(..) | LegacyScope::Expansion(..) => {
804826
relative_depth += 1;
805-
scope = &invocation.expansion;
827+
&invocation.expansion
828+
}
829+
LegacyScope::Invocation(..) => {
830+
where_to_resolve.set(invocation.legacy_scope.get());
831+
where_to_resolve
806832
}
807833
}
808-
}
809-
LegacyScope::Invocation(invocation) => {
810-
relative_depth = relative_depth.saturating_sub(1);
811-
scope = &invocation.legacy_scope;
812-
}
813-
LegacyScope::Binding(potential_binding) => {
814-
if potential_binding.ident == ident {
815-
if record_used && relative_depth > 0 {
816-
self.disallowed_shadowing.push(potential_binding);
834+
LegacyScope::Empty => break, // nowhere else to search
835+
};
836+
837+
continue;
838+
}}
839+
840+
match result {
841+
Some(result) => {
842+
if !record_used {
843+
return Some(result);
844+
}
845+
846+
// Found a solution that is ambiguous with a previously found solution.
847+
// Push an ambiguity error for later reporting and
848+
// return something for better recovery.
849+
if let Some(previous_result) = potentially_ambiguous_result {
850+
if result.0.def() != previous_result.0.def() {
851+
self.ambiguity_errors.push(AmbiguityError {
852+
span: ident.span,
853+
name: ident.name,
854+
b1: previous_result.0,
855+
b2: result.0,
856+
});
857+
return Some(previous_result);
817858
}
818-
return Some((potential_binding.binding, FromExpansion(relative_depth > 0)));
819859
}
820-
scope = &potential_binding.parent;
860+
861+
// Found a solution that's not an ambiguity yet, but is "suspicious" and
862+
// can participate in ambiguities later on.
863+
// Remember it and go search for other solutions in outer scopes.
864+
if (result.1).0 {
865+
potentially_ambiguous_result = Some(result);
866+
867+
continue_search!();
868+
}
869+
870+
// Found a solution that can't be ambiguous.
871+
return Some(result);
821872
}
822-
};
873+
None => {
874+
continue_search!();
875+
}
876+
}
877+
}
878+
879+
// Previously found potentially ambiguous result turned out to not be ambiguous after all.
880+
if let Some(previous_result) = potentially_ambiguous_result {
881+
return Some(previous_result);
823882
}
824883

825884
None
@@ -846,8 +905,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
846905

847906
let check_consistency = |this: &Self, new_def: Def| {
848907
if let Some(def) = def {
849-
if this.ambiguity_errors.is_empty() && this.disallowed_shadowing.is_empty() &&
850-
new_def != def && new_def != Def::Err {
908+
if this.ambiguity_errors.is_empty() && new_def != def && new_def != Def::Err {
851909
// Make sure compilation does not succeed if preferred macro resolution
852910
// has changed after the macro had been expanded. In theory all such
853911
// situations should be reported as ambiguity errors, so this is span-bug.

src/test/ui/macros/macro-shadowing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ macro_rules! macro_one { () => {} }
1717
#[macro_use(macro_two)] extern crate two_macros;
1818

1919
macro_rules! m1 { () => {
20-
macro_rules! foo { () => {} } //~ ERROR `foo` is already in scope
20+
macro_rules! foo { () => {} }
2121

2222
#[macro_use] //~ ERROR `macro_two` is already in scope
2323
extern crate two_macros as __;
2424
}}
2525
m1!();
2626

27-
foo!();
27+
foo!(); //~ ERROR `foo` is ambiguous
2828

2929
macro_rules! m2 { () => {
3030
macro_rules! foo { () => {} }

src/test/ui/macros/macro-shadowing.stderr

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,27 @@ LL | m1!();
99
|
1010
= note: macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)
1111

12-
error: `foo` is already in scope
12+
error[E0659]: `foo` is ambiguous
13+
--> $DIR/macro-shadowing.rs:27:1
14+
|
15+
LL | foo!(); //~ ERROR `foo` is ambiguous
16+
| ^^^
17+
|
18+
note: `foo` could refer to the name defined here
1319
--> $DIR/macro-shadowing.rs:20:5
1420
|
15-
LL | macro_rules! foo { () => {} } //~ ERROR `foo` is already in scope
21+
LL | macro_rules! foo { () => {} }
1622
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1723
...
1824
LL | m1!();
1925
| ------ in this macro invocation
26+
note: `foo` could also refer to the name defined here
27+
--> $DIR/macro-shadowing.rs:15:1
2028
|
21-
= note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560)
29+
LL | macro_rules! foo { () => {} }
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31+
= note: macro-expanded macros do not shadow
2232

2333
error: aborting due to 2 previous errors
2434

35+
For more information about this error, try `rustc --explain E0659`.

src/test/ui/out-of-order-shadowing.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@
99
// except according to those terms.
1010

1111
// aux-build:define_macro.rs
12-
// error-pattern: `bar` is already in scope
1312

1413
macro_rules! bar { () => {} }
1514
define_macro!(bar);
16-
bar!();
15+
bar!(); //~ ERROR `bar` is ambiguous
1716

1817
macro_rules! m { () => { #[macro_use] extern crate define_macro; } }
1918
m!();
Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
1-
error: `bar` is already in scope
1+
error[E0659]: `bar` is ambiguous
22
--> $DIR/out-of-order-shadowing.rs:15:1
33
|
4+
LL | bar!(); //~ ERROR `bar` is ambiguous
5+
| ^^^
6+
|
7+
note: `bar` could refer to the name defined here
8+
--> $DIR/out-of-order-shadowing.rs:14:1
9+
|
410
LL | define_macro!(bar);
511
| ^^^^^^^^^^^^^^^^^^^
12+
note: `bar` could also refer to the name defined here
13+
--> $DIR/out-of-order-shadowing.rs:13:1
614
|
7-
= note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560)
15+
LL | macro_rules! bar { () => {} }
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
= note: macro-expanded macros do not shadow
818
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
919

1020
error: aborting due to previous error
1121

22+
For more information about this error, try `rustc --explain E0659`.

0 commit comments

Comments
 (0)