]> git.lizzy.rs Git - rust.git/commitdiff
Improve intercrate hygiene.
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Mon, 27 Mar 2017 00:46:00 +0000 (00:46 +0000)
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Thu, 25 May 2017 05:52:11 +0000 (05:52 +0000)
src/librustc/hir/def.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/ich/impls_hir.rs
src/librustc/lib.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/libsyntax_pos/symbol.rs

index 771031db0c045f99e985f96b2e7caf05332c55da..feded417ce17fb7910d62a4e671c7ea0a48575be 100644 (file)
@@ -117,7 +117,7 @@ pub fn kind_name(&self) -> &'static str {
 
 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct Export {
-    pub name: ast::Name, // The name of the target.
+    pub ident: ast::Ident, // The name of the target.
     pub def: Def, // The definition of the target.
     pub span: Span, // The span of the target definition.
 }
index 5ef278207ed5e8a9f78fb0890bc35bf1199dae22..91cfbc38aa0ece054207968b2844c7dfcd942885 100644 (file)
@@ -2662,7 +2662,7 @@ fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMod
         let parent_def = self.parent_def.unwrap();
         let def_id = {
             let defs = self.resolver.definitions();
-            let def_path_data = DefPathData::Binding(name.as_str());
+            let def_path_data = DefPathData::Binding(Ident::with_empty_ctxt(name));
             let def_index = defs
                 .create_def_with_parent(parent_def, id, def_path_data, REGULAR_SPACE, Mark::root());
             DefId::local(def_index)
index f834c744f95ee3bff8887f963f65855e392f1bf3..cb25b462b6e243e791514e80316b73e29d5647c2 100644 (file)
@@ -14,7 +14,7 @@
 use syntax::ast::*;
 use syntax::ext::hygiene::Mark;
 use syntax::visit;
-use syntax::symbol::{Symbol, keywords};
+use syntax::symbol::keywords;
 
 use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE};
 
@@ -103,14 +103,14 @@ fn visit_item(&mut self, i: &'a Item) {
                 DefPathData::Impl,
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
             ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
-                DefPathData::TypeNs(i.ident.name.as_str()),
+                DefPathData::TypeNs(i.ident.modern()),
             ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
                 return visit::walk_item(self, i);
             }
