about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-11-22 13:54:41 +0000
committerbors <bors@rust-lang.org>2019-11-22 13:54:41 +0000
commit083b5a0a1bb3b2ee0873697ebf37e88d85faa3e5 (patch)
treea9ec5f23575deb5436cb8dd0fef4675cbc80ba75 /src
parenteaac45a9a9e6d457a03ed354dacde990fe8c14ac (diff)
parent44a595f52ca0dec2cf7a08ba182ce9f1eb637795 (diff)
downloadrust-083b5a0a1bb3b2ee0873697ebf37e88d85faa3e5.tar.gz
rust-083b5a0a1bb3b2ee0873697ebf37e88d85faa3e5.zip
Auto merge of #66460 - cjgillot:hashstable_generic, r=Zoxc
Add a proc-macro to derive HashStable in librustc dependencies

A second proc-macro is added to derive HashStable for crates librustc depends on.
This proc-macro HashStable_Generic (to bikeshed) allows to decouple code and some librustc's boilerplate.

Not everything is migrated, because `Span` and `TokenKind` require to be placed inside librustc.
Types using them stay there too.

Split out of #66279
r? @Zoxc
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ich/impls_hir.rs5
-rw-r--r--src/librustc/ich/impls_misc.rs7
-rw-r--r--src/librustc/ich/impls_syntax.rs210
-rw-r--r--src/librustc/ich/impls_ty.rs5
-rw-r--r--src/librustc/ich/mod.rs1
-rw-r--r--src/librustc/ty/layout.rs152
-rw-r--r--src/librustc_data_structures/stable_hasher.rs10
-rw-r--r--src/librustc_macros/src/hash_stable.rs38
-rw-r--r--src/librustc_macros/src/lib.rs5
-rw-r--r--src/librustc_target/Cargo.toml1
-rw-r--r--src/librustc_target/abi/mod.rs25
-rw-r--r--src/librustc_target/spec/abi.rs5
-rw-r--r--src/librustc_target/spec/mod.rs4
-rw-r--r--src/libsyntax/Cargo.toml1
-rw-r--r--src/libsyntax/ast.rs43
-rw-r--r--src/libsyntax/attr/builtin.rs14
-rw-r--r--src/libsyntax/token.rs5
-rw-r--r--src/libsyntax_pos/edition.rs5
-rw-r--r--src/libsyntax_pos/hygiene.rs13
-rw-r--r--src/libsyntax_pos/lib.rs4
-rw-r--r--src/libsyntax_pos/symbol.rs33
21 files changed, 162 insertions, 424 deletions
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 816e93698bc..39d1f850f45 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -213,11 +213,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem {
     }
 }
 
