Skip to content

Commit ee8491e

Browse files
committed
resolve: Model resolve_legacy_scope after resolve_lexical_macro_path_segment
1 parent 181804a commit ee8491e

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>,
@@ -1714,7 +1712,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
17141712
ambiguity_errors: Vec::new(),
17151713
use_injections: Vec::new(),
17161714
proc_mac_errors: Vec::new(),
1717-
disallowed_shadowing: Vec::new(),
17181715
macro_expanded_macro_export_errors: BTreeSet::new(),
17191716

17201717
arenas,
@@ -4532,7 +4529,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
45324529
}
45334530

45344531
fn report_errors(&mut self, krate: &Crate) {
4535-
self.report_shadowing_errors();
45364532
self.report_with_use_injections(krate);
45374533
self.report_proc_macro_import(krate);
45384534
let mut reported_spans = FxHashSet();
@@ -4570,20 +4566,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
45704566
}
45714567
}
45724568

4573-
fn report_shadowing_errors(&mut self) {
4574-
let mut reported_errors = FxHashSet();
4575-
for binding in replace(&mut self.disallowed_shadowing, Vec::new()) {
4576-
if self.resolve_legacy_scope(&binding.parent, binding.ident, false).is_some() &&
4577-
reported_errors.insert((binding.ident, binding.binding.span)) {
4578-
let msg = format!("`{}` is already in scope", binding.ident);
4579-
self.session.struct_span_err(binding.binding.span, &msg)
4580-
.note("macro-expanded `macro_rules!`s may not shadow \
4581-
existing macros (see RFC 1560)")
4582-
.emit();
4583-
}
4584-
}
4585-
}
4586-
45874569
fn report_conflict<'b>(&mut self,
45884570
parent: Module,
45894571
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 {
@@ -761,42 +761,101 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
761761
}
762762
}
763763

764-
crate fn resolve_legacy_scope(&mut self,
765-
mut scope: &'a Cell<LegacyScope<'a>>,
766-
ident: Ident,
767-
record_used: bool)
768-
-> Option<(&'a NameBinding<'a>, FromExpansion)> {
764+
fn resolve_legacy_scope(&mut self,
765+
scope: &'a Cell<LegacyScope<'a>>,
766+
ident: Ident,
767+
record_used: bool)
768+
-> Option<(&'a NameBinding<'a>, FromExpansion)> {
769769
let ident = ident.modern();
770-
let mut relative_depth: u32 = 0;
770+
771+
// Names from inner scope that can't shadow names from outer scopes, e.g.
772+
// macro_rules! mac { ... }
773+
// {
774+
// define_mac!(); // if this generates another `macro_rules! mac`, then it can't shadow
775+
// // the outer `mac` and we have and ambiguity error
776+
// mac!();
777+
// }
778+
let mut potentially_ambiguous_result: Option<(&NameBinding, FromExpansion)> = None;
779+
780+
// Go through all the scopes and try to resolve the name.
781+
let mut where_to_resolve = scope;
782+
let mut relative_depth = 0u32;
771783
loop {
772-
match scope.get() {
773-
LegacyScope::Empty => break,
774-
LegacyScope::Expansion(invocation) => {
775-
match invocation.expansion.get() {
776-
LegacyScope::Invocation(_) => scope.set(invocation.legacy_scope.get()),
777-
LegacyScope::Empty => {
778-
scope = &invocation.legacy_scope;
779-
}
780-
_ => {
784+
let result = match where_to_resolve.get() {
785+
LegacyScope::Binding(legacy_binding) => if ident == legacy_binding.ident {
786+
Some((legacy_binding.binding, FromExpansion(relative_depth > 0)))
787+
} else {
788+
None
789+
}
790+
_ => None,
791+
};
792+
793+
macro_rules! continue_search { () => {
794+
where_to_resolve = match where_to_resolve.get() {
795+
LegacyScope::Binding(binding) => &binding.parent,
796+
LegacyScope::Invocation(invocation) => {
797+
relative_depth = relative_depth.saturating_sub(1);
798+
&invocation.legacy_scope
799+
}
800+
LegacyScope::Expansion(invocation) => match invocation.expansion.get() {
801+
LegacyScope::Empty => &invocation.legacy_scope,
802+
LegacyScope::Binding(..) | LegacyScope::Expansion(..) => {
781803
relative_depth += 1;
782-
scope = &invocation.expansion;
804+
&invocation.expansion
805+
}
806+
LegacyScope::Invocation(..) => {
807+
where_to_resolve.set(invocation.legacy_scope.get());
808+
where_to_resolve
783809
}
784810
}
785-
}
786-
LegacyScope::Invocation(invocation) => {
787-
relative_depth = relative_depth.saturating_sub(1);
788-
scope = &invocation.legacy_scope;
789-
}
790-
LegacyScope::Binding(potential_binding) => {
791-
if potential_binding.ident == ident {
792-
if record_used && relative_depth > 0 {
793-
self.disallowed_shadowing.push(potential_binding);
811+
LegacyScope::Empty => break, // nowhere else to search
812+
};
813+
814+
continue;
815+
}}
816+
817+
match result {
818+
Some(result) => {
819+
if !record_used {
820+
return Some(result);
821+
}
822+
823+
// Found a solution that is ambiguous with a previously found solution.
824+
// Push an ambiguity error for later reporting and
825+
// return something for better recovery.
826+
if let Some(previous_result) = potentially_ambiguous_result {
827+
if result.0.def() != previous_result.0.def() {
828+
self.ambiguity_errors.push(AmbiguityError {
829+
span: ident.span,
830+
name: ident.name,
831+
b1: previous_result.0,
832+
b2: result.0,
833+
});
834+
return Some(previous_result);
794835
}
795-
return Some((potential_binding.binding, FromExpansion(relative_depth > 0)));
796836
}
797-
scope = &potential_binding.parent;
837+
838+
// Found a solution that's not an ambiguity yet, but is "suspicious" and
839+
// can participate in ambiguities later on.
840+
// Remember it and go search for other solutions in outer scopes.
841+
if (result.1).0 {
842+
potentially_ambiguous_result = Some(result);
843+
844+
continue_search!();
845+
}
846+
847+
// Found a solution that can't be ambiguous.
848+
return Some(result);
798849
}
799-
};
850+
None => {
851+
continue_search!();
852+
}
853+
}
854+
}
855+
856+
// Previously found potentially ambiguous result turned out to not be ambiguous after all.
857+
if let Some(previous_result) = potentially_ambiguous_result {
858+
return Some(previous_result);
800859
}
801860

802861
None
@@ -823,8 +882,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
823882

824883
let check_consistency = |this: &Self, new_def: Def| {
825884
if let Some(def) = def {
826-
if this.ambiguity_errors.is_empty() && this.disallowed_shadowing.is_empty() &&
827-
new_def != def && new_def != Def::Err {
885+
if this.ambiguity_errors.is_empty() && new_def != def && new_def != Def::Err {
828886
// Make sure compilation does not succeed if preferred macro resolution
829887
// has changed after the macro had been expanded. In theory all such
830888
// 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)