Skip to content

Use proc-macro to derive HashStable everywhere #66279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Nov 25, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 10 additions & 18 deletions src/librustc/ich/hcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use std::cell::RefCell;
use syntax::ast;
use syntax::source_map::SourceMap;
use syntax::symbol::Symbol;
use syntax::tokenstream::DelimSpan;
use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::hygiene::{self, SyntaxContext};

Expand Down Expand Up @@ -281,7 +280,7 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::NodeId {
}
}

impl<'a> HashStable<StableHashingContext<'a>> for Span {
impl<'a> syntax_pos::StableHashingContextLike for StableHashingContext<'a> {
/// Hashes a span in a stable way. We can't directly hash the span's `BytePos`
/// fields (that would be similar to hashing pointers, since those are just
/// offsets into the `SourceMap`). Instead, we hash the (file name, line, column)
Expand All @@ -291,25 +290,25 @@ impl<'a> HashStable<StableHashingContext<'a>> for Span {
/// codepoint offsets. For the purpose of the hash that's sufficient.
/// Also, hashing filenames is expensive so we avoid doing it twice when the
/// span starts and ends in the same file, which is almost always the case.
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
fn hash_stable_span(&mut self, span: &Span, hasher: &mut StableHasher) {
const TAG_VALID_SPAN: u8 = 0;
const TAG_INVALID_SPAN: u8 = 1;
const TAG_EXPANSION: u8 = 0;
const TAG_NO_EXPANSION: u8 = 1;

if !hcx.hash_spans {
if !self.hash_spans {
return
}

if *self == DUMMY_SP {
if *span == DUMMY_SP {
return std_hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
}

// If this is not an empty or invalid span, we want to hash the last
// position that belongs to it, as opposed to hashing the first
// position past it.
let span = self.data();
let (file_lo, line_lo, col_lo) = match hcx.source_map()
let span = span.data();
let (file_lo, line_lo, col_lo) = match self.source_map()
.byte_pos_to_line_and_col(span.lo) {
Some(pos) => pos,
None => {
Expand All @@ -333,9 +332,9 @@ impl<'a> HashStable<StableHashingContext<'a>> for Span {
std_hash::Hash::hash(&line_col_len, hasher);

if span.ctxt == SyntaxContext::root() {
TAG_NO_EXPANSION.hash_stable(hcx, hasher);
TAG_NO_EXPANSION.hash_stable(self, hasher);
} else {
TAG_EXPANSION.hash_stable(hcx, hasher);
TAG_EXPANSION.hash_stable(self, hasher);

// Since the same expansion context is usually referenced many
// times, we cache a stable hash of it and hash that instead of
Expand All @@ -352,25 +351,18 @@ impl<'a> HashStable<StableHashingContext<'a>> for Span {
}

let mut hasher = StableHasher::new();
expn_id.expn_data().hash_stable(hcx, &mut hasher);
expn_id.expn_data().hash_stable(self, &mut hasher);
let sub_hash: Fingerprint = hasher.finish();
let sub_hash = sub_hash.to_smaller_hash();
cache.borrow_mut().insert(expn_id, sub_hash);
sub_hash
});

sub_hash.hash_stable(hcx, hasher);
sub_hash.hash_stable(self, hasher);
}
}
}

impl<'a> HashStable<StableHashingContext<'a>> for DelimSpan {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
self.open.hash_stable(hcx, hasher);
self.close.hash_stable(hcx, hasher);
}
}

pub fn hash_stable_trait_impls<'a>(
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher,
Expand Down
5 changes: 0 additions & 5 deletions src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr {

impl_stable_hash_for_spanned!(usize);

impl_stable_hash_for!(struct ast::Ident {
name,
span,
});

impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
let hir::TraitItem {
Expand Down
83 changes: 10 additions & 73 deletions src/librustc/ich/impls_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,14 @@ use std::mem;
use syntax::ast;
use syntax::feature_gate;
use syntax::token;
use syntax::tokenstream;
use syntax_pos::SourceFile;

use crate::hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};

use smallvec::SmallVec;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};

impl_stable_hash_for!(struct ::syntax::ast::Lit {
kind,
token,
span
});
impl<'ctx> rustc_target::StableHashingContextLike for StableHashingContext<'ctx> {}

impl_stable_hash_for_spanned!(::syntax::ast::LitKind);

Expand Down Expand Up @@ -50,20 +45,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
}
}

impl<'a> HashStable<StableHashingContext<'a>> for ast::Path {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
self.segments.len().hash_stable(hcx, hasher);
for segment in &self.segments {
segment.ident.name.hash_stable(hcx, hasher);
}
}
}

impl_stable_hash_for!(struct ::syntax::ast::AttrItem {
path,
tokens,
});

impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
// Make sure that these have been filtered out.
Expand All @@ -81,38 +62,10 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
}
}