-impl_stable_hash_for!(enum ast::CrateSugar {
-    JustCrate,
-    PubCrate,
-});
-
 impl<'a> HashStable<StableHashingContext<'a>> for hir::VisibilityKind {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         mem::discriminant(self).hash_stable(hcx, hasher);
diff --git a/src/librustc/ich/impls_misc.rs b/src/librustc/ich/impls_misc.rs
deleted file mode 100644
index 417305139e4..00000000000
--- a/src/librustc/ich/impls_misc.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//! This module contains `HashStable` implementations for various data types
-//! that don't fit into any of the other impls_xxx modules.
-
-impl_stable_hash_for!(enum ::rustc_target::spec::PanicStrategy {
-    Abort,
-    Unwind
-});
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index b3d82e5522c..f8bf8f4ab8a 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -10,135 +10,12 @@ use syntax::ast;
 use syntax::feature_gate;
 use syntax::token;
 use syntax::tokenstream;
-use syntax_pos::symbol::SymbolStr;
 use syntax_pos::SourceFile;
 
 use crate::hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
 
 use smallvec::SmallVec;
-use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher};
-
-impl<'a> HashStable<StableHashingContext<'a>> for SymbolStr {
-    #[inline]
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let str = self as &str;
-        str.hash_stable(hcx, hasher)
-    }
-}
-
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for SymbolStr {
-    type KeyType = SymbolStr;
-
-    #[inline]
-    fn to_stable_hash_key(&self,
-                          _: &StableHashingContext<'a>)
-                          -> SymbolStr {
-        self.clone()
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
-    #[inline]
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        self.as_str().hash_stable(hcx, hasher);
-    }
-}
-
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
-    type KeyType = SymbolStr;
-
-    #[inline]
-    fn to_stable_hash_key(&self,
-                          _: &StableHashingContext<'a>)
-                          -> SymbolStr {
-        self.as_str()
-    }
-}
-
-impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
-    Att,
-    Intel
-});
-
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::MacroKind {
-    Bang,
-    Attr,
-    Derive,
-});
-
-
-impl_stable_hash_for!(enum ::rustc_target::spec::abi::Abi {
-    Cdecl,
-    Stdcall,
-    Fastcall,
-    Vectorcall,
-    Thiscall,
-    Aapcs,
-    Win64,
-    SysV64,
-    PtxKernel,
-    Msp430Interrupt,
-    X86Interrupt,
-    AmdGpuKernel,
-    EfiApi,
-    Rust,
-    C,
-    System,
-    RustIntrinsic,
-    RustCall,
-    PlatformIntrinsic,
-    Unadjusted
-});
-
-impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
-impl_stable_hash_for!(struct ::syntax::attr::Stability {
-    level,
-    feature,
-    rustc_depr,
-    promotable,
-    allow_const_fn_ptr,
-    const_stability
-});
-
-impl_stable_hash_for!(enum ::syntax::edition::Edition {
-    Edition2015,
-    Edition2018,
-});
-
-impl<'a> HashStable<StableHashingContext<'a>>
-for ::syntax::attr::StabilityLevel {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        mem::discriminant(self).hash_stable(hcx, hasher);
-        match *self {
-            ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue, ref is_soft } => {
-                reason.hash_stable(hcx, hasher);
-                issue.hash_stable(hcx, hasher);
-                is_soft.hash_stable(hcx, hasher);
-            }
-            ::syntax::attr::StabilityLevel::Stable { ref since } => {
-                since.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
-impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason, suggestion });
-
-impl_stable_hash_for!(enum ::syntax::attr::IntType {
-    SignedInt(int_ty),
-    UnsignedInt(uint_ty)
-});
-
-impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
-    Signed(int_ty),
-    Unsigned(int_ty),
-    Unsuffixed
-});
-
-impl_stable_hash_for!(enum ::syntax::ast::LitFloatType {
-    Suffixed(float_ty),
-    Unsuffixed
-});
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 
 impl_stable_hash_for!(struct ::syntax::ast::Lit {
     kind,
@@ -146,32 +23,9 @@ impl_stable_hash_for!(struct ::syntax::ast::Lit {
     span
 });
 
-impl_stable_hash_for!(enum ::syntax::ast::LitKind {
-    Str(value, style),
-    ByteStr(value),
-    Byte(value),
-    Char(value),
-    Int(value, lit_int_type),
-    Float(value, lit_float_type),
-    Bool(value),
-    Err(value)
-});
-
 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
 
-impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 });
-impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 });
-impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
-impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
-impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
-impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
 impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, ident });
-impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
-impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
-impl_stable_hash_for!(enum ::syntax::ast::Movability { Static, Movable });
-impl_stable_hash_for!(enum ::syntax::ast::CaptureBy { Value, Ref });
-impl_stable_hash_for!(enum ::syntax::ast::IsAuto { Yes, No });
-impl_stable_hash_for!(enum ::syntax::ast::ImplPolarity { Positive, Negative });
 
 impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
@@ -255,25 +109,6 @@ for tokenstream::TokenStream {
     }
 }
 