-            ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
+            ItemKind::Mod(..) => DefPathData::Module(i.ident.modern()),
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
-                DefPathData::ValueNs(i.ident.name.as_str()),
-            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
+                DefPathData::ValueNs(i.ident.modern()),
+            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.modern()),
             ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
             ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(ref view_path) => {
@@ -138,15 +138,13 @@ fn visit_item(&mut self, i: &'a Item) {
                     for v in &enum_definition.variants {
                         let variant_def_index =
                             this.create_def(v.node.data.id(),
-                                            DefPathData::EnumVariant(v.node.name.name.as_str()),
+                                            DefPathData::EnumVariant(v.node.name.modern()),
                                             REGULAR_SPACE);
                         this.with_parent(variant_def_index, |this| {
                             for (index, field) in v.node.data.fields().iter().enumerate() {
-                                let name = field.ident.map(|ident| ident.name)
-                                    .unwrap_or_else(|| Symbol::intern(&index.to_string()));
-                                this.create_def(field.id,
-                                                DefPathData::Field(name.as_str()),
-                                                REGULAR_SPACE);
+                                let ident = field.ident.map(Ident::modern)
+                                    .unwrap_or_else(|| Ident::from_str(&index.to_string()));
+                                this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE);
                             }
 
                             if let Some(ref expr) = v.node.disr_expr {
@@ -164,9 +162,9 @@ fn visit_item(&mut self, i: &'a Item) {
                     }
 
                     for (index, field) in struct_def.fields().iter().enumerate() {
-                        let name = field.ident.map(|ident| ident.name.as_str())
-                            .unwrap_or(Symbol::intern(&index.to_string()).as_str());
-                        this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE);
+                        let ident = field.ident.map(Ident::modern)
+                            .unwrap_or_else(|| Ident::from_str(&index.to_string()));
+                        this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE);
                     }
                 }
                 _ => {}
@@ -177,7 +175,7 @@ fn visit_item(&mut self, i: &'a Item) {
 
     fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
         let def = self.create_def(foreign_item.id,
-                                  DefPathData::ValueNs(foreign_item.ident.name.as_str()),
+                                  DefPathData::ValueNs(foreign_item.ident.modern()),
                                   REGULAR_SPACE);
 
         self.with_parent(def, |this| {
@@ -188,7 +186,7 @@ fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
     fn visit_generics(&mut self, generics: &'a Generics) {
         for ty_param in generics.ty_params.iter() {
             self.create_def(ty_param.id,
-                            DefPathData::TypeParam(ty_param.ident.name.as_str()),
+                            DefPathData::TypeParam(ty_param.ident.modern()),
                             REGULAR_SPACE);
         }
 
@@ -198,8 +196,8 @@ fn visit_generics(&mut self, generics: &'a Generics) {
     fn visit_trait_item(&mut self, ti: &'a TraitItem) {
         let def_data = match ti.node {
             TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
-                DefPathData::ValueNs(ti.ident.name.as_str()),
-            TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()),
+                DefPathData::ValueNs(ti.ident.modern()),
+            TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.modern()),
             TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
         };
 
@@ -216,8 +214,8 @@ fn visit_trait_item(&mut self, ti: &'a TraitItem) {
     fn visit_impl_item(&mut self, ii: &'a ImplItem) {
         let def_data = match ii.node {
             ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
-                DefPathData::ValueNs(ii.ident.name.as_str()),
-            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()),
+                DefPathData::ValueNs(ii.ident.modern()),
+            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.modern()),
             ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
         };
 
@@ -238,7 +236,7 @@ fn visit_pat(&mut self, pat: &'a Pat) {
             PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
             PatKind::Ident(_, id, _) => {
                 let def = self.create_def(pat.id,
-                                          DefPathData::Binding(id.node.name.as_str()),
+                                          DefPathData::Binding(id.node.modern()),
                                           REGULAR_SPACE);
                 self.parent_def = Some(def);
             }
@@ -283,7 +281,7 @@ fn visit_ty(&mut self, ty: &'a Ty) {
 
     fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
         self.create_def(def.lifetime.id,
-                        DefPathData::LifetimeDef(def.lifetime.ident.name.as_str()),
+                        DefPathData::LifetimeDef(def.lifetime.ident.modern()),
                         REGULAR_SPACE);
     }
 
index 4a7fe05df8ac7f4afb94a1012bf684b579ef9dcb..c86b140fbc61462d6723c5a61dbb140351c7b631 100644 (file)
@@ -23,8 +23,8 @@
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use std::fmt::Write;
 use std::hash::Hash;
-use syntax::ast;
-use syntax::ext::hygiene::Mark;
+use syntax::ast::{self, Ident};
+use syntax::ext::hygiene::{Mark, SyntaxContext};
 use syntax::symbol::{Symbol, InternedString};
 use ty::TyCtxt;
 use util::nodemap::NodeMap;
@@ -327,7 +327,7 @@ pub fn to_string_no_crate(&self) -> String {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub enum DefPathData {
     // Root: these should only be used for the root nodes, because
     // they are treated specially by the `def_path` function.
@@ -341,31 +341,31 @@ pub enum DefPathData {
     /// An impl
     Impl,
     /// Something in the type NS
-    TypeNs(InternedString),
+    TypeNs(Ident),
     /// Something in the value NS
-    ValueNs(InternedString),
+    ValueNs(Ident),
     /// A module declaration
-    Module(InternedString),
+    Module(Ident),
     /// A macro rule
-    MacroDef(InternedString),
+    MacroDef(Ident),
     /// A closure expression
     ClosureExpr,
 
     // Subportions of items
     /// A type parameter (generic parameter)
-    TypeParam(InternedString),
+    TypeParam(Ident),
     /// A lifetime definition
-    LifetimeDef(InternedString),
+    LifetimeDef(Ident),
     /// A variant of a enum
-    EnumVariant(InternedString),
+    EnumVariant(Ident),
     /// A struct field
-    Field(InternedString),
+    Field(Ident),
     /// Implicit ctor for a tuple-like struct
     StructCtor,
     /// Initializer for a const
     Initializer,
     /// Pattern binding
-    Binding(InternedString),
+    Binding(Ident),
     /// An `impl Trait` type node.
     ImplTrait,
     /// A `typeof` type node.
@@ -551,18 +551,18 @@ pub fn add_macro_def_scope(&mut self, mark: Mark, scope: DefId) {
 }
 
 impl DefPathData {
-    pub fn get_opt_name(&self) -> Option<ast::Name> {
+    pub fn get_opt_ident(&self) -> Option<Ident> {
         use self::DefPathData::*;
         match *self {
-            TypeNs(ref name) |
-            ValueNs(ref name) |
-            Module(ref name) |
-            MacroDef(ref name) |
-            TypeParam(ref name) |
-            LifetimeDef(ref name) |
-            EnumVariant(ref name) |
-            Binding(ref name) |
-            Field(ref name) => Some(Symbol::intern(name)),
+            TypeNs(ident) |
+            ValueNs(ident) |
+            Module(ident) |
+            MacroDef(ident) |
+            TypeParam(ident) |
+            LifetimeDef(ident) |
+            EnumVariant(ident) |
+            Binding(ident) |
+            Field(ident) => Some(ident),
 
             Impl |
             CrateRoot |
@@ -575,19 +575,23 @@ pub fn get_opt_name(&self) -> Option<ast::Name> {
         }
     }
 
+    pub fn get_opt_name(&self) -> Option<ast::Name> {
+        self.get_opt_ident().map(|ident| ident.name)
+    }
+
     pub fn as_interned_str(&self) -> InternedString {
         use self::DefPathData::*;
         let s = match *self {
-            TypeNs(ref name) |
-            ValueNs(ref name) |
-            Module(ref name) |
-            MacroDef(ref name) |
-            TypeParam(ref name) |
-            LifetimeDef(ref name) |
-            EnumVariant(ref name) |
-            Binding(ref name) |
-            Field(ref name) => {
-                return name.clone();
+            TypeNs(ident) |
+            ValueNs(ident) |
+            Module(ident) |
+            MacroDef(ident) |
+            TypeParam(ident) |
+            LifetimeDef(ident) |
+            EnumVariant(ident) |
+            Binding(ident) |
+            Field(ident) => {
+                return ident.name.as_str();
             }
 
             // note that this does not show up in user printouts
@@ -609,3 +613,25 @@ pub fn to_string(&self) -> String {
         self.as_interned_str().to_string()
     }
 }
+
+impl Eq for DefPathData {}
+impl PartialEq for DefPathData {
+    fn eq(&self, other: &DefPathData) -> bool {
+        ::std::mem::discriminant(self) == ::std::mem::discriminant(other) &&
+        self.get_opt_ident() == other.get_opt_ident()
+    }
+}
+
+impl ::std::hash::Hash for DefPathData {
+    fn hash<H: ::std::hash::Hasher>(&self, hasher: &mut H) {
+        ::std::mem::discriminant(self).hash(hasher);
+        if let Some(ident) = self.get_opt_ident() {
+            if ident.ctxt == SyntaxContext::empty() && ident.name == ident.name.interned() {
+                ident.name.as_str().hash(hasher)
+            } else {
+                // FIXME(jseyfried) implement stable hashing for idents with macros 2.0 hygiene info
+                ident.hash(hasher)
+            }
+        }
+    }
+}
index 86965723f30e34b9e170743bf1dbec66fc6e98bd..dbe91e2725deffec2a377df2602646edbb886d79 100644 (file)
@@ -1118,7 +1118,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl_stable_hash_for!(struct hir::def::Export {
-    name,
+    ident,
     def,
     span
 });
index 2b4b5cc73337b7306dc5d6a9d3c3bda7ce9fd7a9..d1d9dd4853d7baa19ee5a43266f8d8321f1ec131 100644 (file)
@@ -28,6 +28,7 @@
 #![feature(conservative_impl_trait)]
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
+#![feature(discriminant_value)]
 #![feature(i128_type)]
 #![feature(libc)]
 #![feature(never_type)]
index d8826d87d4d0f4fd0752b05e5b4ff0dd7197d907..1db5821f31878e9ca1bf954e17ae9e69ff642a8f 100644 (file)
@@ -39,7 +39,7 @@
 
 use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
 use syntax::attr;
-use syntax::ast;
+use syntax::ast::{self, Ident};
 use syntax::codemap;
 use syntax::ext::base::MacroKind;
 use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
@@ -667,7 +667,8 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                         },
                         ext.kind()
                     );
-                    callback(def::Export { name: name, def: def, span: DUMMY_SP });
+                    let ident = Ident::with_empty_ctxt(name);
+                    callback(def::Export { ident: ident, def: def, span: DUMMY_SP });
                 }
             }
             return
@@ -703,7 +704,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                             if let Some(def) = self.get_def(child_index) {
                                 callback(def::Export {
                                     def: def,
-                                    name: self.item_name(child_index),
+                                    ident: Ident::with_empty_ctxt(self.item_name(child_index)),
                                     span: self.entry(child_index).span.decode(self),
                                 });
                             }
@@ -720,7 +721,8 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                 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, span: span });
+                    let ident = Ident::with_empty_ctxt(name);
+                    callback(def::Export { def: def, ident: ident, span: span });
                     // For non-reexport structs and variants add their constructors to children.
                     // Reexport lists automatically contain constructors when necessary.
                     match def {
@@ -728,7 +730,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, span: span });
+                                callback(def::Export { def: ctor_def, ident: ident, span: span });
                             }
                         }
                         Def::Variant(def_id) => {
@@ -736,7 +738,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, span: span });
+                            callback(def::Export { def: ctor_def, ident: ident, span: span });
                         }
                         _ => {}
                     }
index 72f555b47cc9a87c6ff06a6a30e49b7e1a430898..597a62f86884b94092cd57cb40c1ced511eba780 100644 (file)
@@ -439,7 +439,7 @@ fn build_reduced_graph_for_block(&mut self, block: &Block, expansion: Mark) {
 
     /// Builds the reduced graph for a single item in an external crate.
     fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
-        let ident = Ident::with_empty_ctxt(child.name);
+        let ident = child.ident;
         let def = child.def;
         let def_id = def.def_id();
         let vis = self.session.cstore.visibility(def_id);
@@ -480,9 +480,8 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
 
                 for child in self.session.cstore.item_children(def_id) {
                     let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS };
-                    let ident = Ident::with_empty_ctxt(child.name);
-                    self.define(module, ident, ns, (child.def, ty::Visibility::Public,
-                                                    DUMMY_SP, expansion));
+                    self.define(module, child.ident, ns,
+                                (child.def, ty::Visibility::Public, DUMMY_SP, expansion));
 
                     if self.session.cstore.associated_item_cloned(child.def.def_id())
                            .method_has_self_argument {
@@ -643,7 +642,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, false, span);
             if let Ok(binding) = result {
-                self.macro_exports.push(Export { name: name, def: binding.def(), span: span });
+                self.macro_exports.push(Export { ident: ident, def: binding.def(), span: span });
             } else {
                 span_err!(self.session, span, E0470, "reexported macro not found");
             }
index 8957312e1521712656f4e6812abaab4374dc7028..9a37df762327979cca096ffeb6a45b50a9753f08 100644 (file)
@@ -726,7 +726,8 @@ pub fn define_macro(&mut self,
             }));
             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, span: item.span });
