about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2019-08-11 11:48:22 +0100
committerMatthew Jasper <mjjasper1@gmail.com>2019-08-17 08:59:36 +0100
commit497b50206229c28b89150960e2193964d02e8ef6 (patch)
tree2c57e70e69ec558c081a5a90593ee2d3d480f932
parent211d1e073527915f7ce1854ad8b30dc0c45845e8 (diff)
downloadrust-497b50206229c28b89150960e2193964d02e8ef6.tar.gz
rust-497b50206229c28b89150960e2193964d02e8ef6.zip
Stop emulating cross-crate hygiene with gensyms
Most `Ident`s are serialized as `InternedString`s the exceptions are:

* Reexports
* Attributes
* Idents in macro definitions

Using gensyms helped reexports emulate hygiene. However, the actual item
wouldn't have a gensymmed name so would be usable cross-crate. So
removing this case until we have proper cross-crate hygiene seems
sensible.

Codegen attributes (`inline`, `export_name`) are resolved by their
`Symbol`. This meant that opaque macro-expanded codegen attributes could
cause linker errors. This prevented making built-in derives hygienic.
-rw-r--r--src/librustc_metadata/decoder.rs16
-rw-r--r--src/librustc_metadata/encoder.rs17
-rw-r--r--src/libsyntax_pos/hygiene.rs12
-rw-r--r--src/libsyntax_pos/symbol.rs24
-rw-r--r--src/test/ui/hygiene/auxiliary/codegen-attrs.rs10
-rw-r--r--src/test/ui/hygiene/cross-crate-codegen-attrs.rs12
6 files changed, 59 insertions, 32 deletions
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 0bec31d7076..4365b1bee58 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -348,6 +348,22 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
     }
 }
 
+impl SpecializedDecoder<Ident> for DecodeContext<'_, '_> {
+    fn specialized_decode(&mut self) -> Result<Ident, Self::Error> {
+        // FIXME(jseyfried): intercrate hygiene
+
+        Ok(Ident::with_dummy_span(Symbol::decode(self)?))
+    }
+}
+
+impl SpecializedDecoder<SyntaxContext> for DecodeContext<'_, '_> {
+    fn specialized_decode(&mut self) -> Result<SyntaxContext, Self::Error> {
+        // FIXME(jseyfried): intercrate hygiene
+
+        Ok(SyntaxContext::empty())
+    }
+}
+
 impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
         Fingerprint::decode_opaque(&mut self.opaque)
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index fb675d7d841..34ccdad8636 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -31,8 +31,9 @@ use std::u32;
 use syntax::ast;
 use syntax::attr;
 use syntax::source_map::Spanned;
-use syntax::symbol::{kw, sym};
+use syntax::symbol::{kw, sym, Ident};
 use syntax_pos::{self, FileName, SourceFile, Span};
+use syntax_pos::hygiene::SyntaxContext;
 use log::{debug, trace};
 
 use rustc::hir::{self, PatKind};
@@ -173,6 +174,20 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
     }
 }
 
+impl SpecializedEncoder<Ident> for EncodeContext<'tcx> {
+    fn specialized_encode(&mut self, ident: &Ident) -> Result<(), Self::Error> {
+        // FIXME(jseyfried): intercrate hygiene
+        ident.name.encode(self)
+    }
+}
+
+impl SpecializedEncoder<SyntaxContext> for EncodeContext<'tcx> {
+    fn specialized_encode(&mut self, _ctxt: &SyntaxContext) -> Result<(), Self::Error> {
+        // FIXME(jseyfried): intercrate hygiene
+        Ok(())
+    }
+}
+
 impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> {
     #[inline]
     fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> {
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 87d930f897a..1e40994e77b 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -751,14 +751,6 @@ impl Decodable for ExpnId {
     }
 }
 
-impl Encodable for SyntaxContext {
-    fn encode<E: Encoder>(&self, _: &mut E) -> Result<(), E::Error> {
-        Ok(()) // FIXME(jseyfried) intercrate hygiene
-    }
-}
+impl UseSpecializedEncodable for SyntaxContext {}
 
-impl Decodable for SyntaxContext {
-    fn decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
-        Ok(SyntaxContext::root()) // FIXME(jseyfried) intercrate hygiene
-    }
-}
+impl UseSpecializedDecodable for SyntaxContext {}
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 27fc66d3b09..bed898f10b4 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -8,6 +8,7 @@ use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::newtype_index;
 use rustc_macros::symbols;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use rustc_serialize::{UseSpecializedDecodable, UseSpecializedEncodable};
 
 use std::cmp::{PartialEq, Ordering, PartialOrd, Ord};
 use std::fmt;
@@ -847,28 +848,9 @@ impl fmt::Display for Ident {
     }
 }
 
-impl Encodable for Ident {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        if !self.span.modern().from_expansion() {
-            s.emit_str(&self.as_str())
-        } else { // FIXME(jseyfried): intercrate hygiene
-            let mut string = "#".to_owned();
-            string.push_str(&self.as_str());
-            s.emit_str(&string)
-        }
-    }
-}
+impl UseSpecializedEncodable for Ident {}
 
-impl Decodable for Ident {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
-        let string = d.read_str()?;
-        Ok(if !string.starts_with('#') {
-            Ident::from_str(&string)
-        } else { // FIXME(jseyfried): intercrate hygiene
-            Ident::from_str(&string[1..]).gensym()
-        })
-    }
-}
+impl UseSpecializedDecodable for Ident {}
 
 /// A symbol is an interned or gensymed string. A gensym is a symbol that is
 /// never equal to any other symbol.
diff --git a/src/test/ui/hygiene/auxiliary/codegen-attrs.rs b/src/test/ui/hygiene/auxiliary/codegen-attrs.rs
new file mode 100644
index 00000000000..74afedbeb77
--- /dev/null
+++ b/src/test/ui/hygiene/auxiliary/codegen-attrs.rs
@@ -0,0 +1,10 @@
+#![feature(decl_macro)]
+
+macro m($f:ident) {
+    #[export_name = "export_function_name"]
+    pub fn $f() -> i32 {
+        2
+    }
+}
+
+m!(rust_function_name);
diff --git a/src/test/ui/hygiene/cross-crate-codegen-attrs.rs b/src/test/ui/hygiene/cross-crate-codegen-attrs.rs
new file mode 100644
index 00000000000..af6b1334387
--- /dev/null
+++ b/src/test/ui/hygiene/cross-crate-codegen-attrs.rs
@@ -0,0 +1,12 @@
+// Make sure that macro expanded codegen attributes work across crates.
+// We used to gensym the identifiers in attributes, which stopped dependent
+// crates from seeing them, resulting in linker errors in cases like this one.
+
+// run-pass
+// aux-build:codegen-attrs.rs
+
+extern crate codegen_attrs;
+
+fn main() {
+    assert_eq!(codegen_attrs::rust_function_name(), 2);
+}