-impl_stable_hash_for!(enum token::LitKind {
-    Bool,
-    Byte,
-    Char,
-    Integer,
-    Float,
-    Str,
-    ByteStr,
-    StrRaw(n),
-    ByteStrRaw(n),
-    Err
-});
-
-impl_stable_hash_for!(struct token::Lit {
-    kind,
-    symbol,
-    suffix
-});
-
 impl<'a> HashStable<StableHashingContext<'a>> for token::TokenKind {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         mem::discriminant(self).hash_stable(hcx, hasher);
@@ -359,12 +194,6 @@ impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
     NameValue(lit)
 });
 
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency {
-    Transparent,
-    SemiTransparent,
-    Opaque,
-});
-
 impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData {
     kind,
     parent -> _,
@@ -376,43 +205,6 @@ impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData {
     edition
 });
 
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind {
-    Root,
-    Macro(kind, descr),
-    AstPass(kind),
-    Desugaring(kind)
-});
-
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::AstPass {
-    StdImports,
-    TestHarness,
-    ProcMacroHarness,
-    PluginMacroDefs,
-});
-
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::DesugaringKind {
-    CondTemporary,
-    Async,
-    Await,
-    QuestionMark,
-    OpaqueTy,
-    ForLoop,
-    TryBlock
-});
-
-impl_stable_hash_for!(enum ::syntax_pos::FileName {
-    Real(pb),
-    Macros(s),
-    QuoteExpansion(s),
-    Anon(s),
-    MacroExpansion(s),
-    ProcMacroSourceCode(s),
-    CliCrateAttr(s),
-    CfgSpec(s),
-    Custom(s),
-    DocTest(pb, line),
-});
-
 impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let SourceFile {
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index c643baf1125..7f50d859cde 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -159,11 +159,6 @@ where
     }
 }
 
-impl_stable_hash_for!(enum ::syntax::ast::Mutability {
-    Immutable,
-    Mutable
-});
-
 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
     type KeyType = region::Scope;
 
diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs
index f3fc7ec8fda..9e985ffb14c 100644
--- a/src/librustc/ich/mod.rs
+++ b/src/librustc/ich/mod.rs
@@ -10,7 +10,6 @@ mod caching_source_map_view;
 mod hcx;
 
 mod impls_hir;
