| 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); |
| } |
| } |