Check for shadowing errors after all invocations have been expanded.

This commit is contained in:
Jeffrey Seyfried 2016-10-11 03:21:40 +00:00
parent 53fd3b0acc
commit 6808b0a2b7
2 changed files with 26 additions and 17 deletions

View File

@ -78,7 +78,7 @@ use std::mem::replace;
use std::rc::Rc;
use resolve_imports::{ImportDirective, NameResolution};
use macros::{InvocationData, LegacyBinding};
use macros::{InvocationData, LegacyBinding, LegacyScope};
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
@ -1073,7 +1073,7 @@ pub struct Resolver<'a> {
privacy_errors: Vec<PrivacyError<'a>>,
ambiguity_errors: Vec<AmbiguityError<'a>>,
macro_shadowing_errors: FnvHashSet<Span>,
disallowed_shadowing: Vec<(Name, Span, LegacyScope<'a>)>,
arenas: &'a ResolverArenas<'a>,
dummy_binding: &'a NameBinding<'a>,
@ -1260,7 +1260,7 @@ impl<'a> Resolver<'a> {
privacy_errors: Vec::new(),
ambiguity_errors: Vec::new(),
macro_shadowing_errors: FnvHashSet(),
disallowed_shadowing: Vec::new(),
arenas: arenas,
dummy_binding: arenas.alloc_name_binding(NameBinding {
@ -3353,7 +3353,8 @@ impl<'a> Resolver<'a> {
vis.is_accessible_from(module.normal_ancestor_id.unwrap(), self)
}
fn report_errors(&self) {
fn report_errors(&mut self) {
self.report_shadowing_errors();
let mut reported_spans = FnvHashSet();
for &AmbiguityError { span, name, b1, b2 } in &self.ambiguity_errors {
@ -3381,6 +3382,20 @@ impl<'a> Resolver<'a> {
}
}
fn report_shadowing_errors(&mut self) {
let mut reported_errors = FnvHashSet();
for (name, span, scope) in replace(&mut self.disallowed_shadowing, Vec::new()) {
if self.resolve_macro_name(scope, name, false).is_some() &&
reported_errors.insert((name, span)) {
let msg = format!("`{}` is already in scope", name);
self.session.struct_span_err(span, &msg)
.note("macro-expanded `macro_rules!`s and `#[macro_use]`s \
may not shadow existing macros (see RFC 1560)")
.emit();
}
}
}
fn report_conflict(&self,
parent: Module,
name: Name,

View File

@ -207,20 +207,14 @@ impl<'a> base::Resolver for Resolver<'a> {
}
impl<'a> Resolver<'a> {
fn resolve_macro_name(&mut self,
mut scope: LegacyScope<'a>,
name: ast::Name,
record_used: bool)
-> Option<Rc<SyntaxExtension>> {
pub fn resolve_macro_name(&mut self,
mut scope: LegacyScope<'a>,
name: ast::Name,
record_used: bool)
-> Option<Rc<SyntaxExtension>> {
let check_shadowing = |this: &mut Self, relative_depth, scope, span| {
if record_used && relative_depth > 0 &&
this.resolve_macro_name(scope, name, false).is_some() &&
this.macro_shadowing_errors.insert(span) {
let msg = format!("`{}` is already in scope", name);
this.session.struct_span_err(span, &msg)
.note("macro-expanded `macro_rules!`s and `#[macro_use]`s \
may not shadow existing macros (see RFC 1560)")
.emit();
if record_used && relative_depth > 0 {
this.disallowed_shadowing.push((name, span, scope));
}
};