use util::nodemap::NodeMap;
use syntax::ast;
use syntax::ext::base::MacroKind;
+use syntax_pos::Span;
use hir;
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct Export {
pub name: ast::Name, // The name of the target.
pub def: Def, // The definition of the target.
+ pub span: Span, // The span of the target definition.
}
impl CtorKind {
},
ext.kind()
);
- callback(def::Export { name: name, def: def });
+ callback(def::Export { name: name, def: def, span: DUMMY_SP });
}
}
return
callback(def::Export {
def: def,
name: self.item_name(child_index),
+ span: self.entry(child_index).span.decode(self),
});
}
}
}
let def_key = self.def_key(child_index);
+ let span = child.span.decode(self);
if let (Some(def), Some(name)) =
(self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
- callback(def::Export {
- def: def,
- name: name,
- });
+ callback(def::Export { def: def, name: name, span: span });
// For non-reexport structs and variants add their constructors to children.
// Reexport lists automatically contain constructors when necessary.
match def {
if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
let ctor_kind = self.get_ctor_kind(child_index);
let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
- callback(def::Export {
- def: ctor_def,
- name: name,
- });
+ callback(def::Export { def: ctor_def, name: name, span: span });
}
}
Def::Variant(def_id) => {
// value namespace, they are reserved for possible future use.
let ctor_kind = self.get_ctor_kind(child_index);
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
- callback(def::Export {
- def: ctor_def,
- name: name,
- });
+ callback(def::Export { def: ctor_def, name: name, span: span });
}
_ => {}
}
let ident = Ident::with_empty_ctxt(name);
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
if let Ok(binding) = result {
- self.macro_exports.push(Export { name: name, def: binding.def() });
+ self.macro_exports.push(Export { name: name, def: binding.def(), span: span });
} else {
span_err!(self.session, span, E0470, "reexported macro not found");
}
if attr::contains_name(&item.attrs, "macro_export") {
let def = Def::Macro(def_id, MacroKind::Bang);
- self.macro_exports.push(Export { name: ident.name, def: def });
+ self.macro_exports.push(Export { name: ident.name, def: def, span: item.span });
}
}
use rustc::lint::builtin::PRIVATE_IN_PUBLIC;
use rustc::hir::def_id::DefId;
use rustc::hir::def::*;
-use rustc::util::nodemap::FxHashSet;
+use rustc::util::nodemap::FxHashMap;
use syntax::ast::{Ident, NodeId};
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
*module.globs.borrow_mut() = Vec::new();
let mut reexports = Vec::new();
+ let mut exported_macro_names = FxHashMap();
if module as *const _ == self.graph_root as *const _ {
- let mut exported_macro_names = FxHashSet();
- for export in mem::replace(&mut self.macro_exports, Vec::new()).into_iter().rev() {
- if exported_macro_names.insert(export.name) {
+ let macro_exports = mem::replace(&mut self.macro_exports, Vec::new());
+ for export in macro_exports.into_iter().rev() {
+ if exported_macro_names.insert(export.name, export.span).is_none() {
reexports.push(export);
}
}
if !def.def_id().is_local() {
self.session.cstore.export_macros(def.def_id().krate);
}
- reexports.push(Export { name: ident.name, def: def });
+ if let Def::Macro(..) = def {
+ if let Some(&span) = exported_macro_names.get(&ident.name) {
+ let msg =
+ format!("a macro named `{}` has already been exported", ident);
+ self.session.struct_span_err(span, &msg)
+ .span_label(span, &format!("`{}` already exported", ident))
+ .span_note(binding.span, "previous macro export here")
+ .emit();
+ }
+ }
+ reexports.push(Export { name: ident.name, def: def, span: binding.span });
}
}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(use_extern_macros)]
+
+pub use std::panic; //~ NOTE previous macro export here
+
+#[macro_export]
+macro_rules! panic { () => {} } //~ ERROR a macro named `panic` has already been exported
+//~| NOTE `panic` already exported
+
+fn main() {}