-mod impls_misc;
 mod impls_ty;
 mod impls_syntax;
 
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 37d1e8e3340..b6050a5caf1 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -2327,158 +2327,6 @@ where
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for Variants {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        use crate::ty::layout::Variants::*;
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
-            Single { index } => {
-                index.hash_stable(hcx, hasher);
-            }
-            Multiple {
-                ref discr,
-                ref discr_kind,
-                discr_index,
-                ref variants,
-            } => {
-                discr.hash_stable(hcx, hasher);
-                discr_kind.hash_stable(hcx, hasher);
-                discr_index.hash_stable(hcx, hasher);
-                variants.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for DiscriminantKind {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        use crate::ty::layout::DiscriminantKind::*;
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
-            Tag => {}
-            Niche {
-                dataful_variant,
-                ref niche_variants,
-                niche_start,
-            } => {
-                dataful_variant.hash_stable(hcx, hasher);
-                niche_variants.start().hash_stable(hcx, hasher);
-                niche_variants.end().hash_stable(hcx, hasher);
-                niche_start.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for FieldPlacement {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        use crate::ty::layout::FieldPlacement::*;
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
-            Union(count) => {
-                count.hash_stable(hcx, hasher);
-            }
-            Array { count, stride } => {
-                count.hash_stable(hcx, hasher);
-                stride.hash_stable(hcx, hasher);
-            }
-            Arbitrary { ref offsets, ref memory_index } => {
-                offsets.hash_stable(hcx, hasher);
-                memory_index.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for VariantIdx {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        self.as_u32().hash_stable(hcx, hasher)
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for Abi {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        use crate::ty::layout::Abi::*;
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
-            Uninhabited => {}
-            Scalar(ref value) => {
-                value.hash_stable(hcx, hasher);
-            }
-            ScalarPair(ref a, ref b) => {
-                a.hash_stable(hcx, hasher);
-                b.hash_stable(hcx, hasher);
-            }
-            Vector { ref element, count } => {
-                element.hash_stable(hcx, hasher);
-                count.hash_stable(hcx, hasher);
-            }
-            Aggregate { sized } => {
-                sized.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for Scalar {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let Scalar { value, ref valid_range } = *self;
-        value.hash_stable(hcx, hasher);
-        valid_range.start().hash_stable(hcx, hasher);
-        valid_range.end().hash_stable(hcx, hasher);
-    }
-}
-
-impl_stable_hash_for!(struct crate::ty::layout::Niche {
-    offset,
-    scalar
-});
-
-impl_stable_hash_for!(struct crate::ty::layout::LayoutDetails {
-    variants,
-    fields,
-    abi,
-    largest_niche,
-    size,
-    align
-});
-
-impl_stable_hash_for!(enum crate::ty::layout::Integer {
-    I8,
-    I16,
-    I32,
-    I64,
-    I128
-});
-
-impl_stable_hash_for!(enum crate::ty::layout::Primitive {
-    Int(integer, signed),
-    F32,
-    F64,
-    Pointer
-});
-
-impl_stable_hash_for!(struct crate::ty::layout::AbiAndPrefAlign {
-    abi,
-    pref
-});
-
-impl<'tcx> HashStable<StableHashingContext<'tcx>> for Align {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
-        self.bytes().hash_stable(hcx, hasher);
-    }
-}
-
-impl<'tcx> HashStable<StableHashingContext<'tcx>> for Size {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
-        self.bytes().hash_stable(hcx, hasher);
-    }
-}
-
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for LayoutError<'tcx> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         use crate::ty::layout::LayoutError::*;
diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs
index 092208cfe1d..ce62021ac17 100644
--- a/src/librustc_data_structures/stable_hasher.rs
+++ b/src/librustc_data_structures/stable_hasher.rs
@@ -429,6 +429,16 @@ impl<T, CTX> HashStable<CTX> for ::std::mem::Discriminant<T> {
     }
 }
 
+impl<T, CTX> HashStable<CTX> for ::std::ops::RangeInclusive<T>
+    where T: HashStable<CTX>
+{
+    #[inline]
+    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+        self.start().hash_stable(ctx, hasher);
+        self.end().hash_stable(ctx, hasher);
+    }
+}
+
 impl<I: vec::Idx, T, CTX> HashStable<CTX> for vec::IndexVec<I, T>
     where T: HashStable<CTX>,
 {
diff --git a/src/librustc_macros/src/hash_stable.rs b/src/librustc_macros/src/hash_stable.rs
index 735cfb11b36..3fb252cbf8d 100644
--- a/src/librustc_macros/src/hash_stable.rs
+++ b/src/librustc_macros/src/hash_stable.rs
@@ -47,6 +47,44 @@ fn parse_attributes(field: &syn::Field) -> Attributes {
     attrs
 }
 
+pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    let generic: syn::GenericParam = parse_quote!(__CTX);
+    s.add_bounds(synstructure::AddBounds::Generics);
+    s.add_impl_generic(generic);
+    let body = s.each(|bi| {
+        let attrs = parse_attributes(bi.ast());
+        if attrs.ignore {
+             quote!{}
+        } else if let Some(project) = attrs.project {
+            quote!{
+                &#bi.#project.hash_stable(__hcx, __hasher);
+            }
+        } else {
+            quote!{
+                #bi.hash_stable(__hcx, __hasher);
+            }
+        }
+    });
+
+    let discriminant = match s.ast().data {
+        syn::Data::Enum(_) => quote! {
+            ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
+        },
+        syn::Data::Struct(_) => quote! {},
+        syn::Data::Union(_) => panic!("cannot derive on union"),
+    };
+
+    s.bound_impl(quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>), quote!{
+        fn hash_stable(
+            &self,
+            __hcx: &mut __CTX,
+            __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
+            #discriminant
+            match *self { #body }
+        }
+    })
+}
+
 pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     let generic: syn::GenericParam = parse_quote!('__ctx);
     s.add_bounds(synstructure::AddBounds::Generics);
diff --git a/src/librustc_macros/src/lib.rs b/src/librustc_macros/src/lib.rs
index dce3820d284..eee634ffebd 100644
--- a/src/librustc_macros/src/lib.rs
+++ b/src/librustc_macros/src/lib.rs
@@ -25,5 +25,10 @@ pub fn symbols(input: TokenStream) -> TokenStream {
 }
 
 decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
+decl_derive!(
+    [HashStable_Generic, attributes(stable_hasher)] =>
+    hash_stable::hash_stable_generic_derive
+);
+
 decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
 decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
diff --git a/src/librustc_target/Cargo.toml b/src/librustc_target/Cargo.toml
index c73d0adea38..0e0732490fb 100644
--- a/src/librustc_target/Cargo.toml
+++ b/src/librustc_target/Cargo.toml
@@ -12,6 +12,7 @@ path = "lib.rs"
 bitflags = "1.2.1"
 log = "0.4"
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_macros = { path = "../librustc_macros" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc_index = { path = "../librustc_index" }
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 2d7e05037ba..ac781819cc3 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -6,6 +6,7 @@ use crate::spec::Target;
 use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive};
 
 use rustc_index::vec::{Idx, IndexVec};
+use rustc_macros::HashStable_Generic;
 use syntax_pos::Span;
 
 pub mod call;
@@ -242,6 +243,7 @@ pub enum Endian {
 
 /// Size of a type in bytes.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(HashStable_Generic)]
 pub struct Size {
     raw: u64
 }
@@ -365,6 +367,7 @@ impl AddAssign for Size {
 
 /// Alignment of a type in bytes (always a power of two).
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(HashStable_Generic)]
 pub struct Align {
     pow2: u8,
 }
@@ -423,6 +426,7 @@ impl Align {
 
 /// A pair of aligments, ABI-mandated and preferred.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(HashStable_Generic)]
 pub struct AbiAndPrefAlign {
     pub abi: Align,
     pub pref: Align,
@@ -452,7 +456,7 @@ impl AbiAndPrefAlign {
 }
 
 /// Integers, also used for enum discriminants.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, HashStable_Generic)]
 pub enum Integer {
     I8,
     I16,
@@ -533,7 +537,7 @@ impl Integer {
 }
 
 /// Fundamental unit of memory access and layout.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum Primitive {
     /// The `bool` is the signedness of the `Integer` type.
     ///
@@ -588,6 +592,7 @@ impl Primitive {
 
 /// Information about one scalar component of a Rust type.
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(HashStable_Generic)]
 pub struct Scalar {
     pub value: Primitive,
 
@@ -636,7 +641,7 @@ impl Scalar {
 }
 
 /// Describes how the fields of a type are located in memory.
-#[derive(PartialEq, Eq, Hash, Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum FieldPlacement {
     /// All fields start at no offset. The `usize` is the field count.
     ///
@@ -752,7 +757,7 @@ impl FieldPlacement {
 
 /// Describes how values of the type are passed by target ABIs,
 /// in terms of categories of C types there are ABI rules for.
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum Abi {
     Uninhabited,
     Scalar(Scalar),
@@ -800,10 +805,12 @@ impl Abi {
 }
 
 rustc_index::newtype_index! {
-    pub struct VariantIdx { .. }
+    pub struct VariantIdx {
+        derive [HashStable_Generic]
+    }
 }
 
-#[derive(PartialEq, Eq, Hash, Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum Variants {
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
     Single {
@@ -821,7 +828,7 @@ pub enum Variants {
     },
 }
 
-#[derive(PartialEq, Eq, Hash, Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum DiscriminantKind {
     /// Integer tag holding the discriminant value itself.
     Tag,
@@ -842,7 +849,7 @@ pub enum DiscriminantKind {
     },
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct Niche {
     pub offset: Size,
     pub scalar: Scalar,
@@ -906,7 +913,7 @@ impl Niche {
     }
 }
 
-#[derive(PartialEq, Eq, Hash, Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct LayoutDetails {
     pub variants: Variants,
     pub fields: FieldPlacement,
diff --git a/src/librustc_target/spec/abi.rs b/src/librustc_target/spec/abi.rs
index 3a24d30966f..736358a995b 100644
--- a/src/librustc_target/spec/abi.rs
+++ b/src/librustc_target/spec/abi.rs
@@ -1,9 +1,12 @@
 use std::fmt;
 
+use rustc_macros::HashStable_Generic;
+
 #[cfg(test)]
 mod tests;
 
-#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)]
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable,
+         Clone, Copy, Debug, HashStable_Generic)]
 pub enum Abi {
     // N.B., this ordering MUST match the AbiDatas array below.
     // (This is ensured by the test indices_are_correct().)
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 4cd2f13d09c..716aef056a3 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -42,6 +42,8 @@ use std::path::{Path, PathBuf};
 use std::str::FromStr;
 use crate::spec::abi::{Abi, lookup as lookup_abi};
 
+use rustc_macros::HashStable_Generic;
+
 pub mod abi;
 mod android_base;
 mod apple_base;
@@ -153,7 +155,7 @@ flavor_mappings! {
     ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum PanicStrategy {
     Unwind,
     Abort,
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index d96b5b7a3dd..dff23076c82 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -20,5 +20,6 @@ errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_index = { path = "../librustc_index" }
 rustc_lexer = { path = "../librustc_lexer" }
+rustc_macros = { path = "../librustc_macros" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_error_codes = { path = "../librustc_error_codes" }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index bbf00825acb..a9f03e4af5b 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -37,6 +37,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_index::vec::Idx;
 use rustc_serialize::{self, Decoder, Encoder};
+use rustc_macros::HashStable_Generic;
 
 use std::fmt;
 
@@ -722,9 +723,8 @@ pub enum PatKind {
     Mac(Mac),
 }
 
-#[derive(
-    Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy,
-)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
+         RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
 pub enum Mutability {
     Mutable,
     Immutable,
@@ -1328,7 +1328,7 @@ pub struct QSelf {
 }
 
 /// A capture clause used in closures and `async` blocks.
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum CaptureBy {
     /// `move |x| y + x`.
     Value,
@@ -1339,7 +1339,7 @@ pub enum CaptureBy {
 /// The movability of a generator / closure literal:
 /// whether a generator contains self-references, causing it to be `!Unpin`.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
-         RustcEncodable, RustcDecodable, Debug, Copy)]
+         RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
 pub enum Movability {
     /// May contain self-references, `!Unpin`.
     Static,
@@ -1400,7 +1400,7 @@ impl MacroDef {
 }
 
 // Clippy uses Hash and PartialEq
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq, HashStable_Generic)]
 pub enum StrStyle {
     /// A regular string, like `"foo"`.
     Cooked,
@@ -1451,7 +1451,7 @@ impl StrLit {
 
 // Clippy uses Hash and PartialEq
 /// Type of the integer literal based on provided suffix.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq, HashStable_Generic)]
 pub enum LitIntType {
     /// e.g. `42_i32`.
     Signed(IntTy),
@@ -1462,7 +1462,7 @@ pub enum LitIntType {
 }
 
 /// Type of the float literal based on provided suffix.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq, HashStable_Generic)]
 pub enum LitFloatType {
     /// A float literal with a suffix (`1f32` or `1E10f32`).
     Suffixed(FloatTy),
@@ -1474,7 +1474,7 @@ pub enum LitFloatType {
 ///
 /// E.g., `"foo"`, `42`, `12.34`, or `bool`.
 // Clippy uses Hash and PartialEq
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq, HashStable_Generic)]
 pub enum LitKind {
     /// A string literal (`"foo"`).
     Str(Symbol, StrStyle),
@@ -1609,7 +1609,8 @@ pub enum ImplItemKind {
     Macro(Mac),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic,
+         RustcEncodable, RustcDecodable, Debug)]
 pub enum FloatTy {
     F32,
     F64,
@@ -1638,7 +1639,8 @@ impl FloatTy {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic,
+         RustcEncodable, RustcDecodable, Debug)]
 pub enum IntTy {
     Isize,
     I8,
@@ -1690,7 +1692,8 @@ impl IntTy {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy, Debug)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic,
+         RustcEncodable, RustcDecodable, Copy, Debug)]
 pub enum UintTy {
     Usize,
     U8,
@@ -1863,7 +1866,7 @@ pub enum TraitObjectSyntax {
 /// Inline assembly dialect.
 ///
 /// E.g., `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
 pub enum AsmDialect {
     Att,
     Intel,
@@ -2021,14 +2024,14 @@ impl FnDecl {
 }
 
 /// Is the trait definition an auto trait?
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum IsAuto {
     Yes,
     No,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
-         RustcEncodable, RustcDecodable, Debug)]
+         RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum Unsafety {
     Unsafe,
     Normal,
@@ -2085,7 +2088,7 @@ impl IsAsync {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum Constness {
     Const,
     NotConst,
@@ -2093,13 +2096,13 @@ pub enum Constness {
 
 /// Item defaultness.
 /// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum Defaultness {
     Default,
     Final,
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum ImplPolarity {
     /// `impl Trait for Type`
     Positive,
@@ -2233,7 +2236,7 @@ impl UseTree {
 /// Distinguishes between `Attribute`s that decorate items and Attributes that
 /// are contained as statements within items. These two cases need to be
 /// distinguished for pretty-printing.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
 pub enum AttrStyle {
     Outer,
     Inner,
@@ -2331,7 +2334,7 @@ impl PolyTraitRef {
     }
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum CrateSugar {
     /// Source is `pub(crate)`.
     PubCrate,
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index 767fcabc017..c10541c8c7e 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -9,6 +9,7 @@ use errors::{Applicability, Handler};
 use std::num::NonZeroU32;
 use syntax_pos::hygiene::Transparency;
 use syntax_pos::{symbol::Symbol, symbol::sym, Span};
+use rustc_macros::HashStable_Generic;
 
 use super::{mark_used, MetaItemKind};
 
@@ -141,7 +142,8 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op
 }
 
 /// Represents the #[stable], #[unstable], #[rustc_{deprecated,const_unstable}] attributes.
-#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug,
+         PartialEq, Eq, Hash, HashStable_Generic)]
 pub struct Stability {
     pub level: StabilityLevel,
     pub feature: Symbol,
@@ -157,7 +159,8 @@ pub struct Stability {
 }
 
 /// The available stability levels.
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd,
+         Copy, Clone, Debug, Eq, Hash, HashStable_Generic)]
 pub enum StabilityLevel {
     // Reason for the current stability level and the relevant rust-lang issue
     Unstable { reason: Option<Symbol>, issue: Option<NonZeroU32>, is_soft: bool },
@@ -181,7 +184,8 @@ impl StabilityLevel {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd,
+         Copy, Clone, Debug, Eq, Hash, HashStable_Generic)]
 pub struct RustcDeprecation {
     pub since: Symbol,
     pub reason: Symbol,
@@ -636,7 +640,7 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Clone)]
+#[derive(RustcEncodable, RustcDecodable, Clone, HashStable_Generic)]
 pub struct Deprecation {
     pub since: Option<Symbol>,
     pub note: Option<Symbol>,
@@ -763,7 +767,7 @@ pub enum ReprAttr {
     ReprAlign(u32),
 }
 
-#[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
+#[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone, HashStable_Generic)]
 pub enum IntType {
     SignedInt(ast::IntTy),
     UnsignedInt(ast::UintTy)
diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs
index ab798e93d67..fd1623384a4 100644
--- a/src/libsyntax/token.rs
+++ b/src/libsyntax/token.rs
@@ -15,6 +15,7 @@ use syntax_pos::{self, Span, DUMMY_SP};
 use std::fmt;
 use std::mem;
 use rustc_data_structures::sync::Lrc;
+use rustc_macros::HashStable_Generic;
 
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum BinOpToken {
@@ -53,7 +54,7 @@ impl DelimToken {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum LitKind {
     Bool, // AST only, must never appear in a `Token`
     Byte,
@@ -68,7 +69,7 @@ pub enum LitKind {
 }
 
 /// A literal token.
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub struct Lit {
     pub kind: LitKind,
     pub symbol: Symbol,
diff --git a/src/libsyntax_pos/edition.rs b/src/libsyntax_pos/edition.rs
index 00cd00f2837..727aad546f5 100644
--- a/src/libsyntax_pos/edition.rs
+++ b/src/libsyntax_pos/edition.rs
@@ -2,8 +2,11 @@ use crate::symbol::{Symbol, sym};
 use std::fmt;
 use std::str::FromStr;
 
+use rustc_macros::HashStable_Generic;
+
 /// The edition of the compiler (RFC 2052)
-#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)]
+#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug,
+         RustcEncodable, RustcDecodable, Eq, HashStable_Generic)]
 pub enum Edition {
     // editions must be kept in order, oldest to newest
 
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 2a48f8e44aa..eb420454f03 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -30,6 +30,7 @@ use crate::{Span, DUMMY_SP};
 use crate::edition::Edition;
 use crate::symbol::{kw, sym, Symbol};
 
+use rustc_macros::HashStable_Generic;
 use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
@@ -58,7 +59,8 @@ pub struct ExpnId(u32);
 
 /// A property of a macro expansion that determines how identifiers
 /// produced by that expansion are resolved.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug,
+         RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum Transparency {
     /// Identifier produced by a transparent expansion is always resolved at call-site.
     /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this.
@@ -683,7 +685,7 @@ impl ExpnData {
 }
 
 /// Expansion kind.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum ExpnKind {
     /// No expansion, aka root expansion. Only `ExpnId::root()` has this kind.
     Root,
@@ -707,7 +709,8 @@ impl ExpnKind {
 }
 
 /// The kind of macro invocation or definition.
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable,
+         Hash, Debug, HashStable_Generic)]
 pub enum MacroKind {
     /// A bang macro `foo!()`.
     Bang,
@@ -742,7 +745,7 @@ impl MacroKind {
 }
 
 /// The kind of AST transform.
-#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum AstPass {
     StdImports,
     TestHarness,
@@ -762,7 +765,7 @@ impl AstPass {
 }
 
 /// The kind of compiler desugaring.
-#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum DesugaringKind {
     /// We desugar `if c { i } else { e }` to `match $ExprKind::Use(c) { true => i, _ => e }`.
     /// However, we do not want to blame `c` for unreachability but rather say that `i`
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index b88d6dbc3f3..720ace90324 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -15,6 +15,7 @@
 #![feature(step_trait)]
 
 use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
+use rustc_macros::HashStable_Generic;
 
 pub mod source_map;
 
@@ -66,7 +67,8 @@ impl Globals {
 scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals);
 
 /// Differentiates between real files and common virtual files.
-#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash,
+         RustcDecodable, RustcEncodable, HashStable_Generic)]
 pub enum FileName {
     Real(PathBuf),
     /// A macro. This includes the full name of the macro, so that there are no clashes.
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 979074f17c7..23ee972529a 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -8,6 +8,7 @@ use rustc_index::vec::Idx;
 use rustc_macros::symbols;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_serialize::{UseSpecializedDecodable, UseSpecializedEncodable};
+use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher};
 
 use std::cmp::{PartialEq, PartialOrd, Ord};
 use std::fmt;
@@ -941,6 +942,22 @@ impl Decodable for Symbol {
     }
 }
 
+impl<CTX> HashStable<CTX> for Symbol {
+    #[inline]
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        self.as_str().hash_stable(hcx, hasher);
+    }
+}
+
+impl<CTX> ToStableHashKey<CTX> for Symbol {
+    type KeyType = SymbolStr;
+
+    #[inline]
+    fn to_stable_hash_key(&self, _: &CTX) -> SymbolStr {
+        self.as_str()
+    }
+}
+
 // The `&'static str`s in this type actually point into the arena.
 #[derive(Default)]
 pub struct Interner {
@@ -1138,3 +1155,19 @@ impl fmt::Display for SymbolStr {
         fmt::Display::fmt(self.string, f)
     }
 }
+
+impl<CTX> HashStable<CTX> for SymbolStr {
+    #[inline]
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        self.string.hash_stable(hcx, hasher)
+    }
+}
+
+impl<CTX> ToStableHashKey<CTX> for SymbolStr {
+    type KeyType = SymbolStr;
+
+    #[inline]
+    fn to_stable_hash_key(&self, _: &CTX) -> SymbolStr {
+        self.clone()
+    }
+}