mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 07:44:10 +00:00
resolve: Model resolve_legacy_scope
after resolve_lexical_macro_path_segment
This commit is contained in:
parent
4e5e045459
commit
83a51deef5
@ -1402,8 +1402,6 @@ pub struct Resolver<'a, 'b: 'a> {
|
||||
proc_mac_errors: Vec<macros::ProcMacError>,
|
||||
/// crate-local macro expanded `macro_export` referred to by a module-relative path
|
||||
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
|
||||
/// macro-expanded `macro_rules` shadowing existing macros
|
||||
disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
|
||||
|
||||
arenas: &'a ResolverArenas<'a>,
|
||||
dummy_binding: &'a NameBinding<'a>,
|
||||
@ -1715,7 +1713,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||
ambiguity_errors: Vec::new(),
|
||||
use_injections: Vec::new(),
|
||||
proc_mac_errors: Vec::new(),
|
||||
disallowed_shadowing: Vec::new(),
|
||||
macro_expanded_macro_export_errors: BTreeSet::new(),
|
||||
|
||||
arenas,
|
||||
@ -4534,7 +4531,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||
}
|
||||
|
||||
fn report_errors(&mut self, krate: &Crate) {
|
||||
self.report_shadowing_errors();
|
||||
self.report_with_use_injections(krate);
|
||||
self.report_proc_macro_import(krate);
|
||||
let mut reported_spans = FxHashSet();
|
||||
@ -4572,20 +4568,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||
}
|
||||
}
|
||||
|
||||
fn report_shadowing_errors(&mut self) {
|
||||
let mut reported_errors = FxHashSet();
|
||||
for binding in replace(&mut self.disallowed_shadowing, Vec::new()) {
|
||||
if self.resolve_legacy_scope(&binding.parent, binding.ident, false).is_some() &&
|
||||
reported_errors.insert((binding.ident, binding.binding.span)) {
|
||||
let msg = format!("`{}` is already in scope", binding.ident);
|
||||
self.session.struct_span_err(binding.binding.span, &msg)
|
||||
.note("macro-expanded `macro_rules!`s may not shadow \
|
||||
existing macros (see RFC 1560)")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn report_conflict<'b>(&mut self,
|
||||
parent: Module,
|
||||
ident: Ident,
|
||||
|
@ -81,9 +81,9 @@ pub enum LegacyScope<'a> {
|
||||
// Binding produced by a `macro_rules` item.
|
||||
// Not modularized, can shadow previous legacy bindings, etc.
|
||||
pub struct LegacyBinding<'a> {
|
||||
pub binding: &'a NameBinding<'a>,
|
||||
pub parent: Cell<LegacyScope<'a>>,
|
||||
pub ident: Ident,
|
||||
binding: &'a NameBinding<'a>,
|
||||
parent: Cell<LegacyScope<'a>>,
|
||||
ident: Ident,
|
||||
}
|
||||
|
||||
pub struct ProcMacError {
|
||||
@ -784,42 +784,101 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn resolve_legacy_scope(&mut self,
|
||||
mut scope: &'a Cell<LegacyScope<'a>>,
|
||||
ident: Ident,
|
||||
record_used: bool)
|
||||
-> Option<(&'a NameBinding<'a>, FromExpansion)> {
|
||||
fn resolve_legacy_scope(&mut self,
|
||||
scope: &'a Cell<LegacyScope<'a>>,
|
||||
ident: Ident,
|
||||
record_used: bool)
|
||||
-> Option<(&'a NameBinding<'a>, FromExpansion)> {
|
||||
let ident = ident.modern();
|
||||
let mut relative_depth: u32 = 0;
|
||||
|
||||
// Names from inner scope that can't shadow names from outer scopes, e.g.
|
||||
// macro_rules! mac { ... }
|
||||
// {
|
||||
// define_mac!(); // if this generates another `macro_rules! mac`, then it can't shadow
|
||||
// // the outer `mac` and we have and ambiguity error
|
||||
// mac!();
|
||||
// }
|
||||
let mut potentially_ambiguous_result: Option<(&NameBinding, FromExpansion)> = None;
|
||||
|
||||
// Go through all the scopes and try to resolve the name.
|
||||
let mut where_to_resolve = scope;
|
||||
let mut relative_depth = 0u32;
|
||||
loop {
|
||||
match scope.get() {
|
||||
LegacyScope::Empty => break,
|
||||
LegacyScope::Expansion(invocation) => {
|
||||
match invocation.expansion.get() {
|
||||
LegacyScope::Invocation(_) => scope.set(invocation.legacy_scope.get()),
|
||||
LegacyScope::Empty => {
|
||||
scope = &invocation.legacy_scope;
|
||||
}
|
||||
_ => {
|
||||
relative_depth += 1;
|
||||
scope = &invocation.expansion;
|
||||
}
|
||||
}
|
||||
}
|
||||
LegacyScope::Invocation(invocation) => {
|
||||
relative_depth = relative_depth.saturating_sub(1);
|
||||
scope = &invocation.legacy_scope;
|
||||
}
|
||||
LegacyScope::Binding(potential_binding) => {
|
||||
if potential_binding.ident == ident {
|
||||
if record_used && relative_depth > 0 {
|
||||
self.disallowed_shadowing.push(potential_binding);
|
||||
}
|
||||
return Some((potential_binding.binding, FromExpansion(relative_depth > 0)));
|
||||
}
|
||||
scope = &potential_binding.parent;
|
||||
let result = match where_to_resolve.get() {
|
||||
LegacyScope::Binding(legacy_binding) => if ident == legacy_binding.ident {
|
||||
Some((legacy_binding.binding, FromExpansion(relative_depth > 0)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
macro_rules! continue_search { () => {
|
||||
where_to_resolve = match where_to_resolve.get() {
|
||||
LegacyScope::Binding(binding) => &binding.parent,
|
||||
LegacyScope::Invocation(invocation) => {
|
||||
relative_depth = relative_depth.saturating_sub(1);
|
||||
&invocation.legacy_scope
|
||||
}
|
||||
LegacyScope::Expansion(invocation) => match invocation.expansion.get() {
|
||||
LegacyScope::Empty => &invocation.legacy_scope,
|
||||
LegacyScope::Binding(..) | LegacyScope::Expansion(..) => {
|
||||
relative_depth += 1;
|
||||
&invocation.expansion
|
||||
}
|
||||
LegacyScope::Invocation(..) => {
|
||||
where_to_resolve.set(invocation.legacy_scope.get());
|
||||
where_to_resolve
|
||||
}
|
||||
}
|
||||
LegacyScope::Empty => break, // nowhere else to search
|
||||
};
|
||||
|
||||
continue;
|
||||
}}
|
||||
|
||||
match result {
|
||||
Some(result) => {
|
||||
if !record_used {
|
||||
return Some(result);
|
||||
}
|
||||
|
||||
// Found a solution that is ambiguous with a previously found solution.
|
||||
// Push an ambiguity error for later reporting and
|
||||
// return something for better recovery.
|
||||
if let Some(previous_result) = potentially_ambiguous_result {
|
||||
if result.0.def() != previous_result.0.def() {
|
||||
self.ambiguity_errors.push(AmbiguityError {
|
||||
span: ident.span,
|
||||
name: ident.name,
|
||||
b1: previous_result.0,
|
||||
b2: result.0,
|
||||
});
|
||||
return Some(previous_result);
|
||||
}
|
||||
}
|
||||
|
||||
// Found a solution that's not an ambiguity yet, but is "suspicious" and
|
||||
// can participate in ambiguities later on.
|
||||
// Remember it and go search for other solutions in outer scopes.
|
||||
if (result.1).0 {
|
||||
potentially_ambiguous_result = Some(result);
|
||||
|
||||
continue_search!();
|
||||
}
|
||||
|
||||
// Found a solution that can't be ambiguous.
|
||||
return Some(result);
|
||||
}
|
||||
None => {
|
||||
continue_search!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Previously found potentially ambiguous result turned out to not be ambiguous after all.
|
||||
if let Some(previous_result) = potentially_ambiguous_result {
|
||||
return Some(previous_result);
|
||||
}
|
||||
|
||||
None
|
||||
@ -846,8 +905,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||
|
||||
let check_consistency = |this: &Self, new_def: Def| {
|
||||
if let Some(def) = def {
|
||||
if this.ambiguity_errors.is_empty() && this.disallowed_shadowing.is_empty() &&
|
||||
new_def != def && new_def != Def::Err {
|
||||
if this.ambiguity_errors.is_empty() && new_def != def && new_def != Def::Err {
|
||||
// Make sure compilation does not succeed if preferred macro resolution
|
||||
// has changed after the macro had been expanded. In theory all such
|
||||
// situations should be reported as ambiguity errors, so this is span-bug.
|
||||
|
@ -17,14 +17,14 @@ macro_rules! macro_one { () => {} }
|
||||
#[macro_use(macro_two)] extern crate two_macros;
|
||||
|
||||
macro_rules! m1 { () => {
|
||||
macro_rules! foo { () => {} } //~ ERROR `foo` is already in scope
|
||||
macro_rules! foo { () => {} }
|
||||
|
||||
#[macro_use] //~ ERROR `macro_two` is already in scope
|
||||
extern crate two_macros as __;
|
||||
}}
|
||||
m1!();
|
||||
|
||||
foo!();
|
||||
foo!(); //~ ERROR `foo` is ambiguous
|
||||
|
||||
macro_rules! m2 { () => {
|
||||
macro_rules! foo { () => {} }
|
||||
|
@ -9,16 +9,27 @@ LL | m1!();
|
||||
|
|
||||
= note: macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)
|
||||
|
||||
error: `foo` is already in scope
|
||||
error[E0659]: `foo` is ambiguous
|
||||
--> $DIR/macro-shadowing.rs:27:1
|
||||
|
|
||||
LL | foo!(); //~ ERROR `foo` is ambiguous
|
||||
| ^^^
|
||||
|
|
||||
note: `foo` could refer to the name defined here
|
||||
--> $DIR/macro-shadowing.rs:20:5
|
||||
|
|
||||
LL | macro_rules! foo { () => {} } //~ ERROR `foo` is already in scope
|
||||
LL | macro_rules! foo { () => {} }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | m1!();
|
||||
| ------ in this macro invocation
|
||||
note: `foo` could also refer to the name defined here
|
||||
--> $DIR/macro-shadowing.rs:15:1
|
||||
|
|
||||
= note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560)
|
||||
LL | macro_rules! foo { () => {} }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: macro-expanded macros do not shadow
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0659`.
|
||||
|
@ -9,11 +9,10 @@
|
||||
// except according to those terms.
|
||||
|
||||
// aux-build:define_macro.rs
|
||||
// error-pattern: `bar` is already in scope
|
||||
|
||||
macro_rules! bar { () => {} }
|
||||
define_macro!(bar);
|
||||
bar!();
|
||||
bar!(); //~ ERROR `bar` is ambiguous
|
||||
|
||||
macro_rules! m { () => { #[macro_use] extern crate define_macro; } }
|
||||
m!();
|
||||
|
@ -1,11 +1,22 @@
|
||||
error: `bar` is already in scope
|
||||
error[E0659]: `bar` is ambiguous
|
||||
--> $DIR/out-of-order-shadowing.rs:15:1
|
||||
|
|
||||
LL | bar!(); //~ ERROR `bar` is ambiguous
|
||||
| ^^^
|
||||
|
|
||||
note: `bar` could refer to the name defined here
|
||||
--> $DIR/out-of-order-shadowing.rs:14:1
|
||||
|
|
||||
LL | define_macro!(bar);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
note: `bar` could also refer to the name defined here
|
||||
--> $DIR/out-of-order-shadowing.rs:13:1
|
||||
|
|
||||
= note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560)
|
||||
LL | macro_rules! bar { () => {} }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: macro-expanded macros do not shadow
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0659`.
|
||||
|
Loading…
Reference in New Issue
Block a user