+                self.macro_exports
+                    .push(Export { ident: ident.modern(), def: def, span: item.span });
             } else {
                 self.unused_macros.insert(def_id);
             }
index f304aad4638cead713a6b555c1dbeebe91af3e98..c077f507932c62e6ac5eb235d3779689be9bb19a 100644 (file)
@@ -803,7 +803,7 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
         if module as *const _ == self.graph_root as *const _ {
             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() {
+                if exported_macro_names.insert(export.ident.modern(), export.span).is_none() {
                     reexports.push(export);
                 }
             }
@@ -824,7 +824,7 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
                         self.session.cstore.export_macros(def.def_id().krate);
                     }
                     if let Def::Macro(..) = def {
-                        if let Some(&span) = exported_macro_names.get(&ident.name) {
+                        if let Some(&span) = exported_macro_names.get(&ident.modern()) {
                             let msg =
                                 format!("a macro named `{}` has already been exported", ident);
                             self.session.struct_span_err(span, &msg)
@@ -833,7 +833,7 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
                                 .emit();
                         }
                     }
-                    reexports.push(Export { name: ident.name, def: def, span: binding.span });
+                    reexports.push(Export { ident: ident.modern(), def: def, span: binding.span });
                 }
             }
 
index 17de8129f997b360cdc8f366e7d98a9dd43b95e1..73c0256f2c1f50babdde07d8a7a5c8c6e0e8f196 100644 (file)
@@ -54,13 +54,24 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 impl Encodable for Ident {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        self.name.encode(s)
+        if self.ctxt.modern() == SyntaxContext::empty() {
+            s.emit_str(&self.name.as_str())
+        } else { // FIXME(jseyfried) intercrate hygiene
+            let mut string = "#".to_owned();
+            string.push_str(&self.name.as_str());
+            s.emit_str(&string)
+        }
     }
 }
 
 impl Decodable for Ident {
     fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
-        Ok(Ident::with_empty_ctxt(Symbol::decode(d)?))
+        let string = d.read_str()?;
+        Ok(if !string.starts_with('#') {
+            Ident::from_str(&string)
+        } else { // FIXME(jseyfried) intercrate hygiene
+            Ident::with_empty_ctxt(Symbol::gensym(&string[1..]))
+        })
     }
 }