blob: b8b2da69bc1d3dc2faae588e05fc4b57ca7ed1ae [file]
use std::hash::Hash;
use rustc_data_structures::stable_hash::StableHasher;
use rustc_serialize::Encoder;
use rustc_span::def_id::{CrateNum, DefId, DefIndex};
use rustc_span::{ByteSymbol, ExpnId, Span, SpanEncoder, Symbol, SyntaxContext};
/// Hasher used to determine if two diagnostics are the same and should be deduplicated. Used by
/// `DiagCtxtInner::emitted_diagnostics`. It's a stable hash with one special behaviour: parents of
/// spans within the diagnostics are ignored so that incremental and non-incremental compilation
/// get the same behaviour.
///
/// Although this has nothing to do with encoding data to/from file, it is implemented on top of
/// `Encoder`/`SpanEncoder` because they provide traversals of all the relevant types used within
/// diagnostics. There is no corresponding decoder.
pub(crate) struct DedupHashEncoder(pub(crate) StableHasher);
macro_rules! encoder_methods {
($($name:ident($ty:ty);)*) => {
$(
#[inline]
fn $name(&mut self, value: $ty) {
value.hash(&mut self.0)
}
)*
}
}
impl Encoder for DedupHashEncoder {
encoder_methods! {
emit_usize(usize);
emit_u128(u128);
emit_u64(u64);
emit_u32(u32);
emit_u16(u16);
emit_u8(u8);
emit_isize(isize);
emit_i128(i128);
emit_i64(i64);
emit_i32(i32);
emit_i16(i16);
emit_raw_bytes(&[u8]);
}
}
impl SpanEncoder for DedupHashEncoder {
fn encode_span(&mut self, span: Span) {
// The raison d'ĂȘtre of `DedupHashEncoder` is to ignore `parent` here.
span.with_parent(None).hash(&mut self.0);
}
encoder_methods! {
encode_symbol(Symbol);
encode_byte_symbol(ByteSymbol);
encode_expn_id(ExpnId);
encode_syntax_context(SyntaxContext);
encode_crate_num(CrateNum);
encode_def_index(DefIndex);
encode_def_id(DefId);
}
}