//! This module contains `HashStable` implementations for various data types //! from libsyntax in no particular order. use crate::ich::StableHashingContext; use syntax::ast; 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<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {} impl<'a> HashStable> for ast::Lifetime { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { self.id.hash_stable(hcx, hasher); self.ident.hash_stable(hcx, hasher); } } impl<'a> HashStable> for [ast::Attribute] { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { if self.len() == 0 { self.len().hash_stable(hcx, hasher); return } // Some attributes are always ignored during hashing. let filtered: SmallVec<[&ast::Attribute; 8]> = self .iter() .filter(|attr| { !attr.is_doc_comment() && !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name)) }) .collect(); filtered.len().hash_stable(hcx, hasher); for attr in filtered { attr.hash_stable(hcx, hasher); } } } impl<'a> HashStable> for ast::Attribute { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { // Make sure that these have been filtered out. debug_assert!(!self.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))); debug_assert!(!self.is_doc_comment()); let ast::Attribute { kind, id: _, style, span } = self; if let ast::AttrKind::Normal(item) = kind { item.hash_stable(hcx, hasher); style.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher); } else { unreachable!(); } } } impl<'ctx> syntax::HashStableContext for StableHashingContext<'ctx> {} impl<'a> HashStable> for SourceFile { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let SourceFile { name: _, // We hash the smaller name_hash instead of this name_hash, name_was_remapped, unmapped_path: _, crate_of_origin, // Do not hash the source as it is not encoded src: _, src_hash, external_src: _, start_pos, end_pos: _, ref lines, ref multibyte_chars, ref non_narrow_chars, ref normalized_pos, } = *self; (name_hash as u64).hash_stable(hcx, hasher); name_was_remapped.hash_stable(hcx, hasher); DefId { krate: CrateNum::from_u32(crate_of_origin), index: CRATE_DEF_INDEX, }.hash_stable(hcx, hasher); src_hash.hash_stable(hcx, hasher); // We only hash the relative position within this source_file lines.len().hash_stable(hcx, hasher); for &line in lines.iter() { stable_byte_pos(line, start_pos).hash_stable(hcx, hasher); } // We only hash the relative position within this source_file multibyte_chars.len().hash_stable(hcx, hasher); for &char_pos in multibyte_chars.iter() { stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher); } non_narrow_chars.len().hash_stable(hcx, hasher); for &char_pos in non_narrow_chars.iter() { stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher); } normalized_pos.len().hash_stable(hcx, hasher); for &char_pos in normalized_pos.iter() { stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher); } } } fn stable_byte_pos(pos: ::syntax_pos::BytePos, source_file_start: ::syntax_pos::BytePos) -> u32 { pos.0 - source_file_start.0 } fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar, source_file_start: ::syntax_pos::BytePos) -> (u32, u32) { let ::syntax_pos::MultiByteChar { pos, bytes, } = mbc; (pos.0 - source_file_start.0, bytes as u32) } fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar, source_file_start: ::syntax_pos::BytePos) -> (u32, u32) { let pos = swc.pos(); let width = swc.width(); (pos.0 - source_file_start.0, width as u32) } fn stable_normalized_pos(np: ::syntax_pos::NormalizedPos, source_file_start: ::syntax_pos::BytePos) -> (u32, u32) { let ::syntax_pos::NormalizedPos { pos, diff } = np; (pos.0 - source_file_start.0, diff) } impl<'tcx> HashStable> for rustc_feature::Features { fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { // Unfortunately we cannot exhaustively list fields here, since the // struct is macro generated. self.declared_lang_features.hash_stable(hcx, hasher); self.declared_lib_features.hash_stable(hcx, hasher); self.walk_feature_fields(|feature_name, value| { feature_name.hash_stable(hcx, hasher); value.hash_stable(hcx, hasher); }); } }