Skip to content

Commit c22ba27

Browse files
committed
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.
1 parent 60960a2 commit c22ba27

File tree

6 files changed

+61
-35
lines changed

6 files changed

+61
-35
lines changed

src/librustc_metadata/decoder.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use syntax::ast::{self, Ident};
3131
use syntax::source_map;
3232
use syntax::symbol::{Symbol, sym};
3333
use syntax::ext::base::{MacroKind, SyntaxExtension};
34-
use syntax::ext::hygiene::ExpnId;
34+
use syntax::ext::hygiene::{ExpnId, SyntaxContext};
3535
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
3636
use log::debug;
3737

@@ -348,6 +348,22 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
348348
}
349349
}
350350

351+
impl SpecializedDecoder<Ident> for DecodeContext<'_, '_> {
352+
fn specialized_decode(&mut self) -> Result<Ident, Self::Error> {
353+
// FIXME(jseyfried): intercrate hygiene
354+
355+
Ok(Ident::with_empty_ctxt(Symbol::decode(self)?))
356+
}
357+
}
358+
359+
impl SpecializedDecoder<SyntaxContext> for DecodeContext<'_, '_> {
360+
fn specialized_decode(&mut self) -> Result<SyntaxContext, Self::Error> {
361+
// FIXME(jseyfried): intercrate hygiene
362+
363+
Ok(SyntaxContext::empty())
364+
}
365+
}
366+
351367
impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
352368
fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
353369
Fingerprint::decode_opaque(&mut self.opaque)

src/librustc_metadata/encoder.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ use std::u32;
3131
use syntax::ast;
3232
use syntax::attr;
3333
use syntax::source_map::Spanned;
34-
use syntax::symbol::{kw, sym};
34+
use syntax::symbol::{kw, sym, Ident};
3535
use syntax_pos::{self, FileName, SourceFile, Span};
36+
use syntax_pos::hygiene::SyntaxContext;
3637
use log::{debug, trace};
3738

3839
use rustc::hir::{self, PatKind};
@@ -173,6 +174,20 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
173174
}
174175
}
175176

177+
impl SpecializedEncoder<Ident> for EncodeContext<'tcx> {
178+
fn specialized_encode(&mut self, ident: &Ident) -> Result<(), Self::Error> {
179+
// FIXME(jseyfried): intercrate hygiene
180+
ident.name.encode(self)
181+
}
182+
}
183+
184+
impl SpecializedEncoder<SyntaxContext> for EncodeContext<'tcx> {
185+
fn specialized_encode(&mut self, _ctxt: &SyntaxContext) -> Result<(), Self::Error> {
186+
// FIXME(jseyfried): intercrate hygiene
187+
Ok(())
188+
}
189+
}
190+
176191
impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> {
177192
#[inline]
178193
fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> {

src/libsyntax_pos/hygiene.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::{Span, DUMMY_SP};
3030
use crate::edition::Edition;
3131
use crate::symbol::{kw, Symbol};
3232

33-
use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
33+
use rustc_serialize::{UseSpecializedEncodable, UseSpecializedDecodable};
3434
use rustc_data_structures::fx::FxHashMap;
3535
use rustc_data_structures::sync::Lrc;
3636
use std::fmt;
@@ -767,14 +767,6 @@ impl DesugaringKind {
767767
}
768768
}
769769

770-
impl Encodable for SyntaxContext {
771-
fn encode<E: Encoder>(&self, _: &mut E) -> Result<(), E::Error> {
772-
Ok(()) // FIXME(jseyfried) intercrate hygiene
773-
}
774-
}
770+
impl UseSpecializedEncodable for SyntaxContext {}
775771

776-
impl Decodable for SyntaxContext {
777-
fn decode<D: Decoder>(_: &mut D) -> Result<SyntaxContext, D::Error> {
778-
Ok(SyntaxContext::empty()) // FIXME(jseyfried) intercrate hygiene
779-
}
780-
}
772+
impl UseSpecializedDecodable for SyntaxContext {}

src/libsyntax_pos/symbol.rs

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ use rustc_data_structures::indexed_vec::Idx;
88
use rustc_data_structures::newtype_index;
99
use rustc_macros::symbols;
1010
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
11+
use rustc_serialize::{UseSpecializedDecodable, UseSpecializedEncodable};
1112

1213
use std::cmp::{PartialEq, Ordering, PartialOrd, Ord};
1314
use std::fmt;
1415
use std::hash::{Hash, Hasher};
1516
use std::str;
1617

17-
use crate::hygiene::SyntaxContext;
1818
use crate::{Span, DUMMY_SP, GLOBALS};
1919

2020
#[cfg(test)]
@@ -849,28 +849,9 @@ impl fmt::Display for Ident {
849849
}
850850
}
851851

852-
impl Encodable for Ident {
853-
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
854-
if self.span.ctxt().modern() == SyntaxContext::empty() {
855-
s.emit_str(&self.as_str())
856-
} else { // FIXME(jseyfried): intercrate hygiene
857-
let mut string = "#".to_owned();
858-
string.push_str(&self.as_str());
859-
s.emit_str(&string)
860-
}
861-
}
862-
}
852+
impl UseSpecializedEncodable for Ident {}
863853

864-
impl Decodable for Ident {
865-
fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
866-
let string = d.read_str()?;
867-
Ok(if !string.starts_with('#') {
868-
Ident::from_str(&string)
869-
} else { // FIXME(jseyfried): intercrate hygiene
870-
Ident::from_str(&string[1..]).gensym()
871-
})
872-
}
873-
}
854+
impl UseSpecializedDecodable for Ident {}
874855

875856
/// A symbol is an interned or gensymed string. A gensym is a symbol that is
876857
/// never equal to any other symbol.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![feature(decl_macro)]
2+
3+
macro m($f:ident) {
4+
#[export_name = "export_function_name"]
5+
pub fn $f() -> i32 {
6+
2
7+
}
8+
}
9+
10+
m!(rust_function_name);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Make sure that macro expanded codegen attributes work across crates.
2+
// We used to gensym the identifiers in attributes, which stopped dependent
3+
// crates from seeing them, resulting in linker errors in cases like this one.
4+
5+
// run-pass
6+
// aux-build:codegen-attrs.rs
7+
8+
extern crate codegen_attrs;
9+
10+
fn main() {
11+
assert_eq!(codegen_attrs::rust_function_name(), 2);
12+
}

0 commit comments

Comments
 (0)