1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! This module contains `HashStable` implementations for various HIR data
12 //! types in no particular order.
15 use hir::map::DefPathHash;
16 use hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX};
17 use ich::{StableHashingContext, NodeIdHashingMode, Fingerprint};
18 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
19 StableHasher, StableHasherResult};
24 impl<'a> HashStable<StableHashingContext<'a>> for DefId {
26 fn hash_stable<W: StableHasherResult>(&self,
27 hcx: &mut StableHashingContext<'a>,
28 hasher: &mut StableHasher<W>) {
29 hcx.def_path_hash(*self).hash_stable(hcx, hasher);
33 impl<'a> ToStableHashKey<StableHashingContext<'a>> for DefId {
34 type KeyType = DefPathHash;
37 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
38 hcx.def_path_hash(*self)
42 impl<'a> HashStable<StableHashingContext<'a>> for LocalDefId {
44 fn hash_stable<W: StableHasherResult>(&self,
45 hcx: &mut StableHashingContext<'a>,
46 hasher: &mut StableHasher<W>) {
47 hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher);
51 impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalDefId {
52 type KeyType = DefPathHash;
55 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
56 hcx.def_path_hash(self.to_def_id())
60 impl<'a> HashStable<StableHashingContext<'a>> for CrateNum {
62 fn hash_stable<W: StableHasherResult>(&self,
63 hcx: &mut StableHashingContext<'a>,
64 hasher: &mut StableHasher<W>) {
65 hcx.def_path_hash(DefId {
67 index: CRATE_DEF_INDEX
68 }).hash_stable(hcx, hasher);
72 impl<'a> ToStableHashKey<StableHashingContext<'a>> for CrateNum {
73 type KeyType = DefPathHash;
76 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
77 let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
78 def_id.to_stable_hash_key(hcx)
82 impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index });
84 impl<'a> ToStableHashKey<StableHashingContext<'a>>
85 for hir::ItemLocalId {
86 type KeyType = hir::ItemLocalId;
89 fn to_stable_hash_key(&self,
90 _: &StableHashingContext<'a>)
96 // The following implementations of HashStable for ItemId, TraitItemId, and
97 // ImplItemId deserve special attention. Normally we do not hash NodeIds within
98 // the HIR, since they just signify a HIR nodes own path. But ItemId et al
99 // are used when another item in the HIR is *referenced* and we certainly
100 // want to pick up on a reference changing its target, so we hash the NodeIds
101 // in "DefPath Mode".
103 impl<'a> HashStable<StableHashingContext<'a>> for hir::ItemId {
104 fn hash_stable<W: StableHasherResult>(&self,
105 hcx: &mut StableHashingContext<'a>,
106 hasher: &mut StableHasher<W>) {
111 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
112 id.hash_stable(hcx, hasher);
117 impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItemId {
118 fn hash_stable<W: StableHasherResult>(&self,
119 hcx: &mut StableHashingContext<'a>,
120 hasher: &mut StableHasher<W>) {
121 let hir::TraitItemId {
125 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
126 node_id.hash_stable(hcx, hasher);
131 impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItemId {
132 fn hash_stable<W: StableHasherResult>(&self,
133 hcx: &mut StableHashingContext<'a>,
134 hasher: &mut StableHasher<W>) {
135 let hir::ImplItemId {
139 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
140 node_id.hash_stable(hcx, hasher);
145 impl_stable_hash_for!(enum hir::ParamName {
150 impl_stable_hash_for!(enum hir::LifetimeName {
157 impl_stable_hash_for!(struct hir::Label {
161 impl_stable_hash_for!(struct hir::Lifetime {
167 impl_stable_hash_for!(struct hir::Path {
173 impl_stable_hash_for!(struct hir::PathSegment {
174 ident -> (ident.name),
179 impl_stable_hash_for!(enum hir::GenericArg {
184 impl_stable_hash_for!(struct hir::GenericArgs {
190 impl_stable_hash_for!(enum hir::GenericBound {
191 Trait(poly_trait_ref, trait_bound_modifier),
195 impl_stable_hash_for!(enum hir::TraitBoundModifier {
200 impl_stable_hash_for!(struct hir::GenericParam {
210 impl<'a> HashStable<StableHashingContext<'a>> for hir::GenericParamKind {
211 fn hash_stable<W: StableHasherResult>(&self,
212 hcx: &mut StableHashingContext<'a>,
213 hasher: &mut StableHasher<W>) {
214 mem::discriminant(self).hash_stable(hcx, hasher);
216 hir::GenericParamKind::Lifetime { in_band } => {
217 in_band.hash_stable(hcx, hasher);
219 hir::GenericParamKind::Type { ref default, synthetic } => {
220 default.hash_stable(hcx, hasher);
221 synthetic.hash_stable(hcx, hasher);
227 impl_stable_hash_for!(struct hir::Generics {
233 impl_stable_hash_for!(enum hir::SyntheticTyParamKind {
237 impl_stable_hash_for!(struct hir::WhereClause {
242 impl_stable_hash_for!(enum hir::WherePredicate {
243 BoundPredicate(pred),
244 RegionPredicate(pred),
248 impl_stable_hash_for!(struct hir::WhereBoundPredicate {
250 bound_generic_params,
255 impl_stable_hash_for!(struct hir::WhereRegionPredicate {
261 impl_stable_hash_for!(struct hir::WhereEqPredicate {
268 impl_stable_hash_for!(struct hir::MutTy {
273 impl_stable_hash_for!(struct hir::MethodSig {
278 impl_stable_hash_for!(struct hir::TypeBinding {
280 ident -> (ident.name),
285 impl_stable_hash_for!(struct hir::FnHeader {
292 impl<'a> HashStable<StableHashingContext<'a>> for hir::Ty {
293 fn hash_stable<W: StableHasherResult>(&self,
294 hcx: &mut StableHashingContext<'a>,
295 hasher: &mut StableHasher<W>) {
296 hcx.while_hashing_hir_bodies(true, |hcx| {
304 node.hash_stable(hcx, hasher);
305 span.hash_stable(hcx, hasher);
310 impl_stable_hash_for!(enum hir::PrimTy {
319 impl_stable_hash_for!(struct hir::BareFnTy {
327 impl_stable_hash_for!(struct hir::ExistTy {
333 impl_stable_hash_for!(enum hir::TyKind {
343 TraitObject(trait_refs, lifetime),
349 impl_stable_hash_for!(struct hir::FnDecl {
356 impl_stable_hash_for!(enum hir::FunctionRetTy {
361 impl_stable_hash_for!(struct hir::TraitRef {
362 // Don't hash the ref_id. It is tracked via the thing it is used to access
368 impl_stable_hash_for!(struct hir::PolyTraitRef {
369 bound_generic_params,
374 impl_stable_hash_for!(enum hir::QPath {
376 TypeRelative(t, path_segment)
379 impl_stable_hash_for!(struct hir::MacroDef {
389 impl_stable_hash_for!(struct hir::Block {
400 impl_stable_hash_for!(struct hir::Pat {
407 impl_stable_hash_for_spanned!(hir::FieldPat);
409 impl_stable_hash_for!(struct hir::FieldPat {
411 ident -> (ident.name),
416 impl_stable_hash_for!(enum hir::BindingAnnotation {
423 impl_stable_hash_for!(enum hir::RangeEnd {
428 impl_stable_hash_for!(enum hir::PatKind {
430 Binding(binding_mode, var, name, sub),
431 Struct(path, field_pats, dotdot),
432 TupleStruct(path, field_pats, dotdot),
434 Tuple(field_pats, dotdot),
436 Ref(sub, mutability),
438 Range(start, end, end_kind),
439 Slice(one, two, three)
442 impl_stable_hash_for!(enum hir::BinOpKind {
463 impl_stable_hash_for_spanned!(hir::BinOpKind);
465 impl_stable_hash_for!(enum hir::UnOp {
471 impl_stable_hash_for_spanned!(hir::StmtKind);
473 impl_stable_hash_for!(struct hir::Local {
484 impl_stable_hash_for_spanned!(hir::DeclKind);
485 impl_stable_hash_for!(enum hir::DeclKind {
490 impl_stable_hash_for!(struct hir::Arm {
497 impl_stable_hash_for!(enum hir::Guard {
501 impl_stable_hash_for!(struct hir::Field {
509 impl_stable_hash_for_spanned!(ast::Name);
512 impl_stable_hash_for!(enum hir::BlockCheckMode {
515 PushUnsafeBlock(src),
519 impl_stable_hash_for!(enum hir::UnsafeSource {
524 impl_stable_hash_for!(struct hir::AnonConst {
530 impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr {
531 fn hash_stable<W: StableHasherResult>(&self,
532 hcx: &mut StableHashingContext<'a>,
533 hasher: &mut StableHasher<W>) {
534 hcx.while_hashing_hir_bodies(true, |hcx| {
543 span.hash_stable(hcx, hasher);
544 node.hash_stable(hcx, hasher);
545 attrs.hash_stable(hcx, hasher);
550 impl_stable_hash_for!(enum hir::ExprKind {
554 MethodCall(segment, span, args),
556 Binary(op, lhs, rhs),
562 While(cond, body, label),
563 Loop(body, label, loop_src),
564 Match(matchee, arms, match_src),
565 Closure(capture_clause, decl, body_id, span, gen),
568 AssignOp(op, lhs, rhs),
572 AddrOf(mutability, sub),
573 Break(destination, sub),
574 Continue(destination),
576 InlineAsm(asm, inputs, outputs),
577 Struct(path, fields, base),
582 impl_stable_hash_for!(enum hir::LocalSource {
587 impl_stable_hash_for!(enum hir::LoopSource {
593 impl<'a> HashStable<StableHashingContext<'a>> for hir::MatchSource {
594 fn hash_stable<W: StableHasherResult>(&self,
595 hcx: &mut StableHashingContext<'a>,
596 hasher: &mut StableHasher<W>) {
597 use hir::MatchSource;
599 mem::discriminant(self).hash_stable(hcx, hasher);
601 MatchSource::Normal |
602 MatchSource::WhileLetDesugar |
603 MatchSource::ForLoopDesugar |
604 MatchSource::TryDesugar => {
605 // No fields to hash.
607 MatchSource::IfLetDesugar { contains_else_clause } => {
608 contains_else_clause.hash_stable(hcx, hasher);
614 impl_stable_hash_for!(enum hir::GeneratorMovability {
619 impl_stable_hash_for!(enum hir::CaptureClause {
624 impl_stable_hash_for_spanned!(usize);
626 impl_stable_hash_for!(struct hir::Destination {
631 impl_stable_hash_for_spanned!(ast::Ident);
633 impl_stable_hash_for!(enum hir::LoopIdError {
635 UnlabeledCfInWhileCondition,
639 impl_stable_hash_for!(struct ast::Ident {
644 impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem {
645 fn hash_stable<W: StableHasherResult>(&self,
646 hcx: &mut StableHashingContext<'a>,
647 hasher: &mut StableHasher<W>) {
658 hcx.hash_hir_item_like(|hcx| {
659 ident.name.hash_stable(hcx, hasher);
660 attrs.hash_stable(hcx, hasher);
661 generics.hash_stable(hcx, hasher);
662 node.hash_stable(hcx, hasher);
663 span.hash_stable(hcx, hasher);
668 impl_stable_hash_for!(enum hir::TraitMethod {
673 impl_stable_hash_for!(enum hir::TraitItemKind {
679 impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem {
680 fn hash_stable<W: StableHasherResult>(&self,
681 hcx: &mut StableHashingContext<'a>,
682 hasher: &mut StableHasher<W>) {
695 hcx.hash_hir_item_like(|hcx| {
696 ident.name.hash_stable(hcx, hasher);
697 vis.hash_stable(hcx, hasher);
698 defaultness.hash_stable(hcx, hasher);
699 attrs.hash_stable(hcx, hasher);
700 generics.hash_stable(hcx, hasher);
701 node.hash_stable(hcx, hasher);
702 span.hash_stable(hcx, hasher);
707 impl_stable_hash_for!(enum hir::ImplItemKind {
714 impl_stable_hash_for!(enum ::syntax::ast::CrateSugar {
719 impl<'a> HashStable<StableHashingContext<'a>> for hir::VisibilityKind {
720 fn hash_stable<W: StableHasherResult>(&self,
721 hcx: &mut StableHashingContext<'a>,
722 hasher: &mut StableHasher<W>) {
723 mem::discriminant(self).hash_stable(hcx, hasher);
725 hir::VisibilityKind::Public |
726 hir::VisibilityKind::Inherited => {
727 // No fields to hash.
729 hir::VisibilityKind::Crate(sugar) => {
730 sugar.hash_stable(hcx, hasher);
732 hir::VisibilityKind::Restricted { ref path, id, hir_id } => {
733 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
734 id.hash_stable(hcx, hasher);
735 hir_id.hash_stable(hcx, hasher);
737 path.hash_stable(hcx, hasher);
743 impl_stable_hash_for_spanned!(hir::VisibilityKind);
745 impl<'a> HashStable<StableHashingContext<'a>> for hir::Defaultness {
746 fn hash_stable<W: StableHasherResult>(&self,
747 hcx: &mut StableHashingContext<'a>,
748 hasher: &mut StableHasher<W>) {
749 mem::discriminant(self).hash_stable(hcx, hasher);
751 hir::Defaultness::Final => {
752 // No fields to hash.
754 hir::Defaultness::Default { has_value } => {
755 has_value.hash_stable(hcx, hasher);
761 impl_stable_hash_for!(enum hir::ImplPolarity {
766 impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod {
767 fn hash_stable<W: StableHasherResult>(&self,
768 hcx: &mut StableHashingContext<'a>,
769 hasher: &mut StableHasher<W>) {
771 inner: ref inner_span,
775 inner_span.hash_stable(hcx, hasher);
777 // Combining the DefPathHashes directly is faster than feeding them
778 // into the hasher. Because we use a commutative combine, we also don't
779 // have to sort the array.
780 let item_ids_hash = item_ids
783 let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx);
784 debug_assert_eq!(local_id, hir::ItemLocalId(0));
786 }).fold(Fingerprint::ZERO, |a, b| {
787 a.combine_commutative(b)
790 item_ids.len().hash_stable(hcx, hasher);
791 item_ids_hash.hash_stable(hcx, hasher);
795 impl_stable_hash_for!(struct hir::ForeignMod {
800 impl_stable_hash_for!(struct hir::EnumDef {
804 impl_stable_hash_for!(struct hir::VariantKind {
811 impl_stable_hash_for_spanned!(hir::VariantKind);
813 impl_stable_hash_for!(enum hir::UseKind {
819 impl_stable_hash_for!(struct hir::StructField {
821 ident -> (ident.name),
828 impl_stable_hash_for!(enum hir::VariantData {
834 impl<'a> HashStable<StableHashingContext<'a>> for hir::Item {
835 fn hash_stable<W: StableHasherResult>(&self,
836 hcx: &mut StableHashingContext<'a>,
837 hasher: &mut StableHasher<W>) {
848 hcx.hash_hir_item_like(|hcx| {
849 name.hash_stable(hcx, hasher);
850 attrs.hash_stable(hcx, hasher);
851 node.hash_stable(hcx, hasher);
852 vis.hash_stable(hcx, hasher);
853 span.hash_stable(hcx, hasher);
858 impl_stable_hash_for!(enum hir::ItemKind {
859 ExternCrate(orig_name),
861 Static(ty, mutability, body_id),
863 Fn(fn_decl, header, generics, body_id),
865 ForeignMod(foreign_mod),
866 GlobalAsm(global_asm),
869 Enum(enum_def, generics),
870 Struct(variant_data, generics),
871 Union(variant_data, generics),
872 Trait(is_auto, unsafety, generics, bounds, item_refs),
873 TraitAlias(generics, bounds),
874 Impl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
877 impl_stable_hash_for!(struct hir::TraitItemRef {
879 ident -> (ident.name),
885 impl_stable_hash_for!(struct hir::ImplItemRef {
887 ident -> (ident.name),
894 impl<'a> HashStable<StableHashingContext<'a>> for hir::AssociatedItemKind {
895 fn hash_stable<W: StableHasherResult>(&self,
896 hcx: &mut StableHashingContext<'a>,
897 hasher: &mut StableHasher<W>) {
898 mem::discriminant(self).hash_stable(hcx, hasher);
900 hir::AssociatedItemKind::Const |
901 hir::AssociatedItemKind::Existential |
902 hir::AssociatedItemKind::Type => {
903 // No fields to hash.
905 hir::AssociatedItemKind::Method { has_self } => {
906 has_self.hash_stable(hcx, hasher);
912 impl_stable_hash_for!(struct hir::ForeignItem {
921 impl_stable_hash_for!(enum hir::ForeignItemKind {
922 Fn(fn_decl, arg_names, generics),
923 Static(ty, is_mutbl),
927 impl_stable_hash_for!(enum hir::StmtKind {
933 impl_stable_hash_for!(struct hir::Arg {
939 impl<'a> HashStable<StableHashingContext<'a>> for hir::Body {
940 fn hash_stable<W: StableHasherResult>(&self,
941 hcx: &mut StableHashingContext<'a>,
942 hasher: &mut StableHasher<W>) {
949 hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| {
950 arguments.hash_stable(hcx, hasher);
951 value.hash_stable(hcx, hasher);
952 is_generator.hash_stable(hcx, hasher);
957 impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::BodyId {
958 type KeyType = (DefPathHash, hir::ItemLocalId);
961 fn to_stable_hash_key(&self,
962 hcx: &StableHashingContext<'a>)
963 -> (DefPathHash, hir::ItemLocalId) {
964 let hir::BodyId { node_id } = *self;
965 node_id.to_stable_hash_key(hcx)
969 impl_stable_hash_for!(struct hir::InlineAsmOutput {
975 impl_stable_hash_for!(struct hir::GlobalAsm {
977 ctxt -> _, // This is used for error reporting
980 impl_stable_hash_for!(struct hir::InlineAsm {
989 ctxt -> _, // This is used for error reporting
992 impl_stable_hash_for!(enum hir::def::CtorKind {
998 impl_stable_hash_for!(enum hir::def::NonMacroAttrKind {
1005 impl_stable_hash_for!(enum hir::def::Def {
1010 Existential(def_id),
1015 AssociatedTy(def_id),
1016 AssociatedExistential(def_id),
1019 SelfTy(trait_def_id, impl_def_id),
1023 Static(def_id, is_mutbl),
1024 StructCtor(def_id, ctor_kind),
1025 SelfCtor(impl_def_id),
1026 VariantCtor(def_id, ctor_kind),
1028 AssociatedConst(def_id),
1030 Upvar(def_id, index, expr_id),
1032 Macro(def_id, macro_kind),
1034 NonMacroAttr(attr_kind),
1038 impl_stable_hash_for!(enum hir::Mutability {
1043 impl_stable_hash_for!(enum hir::IsAuto {
1048 impl_stable_hash_for!(enum hir::Unsafety {
1053 impl_stable_hash_for!(enum hir::IsAsync {
1058 impl_stable_hash_for!(enum hir::Constness {
1063 impl<'a> HashStable<StableHashingContext<'a>> for hir::def_id::DefIndex {
1065 fn hash_stable<W: StableHasherResult>(&self,
1066 hcx: &mut StableHashingContext<'a>,
1067 hasher: &mut StableHasher<W>) {
1068 hcx.local_def_path_hash(*self).hash_stable(hcx, hasher);
1072 impl<'a> ToStableHashKey<StableHashingContext<'a>>
1073 for hir::def_id::DefIndex {
1074 type KeyType = DefPathHash;
1077 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
1078 hcx.local_def_path_hash(*self)
1082 impl_stable_hash_for!(struct hir::def::Export {
1089 impl_stable_hash_for!(struct ::middle::lib_features::LibFeatures {
1094 impl<'a> HashStable<StableHashingContext<'a>> for ::middle::lang_items::LangItem {
1095 fn hash_stable<W: StableHasherResult>(&self,
1096 _: &mut StableHashingContext<'a>,
1097 hasher: &mut StableHasher<W>) {
1098 ::std::hash::Hash::hash(self, hasher);
1102 impl_stable_hash_for!(struct ::middle::lang_items::LanguageItems {
1107 impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitCandidate {
1108 fn hash_stable<W: StableHasherResult>(&self,
1109 hcx: &mut StableHashingContext<'a>,
1110 hasher: &mut StableHasher<W>) {
1111 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
1112 let hir::TraitCandidate {
1117 def_id.hash_stable(hcx, hasher);
1118 import_id.hash_stable(hcx, hasher);
1123 impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::TraitCandidate {
1124 type KeyType = (DefPathHash, Option<(DefPathHash, hir::ItemLocalId)>);
1126 fn to_stable_hash_key(&self,
1127 hcx: &StableHashingContext<'a>)
1129 let hir::TraitCandidate {
1134 let import_id = import_id.map(|node_id| hcx.node_to_hir_id(node_id))
1135 .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner),
1137 (hcx.def_path_hash(def_id), import_id)
1141 impl_stable_hash_for!(struct hir::CodegenFnAttrs {
1151 impl<'hir> HashStable<StableHashingContext<'hir>> for hir::CodegenFnAttrFlags
1153 fn hash_stable<W: StableHasherResult>(&self,
1154 hcx: &mut StableHashingContext<'hir>,
1155 hasher: &mut StableHasher<W>) {
1156 self.bits().hash_stable(hcx, hasher);
1160 impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InlineAttr {
1161 fn hash_stable<W: StableHasherResult>(&self,
1162 hcx: &mut StableHashingContext<'hir>,
1163 hasher: &mut StableHasher<W>) {
1164 mem::discriminant(self).hash_stable(hcx, hasher);
1168 impl_stable_hash_for!(struct hir::Freevar {