impl<'a> HashStable<StableHashingContext<'a>>
for tokenstream::TokenTree {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
tokenstream::TokenTree::Token(ref token) => {
token.hash_stable(hcx, hasher);
}
tokenstream::TokenTree::Delimited(span, delim, ref tts) => {
span.hash_stable(hcx, hasher);
std_hash::Hash::hash(&delim, hasher);
for sub_tt in tts.trees() {
sub_tt.hash_stable(hcx, hasher);
}
}
}
}
}

impl<'a> HashStable<StableHashingContext<'a>>
for tokenstream::TokenStream {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
for sub_tt in self.trees() {
sub_tt.hash_stable(hcx, hasher);
}
}
}

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);
match *self {
impl<'ctx> syntax::StableHashingContextLike for StableHashingContext<'ctx> {
fn hash_stable_tokenkind(&mut self, tokenkind: &token::TokenKind, hasher: &mut StableHasher) {
mem::discriminant(tokenkind).hash_stable(self, hasher);
match *tokenkind {
token::Eq |
token::Lt |
token::Le |
Expand Down Expand Up @@ -153,30 +106,25 @@ impl<'a> HashStable<StableHashingContext<'a>> for token::TokenKind {
token::CloseDelim(delim_token) => {
std_hash::Hash::hash(&delim_token, hasher);
}
token::Literal(lit) => lit.hash_stable(hcx, hasher),
token::Literal(lit) => lit.hash_stable(self, hasher),

token::Ident(name, is_raw) => {
name.hash_stable(hcx, hasher);
is_raw.hash_stable(hcx, hasher);
name.hash_stable(self, hasher);
is_raw.hash_stable(self, hasher);
}
token::Lifetime(name) => name.hash_stable(hcx, hasher),
token::Lifetime(name) => name.hash_stable(self, hasher),

token::Interpolated(_) => {
bug!("interpolated tokens should not be present in the HIR")
}

token::DocComment(val) |
token::Shebang(val) |
token::Unknown(val) => val.hash_stable(hcx, hasher),
token::Unknown(val) => val.hash_stable(self, hasher),
}
}
}

impl_stable_hash_for!(struct token::Token {
kind,
span
});

impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItem {
MetaItem(meta_item),
Literal(lit)
Expand All @@ -194,17 +142,6 @@ impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
NameValue(lit)
});

impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData {
kind,
parent -> _,
call_site,
def_site,
allow_internal_unstable,
allow_internal_unsafe,
local_inner_macros,
edition
});

impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
let SourceFile {
Expand Down
1 change: 1 addition & 0 deletions src/librustc_macros/src/hash_stable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_ma
let generic: syn::GenericParam = parse_quote!(__CTX);
s.add_bounds(synstructure::AddBounds::Generics);
s.add_impl_generic(generic);
s.add_where_predicate(parse_quote!{ __CTX: crate::StableHashingContextLike });
let body = s.each(|bi| {
let attrs = parse_attributes(bi.ast());
if attrs.ignore {
Expand Down
20 changes: 20 additions & 0 deletions src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::fmt::Write;
use std::mem;

use syntax::source_map::{self, Span, DUMMY_SP};
use rustc::ich::StableHashingContext;
use rustc::hir::def_id::DefId;
use rustc::hir::def::DefKind;
use rustc::mir;
Expand All @@ -18,6 +19,7 @@ use rustc::mir::interpret::{
InterpResult, truncate, sign_extend,
};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::HashStable;

use super::{
Expand Down Expand Up @@ -829,3 +831,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
frames
}
}

impl<'ctx, 'mir, 'tcx, Tag, Extra> HashStable<StableHashingContext<'ctx>>
for Frame<'mir, 'tcx, Tag, Extra>
where Extra: HashStable<StableHashingContext<'ctx>>,
Tag: HashStable<StableHashingContext<'ctx>>
{
fn hash_stable(&self, hcx: &mut StableHashingContext<'ctx>, hasher: &mut StableHasher) {
self.body.hash_stable(hcx, hasher);
self.instance.hash_stable(hcx, hasher);
self.span.hash_stable(hcx, hasher);
self.return_to_block.hash_stable(hcx, hasher);
self.return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher);
self.locals.hash_stable(hcx, hasher);
self.block.hash_stable(hcx, hasher);
self.stmt.hash_stable(hcx, hasher);
self.extra.hash_stable(hcx, hasher);
}
}
12 changes: 0 additions & 12 deletions src/librustc_mir/interpret/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,18 +304,6 @@ struct FrameSnapshot<'a, 'tcx> {
stmt: usize,
}

impl_stable_hash_for!(impl<> for struct Frame<'mir, 'tcx> {
body,
instance,
span,
return_to_block,
return_place -> (return_place.as_ref().map(|r| &**r)),
locals,
block,
stmt,
extra,
});

impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
where Ctx: SnapshotContext<'a>,
{
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_target/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@

pub mod abi;
pub mod spec;

/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in librustc.
pub trait StableHashingContextLike {}
14 changes: 12 additions & 2 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use syntax_pos::symbol::{kw, sym, Symbol};
use syntax_pos::{Span, DUMMY_SP, ExpnId};

use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_index::vec::Idx;
Expand Down Expand Up @@ -112,6 +113,15 @@ impl PartialEq<Symbol> for Path {
}
}

impl<CTX> HashStable<CTX> for Path {
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
self.segments.len().hash_stable(hcx, hasher);
for segment in &self.segments {
segment.ident.name.hash_stable(hcx, hasher);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michaelwoerister This skips all the other fields in PathSegment and also the span field in Path. Is this intentional?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the NodeId field was added later and the whole implementation was lifted to a more general context in 759bd01. It would be good to hash the generic arguments too.

}
}
}

impl Path {
// Convert a span and an identifier to the corresponding
// one-segment path.
Expand Down Expand Up @@ -1411,7 +1421,7 @@ pub enum StrStyle {
}

/// An AST literal.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
pub struct Lit {
/// The original literal token as written in source code.
pub token: token::Lit,
Expand Down Expand Up @@ -2266,7 +2276,7 @@ impl rustc_serialize::Decodable for AttrId {
}
}

#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
pub struct AttrItem {
pub path: Path,
pub tokens: TokenStream,
Expand Down
8 changes: 8 additions & 0 deletions src/libsyntax/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#![recursion_limit="256"]

pub use errors;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::Lock;
use rustc_index::bit_set::GrowableBitSet;
pub use rustc_data_structures::thin_vec::ThinVec;
Expand Down Expand Up @@ -110,3 +111,10 @@ pub mod print {
}

pub mod early_buffered_lints;

/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in librustc.
pub trait StableHashingContextLike: syntax_pos::StableHashingContextLike {
fn hash_stable_tokenkind(&mut self, tokenkind: &token::TokenKind, hasher: &mut StableHasher);
}
11 changes: 10 additions & 1 deletion src/libsyntax/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use syntax_pos::{self, Span, DUMMY_SP};

use std::fmt;
use std::mem;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc;
use rustc_macros::HashStable_Generic;

Expand Down Expand Up @@ -262,7 +263,15 @@ pub enum TokenKind {
#[cfg(target_arch = "x86_64")]
rustc_data_structures::static_assert_size!(TokenKind, 16);

#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
impl<CTX> HashStable<CTX> for TokenKind
where CTX: crate::StableHashingContextLike
{
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
hcx.hash_stable_tokenkind(self, hasher)
}
}

#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
pub struct Token {
pub kind: TokenKind,
pub span: Span,
Expand Down
Loading