Skip to main content

rustc_errors/
dedup_hash.rs

1use std::hash::Hash;
2
3use rustc_data_structures::stable_hash::StableHasher;
4use rustc_serialize::Encoder;
5use rustc_span::def_id::{CrateNum, DefId, DefIndex};
6use rustc_span::{ByteSymbol, ExpnId, Span, SpanEncoder, Symbol, SyntaxContext};
7
8/// Hasher used to determine if two diagnostics are the same and should be deduplicated. Used by
9/// `DiagCtxtInner::emitted_diagnostics`. It's a stable hash with one special behaviour: parents of
10/// spans within the diagnostics are ignored so that incremental and non-incremental compilation
11/// get the same behaviour.
12///
13/// Although this has nothing to do with encoding data to/from file, it is implemented on top of
14/// `Encoder`/`SpanEncoder` because they provide traversals of all the relevant types used within
15/// diagnostics. There is no corresponding decoder.
16pub(crate) struct DedupHashEncoder(pub(crate) StableHasher);
17
18macro_rules! encoder_methods {
19    ($($name:ident($ty:ty);)*) => {
20        $(
21            #[inline]
22            fn $name(&mut self, value: $ty) {
23                value.hash(&mut self.0)
24            }
25        )*
26    }
27}
28
29impl Encoder for DedupHashEncoder {
30    #[inline]
fn emit_usize(&mut self, value: usize) { value.hash(&mut self.0) }
#[inline]
fn emit_u128(&mut self, value: u128) { value.hash(&mut self.0) }
#[inline]
fn emit_u64(&mut self, value: u64) { value.hash(&mut self.0) }
#[inline]
fn emit_u32(&mut self, value: u32) { value.hash(&mut self.0) }
#[inline]
fn emit_u16(&mut self, value: u16) { value.hash(&mut self.0) }
#[inline]
fn emit_u8(&mut self, value: u8) { value.hash(&mut self.0) }
#[inline]
fn emit_isize(&mut self, value: isize) { value.hash(&mut self.0) }
#[inline]
fn emit_i128(&mut self, value: i128) { value.hash(&mut self.0) }
#[inline]
fn emit_i64(&mut self, value: i64) { value.hash(&mut self.0) }
#[inline]
fn emit_i32(&mut self, value: i32) { value.hash(&mut self.0) }
#[inline]
fn emit_i16(&mut self, value: i16) { value.hash(&mut self.0) }
#[inline]
fn emit_raw_bytes(&mut self, value: &[u8]) { value.hash(&mut self.0) }encoder_methods! {
31        emit_usize(usize);
32        emit_u128(u128);
33        emit_u64(u64);
34        emit_u32(u32);
35        emit_u16(u16);
36        emit_u8(u8);
37
38        emit_isize(isize);
39        emit_i128(i128);
40        emit_i64(i64);
41        emit_i32(i32);
42        emit_i16(i16);
43
44        emit_raw_bytes(&[u8]);
45    }
46}
47
48impl SpanEncoder for DedupHashEncoder {
49    fn encode_span(&mut self, span: Span) {
50        // The raison d'ĂȘtre of `DedupHashEncoder` is to ignore `parent` here.
51        span.with_parent(None).hash(&mut self.0);
52    }
53
54    #[inline]
fn encode_symbol(&mut self, value: Symbol) { value.hash(&mut self.0) }
#[inline]
fn encode_byte_symbol(&mut self, value: ByteSymbol) {
    value.hash(&mut self.0)
}
#[inline]
fn encode_expn_id(&mut self, value: ExpnId) { value.hash(&mut self.0) }
#[inline]
fn encode_syntax_context(&mut self, value: SyntaxContext) {
    value.hash(&mut self.0)
}
#[inline]
fn encode_crate_num(&mut self, value: CrateNum) { value.hash(&mut self.0) }
#[inline]
fn encode_def_index(&mut self, value: DefIndex) { value.hash(&mut self.0) }
#[inline]
fn encode_def_id(&mut self, value: DefId) { value.hash(&mut self.0) }encoder_methods! {
55        encode_symbol(Symbol);
56        encode_byte_symbol(ByteSymbol);
57        encode_expn_id(ExpnId);
58        encode_syntax_context(SyntaxContext);
59        encode_crate_num(CrateNum);
60        encode_def_index(DefIndex);
61        encode_def_id(DefId);
62    }
63}