]> git.lizzy.rs Git - rust.git/commitdiff
Check for conflicts between macros 1.0 exports (`#[macro_export]`, `#[macro_reexport]`)
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Tue, 14 Mar 2017 05:16:54 +0000 (05:16 +0000)
committerPeter Atashian <retep998@gmail.com>
Tue, 21 Mar 2017 20:23:18 +0000 (16:23 -0400)
and macros 2.0 exports (`pub use` macro re-exports and `pub macro` (once implemented)
at the crate root.

src/librustc/hir/def.rs
src/librustc_metadata/decoder.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/test/compile-fail/duplicate-check-macro-exports.rs [new file with mode: 0644]

index aedb8fef2885cf461cca140334147a030940e891..7bab4a8d725dc2bcdfd87fdde54c44d639c3973c 100644 (file)
@@ -12,6 +12,7 @@
 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)]
@@ -116,6 +117,7 @@ pub fn kind_name(&self) -> &'static str {
 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 {
index b4b9966cbe47b98138d8ad1afe0e3b047d5537a6..c2ad598b0c503c49acf8c080596f84360f411048 100644 (file)
@@ -683,7 +683,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                         },
                         ext.kind()
                     );
-                    callback(def::Export { name: name, def: def });
+                    callback(def::Export { name: name, def: def, span: DUMMY_SP });
                 }
             }
             return
@@ -720,6 +720,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                                 callback(def::Export {
                                     def: def,
                                     name: self.item_name(child_index),
+                                    span: self.entry(child_index).span.decode(self),
                                 });
                             }
                         }
@@ -732,12 +733,10 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                 }
 
                 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 {
@@ -745,10 +744,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                             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) => {
@@ -756,10 +752,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                             // 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 });
                         }
                         _ => {}
                     }
index be905a9d0f94a904af2bed118631f52007dd7985..c33d5b9b6e16bb14bb4980039c00deac67c22c5c 100644 (file)
@@ -605,7 +605,7 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expa
             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");
             }
index df3be8fa0f810cb22bc639830b0f88776a0a1295..f72c2eadb04a865e999acad78063778b536a365e 100644 (file)
@@ -653,7 +653,7 @@ pub fn define_macro(&mut self, item: &ast::Item, legacy_scope: &mut LegacyScope<
 
         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 });
         }
     }
 
index dbc8bca548b769a1334f15facf53288a0a7e8845..2f4ac12cd7363bf2604c8d738206947802300f27 100644 (file)
@@ -21,7 +21,7 @@
 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};
@@ -763,10 +763,11 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
         *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);
                 }
             }
@@ -786,7 +787,17 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
                     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 });
                 }
             }
 
diff --git a/src/test/compile-fail/duplicate-check-macro-exports.rs b/src/test/compile-fail/duplicate-check-macro-exports.rs
new file mode 100644 (file)
index 0000000..53d7e54
--- /dev/null
@@ -0,0 +1,19 @@
+// 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() {}