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::def_id::DefId;
16 use ich::{StableHashingContext, NodeIdHashingMode};
21 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
24 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for DefId {
26 fn hash_stable<W: StableHasherResult>(&self,
27 hcx: &mut StableHashingContext<'a, 'tcx>,
28 hasher: &mut StableHasher<W>) {
29 hcx.def_path_hash(*self).hash_stable(hcx, hasher);
34 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::HirId {
36 fn hash_stable<W: StableHasherResult>(&self,
37 hcx: &mut StableHashingContext<'a, 'tcx>,
38 hasher: &mut StableHasher<W>) {
44 hcx.def_path_hash(DefId::local(owner)).hash_stable(hcx, hasher);
45 local_id.hash_stable(hcx, hasher);
49 impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index });
51 // The following implementations of HashStable for ItemId, TraitItemId, and
52 // ImplItemId deserve special attention. Normally we do not hash NodeIds within
53 // the HIR, since they just signify a HIR nodes own path. But ItemId et al
54 // are used when another item in the HIR is *referenced* and we certainly
55 // want to pick up on a reference changing its target, so we hash the NodeIds
58 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::ItemId {
59 fn hash_stable<W: StableHasherResult>(&self,
60 hcx: &mut StableHashingContext<'a, 'tcx>,
61 hasher: &mut StableHasher<W>) {
66 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
67 id.hash_stable(hcx, hasher);
72 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::TraitItemId {
73 fn hash_stable<W: StableHasherResult>(&self,
74 hcx: &mut StableHashingContext<'a, 'tcx>,
75 hasher: &mut StableHasher<W>) {
76 let hir::TraitItemId {
80 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
81 node_id.hash_stable(hcx, hasher);
86 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::ImplItemId {
87 fn hash_stable<W: StableHasherResult>(&self,
88 hcx: &mut StableHashingContext<'a, 'tcx>,
89 hasher: &mut StableHasher<W>) {
94 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
95 node_id.hash_stable(hcx, hasher);
100 impl_stable_hash_for!(struct hir::Lifetime {
106 impl_stable_hash_for!(struct hir::LifetimeDef {
112 impl_stable_hash_for!(struct hir::Path {
118 impl_stable_hash_for!(struct hir::PathSegment {
123 impl_stable_hash_for!(enum hir::PathParameters {
124 AngleBracketedParameters(data),
125 ParenthesizedParameters(data)
128 impl_stable_hash_for!(struct hir::AngleBracketedParameterData {
135 impl_stable_hash_for!(struct hir::ParenthesizedParameterData {
141 impl_stable_hash_for!(enum hir::TyParamBound {
142 TraitTyParamBound(poly_trait_ref, trait_bound_modifier),
143 RegionTyParamBound(lifetime)
146 impl_stable_hash_for!(enum hir::TraitBoundModifier {
151 impl_stable_hash_for!(struct hir::TyParam {
160 impl_stable_hash_for!(struct hir::Generics {
167 impl_stable_hash_for!(struct hir::WhereClause {
172 impl_stable_hash_for!(enum hir::WherePredicate {
173 BoundPredicate(pred),
174 RegionPredicate(pred),
178 impl_stable_hash_for!(struct hir::WhereBoundPredicate {
185 impl_stable_hash_for!(struct hir::WhereRegionPredicate {
191 impl_stable_hash_for!(struct hir::WhereEqPredicate {
198 impl_stable_hash_for!(struct hir::MutTy {
203 impl_stable_hash_for!(struct hir::MethodSig {
211 impl_stable_hash_for!(struct hir::TypeBinding {
218 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Ty {
219 fn hash_stable<W: StableHasherResult>(&self,
220 hcx: &mut StableHashingContext<'a, 'tcx>,
221 hasher: &mut StableHasher<W>) {
222 let node_id_hashing_mode = match self.node {
230 hir::TyTraitObject(..) |
231 hir::TyImplTrait(..) |
234 NodeIdHashingMode::Ignore
237 NodeIdHashingMode::HashTraitsInScope
241 hcx.while_hashing_hir_bodies(true, |hcx| {
248 hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
249 id.hash_stable(hcx, hasher);
251 node.hash_stable(hcx, hasher);
252 span.hash_stable(hcx, hasher);
257 impl_stable_hash_for!(enum hir::PrimTy {
266 impl_stable_hash_for!(struct hir::BareFnTy {
273 impl_stable_hash_for!(enum hir::Ty_ {
282 TyTraitObject(trait_refs, lifetime),
288 impl_stable_hash_for!(struct hir::FnDecl {
295 impl_stable_hash_for!(enum hir::FunctionRetTy {
300 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::TraitRef {
301 fn hash_stable<W: StableHasherResult>(&self,
302 hcx: &mut StableHashingContext<'a, 'tcx>,
303 hasher: &mut StableHasher<W>) {
309 path.hash_stable(hcx, hasher);
310 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashTraitsInScope, |hcx| {
311 ref_id.hash_stable(hcx, hasher);
317 impl_stable_hash_for!(struct hir::PolyTraitRef {
323 impl_stable_hash_for!(enum hir::QPath {
325 TypeRelative(t, path_segment)
328 impl_stable_hash_for!(struct hir::MacroDef {
337 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Block {
338 fn hash_stable<W: StableHasherResult>(&self,
339 hcx: &mut StableHashingContext<'a, 'tcx>,
340 hasher: &mut StableHasher<W>) {
350 let non_item_stmts = || stmts.iter().filter(|stmt| {
352 hir::StmtDecl(ref decl, _) => {
354 // If this is a declaration of a nested item, we don't
355 // want to leave any trace of it in the hash value, not
356 // even that it exists. Otherwise changing the position
357 // of nested items would invalidate the containing item
358 // even though that does not constitute a semantic
360 hir::DeclItem(_) => false,
361 hir::DeclLocal(_) => true
365 hir::StmtSemi(..) => true
369 let count = non_item_stmts().count();
371 count.hash_stable(hcx, hasher);
373 for stmt in non_item_stmts() {
374 stmt.hash_stable(hcx, hasher);
377 expr.hash_stable(hcx, hasher);
378 id.hash_stable(hcx, hasher);
379 rules.hash_stable(hcx, hasher);
380 span.hash_stable(hcx, hasher);
381 targeted_by_break.hash_stable(hcx, hasher);
385 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Pat {
386 fn hash_stable<W: StableHasherResult>(&self,
387 hcx: &mut StableHashingContext<'a, 'tcx>,
388 hasher: &mut StableHasher<W>) {
389 let node_id_hashing_mode = match self.node {
391 hir::PatKind::Binding(..) |
392 hir::PatKind::Tuple(..) |
393 hir::PatKind::Box(..) |
394 hir::PatKind::Ref(..) |
395 hir::PatKind::Lit(..) |
396 hir::PatKind::Range(..) |
397 hir::PatKind::Slice(..) => {
398 NodeIdHashingMode::Ignore
400 hir::PatKind::Path(..) |
401 hir::PatKind::Struct(..) |
402 hir::PatKind::TupleStruct(..) => {
403 NodeIdHashingMode::HashTraitsInScope
413 hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
414 id.hash_stable(hcx, hasher);
416 node.hash_stable(hcx, hasher);
417 span.hash_stable(hcx, hasher);
421 impl_stable_hash_for_spanned!(hir::FieldPat);
422 impl_stable_hash_for!(struct hir::FieldPat {
428 impl_stable_hash_for!(enum hir::BindingMode {
429 BindByRef(mutability),
430 BindByValue(mutability)
433 impl_stable_hash_for!(enum hir::RangeEnd {
438 impl_stable_hash_for!(enum hir::PatKind {
440 Binding(binding_mode, var, name, sub),
441 Struct(path, field_pats, dotdot),
442 TupleStruct(path, field_pats, dotdot),
444 Tuple(field_pats, dotdot),
446 Ref(sub, mutability),
448 Range(start, end, end_kind),
449 Slice(one, two, three)
452 impl_stable_hash_for!(enum hir::BinOp_ {
473 impl_stable_hash_for_spanned!(hir::BinOp_);
475 impl_stable_hash_for!(enum hir::UnOp {
481 impl_stable_hash_for_spanned!(hir::Stmt_);
483 impl_stable_hash_for!(struct hir::Local {
492 impl_stable_hash_for_spanned!(hir::Decl_);
493 impl_stable_hash_for!(enum hir::Decl_ {
498 impl_stable_hash_for!(struct hir::Arm {
505 impl_stable_hash_for!(struct hir::Field {
512 impl_stable_hash_for_spanned!(ast::Name);
515 impl_stable_hash_for!(enum hir::BlockCheckMode {
518 PushUnsafeBlock(src),
522 impl_stable_hash_for!(enum hir::UnsafeSource {
527 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Expr {
528 fn hash_stable<W: StableHasherResult>(&self,
529 hcx: &mut StableHashingContext<'a, 'tcx>,
530 hasher: &mut StableHasher<W>) {
531 hcx.while_hashing_hir_bodies(true, |hcx| {
539 let (spans_always_on, node_id_hashing_mode) = match *node {
550 hir::ExprClosure(..) |
552 hir::ExprAssign(..) |
553 hir::ExprTupField(..) |
554 hir::ExprAddrOf(..) |
558 hir::ExprInlineAsm(..) |
559 hir::ExprRepeat(..) |
560 hir::ExprTup(..) => {
561 // For these we only hash the span when debuginfo is on.
562 (false, NodeIdHashingMode::Ignore)
564 // For the following, spans might be significant because of
565 // panic messages indicating the source location.
566 hir::ExprBinary(op, ..) => {
567 (hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::Ignore)
569 hir::ExprUnary(op, _) => {
570 (hcx.unop_can_panic_at_runtime(op), NodeIdHashingMode::Ignore)
572 hir::ExprAssignOp(op, ..) => {
573 (hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::Ignore)
575 hir::ExprIndex(..) => {
576 (true, NodeIdHashingMode::Ignore)
578 // For these we don't care about the span, but want to hash the
580 hir::ExprMethodCall(..) |
582 hir::ExprStruct(..) |
583 hir::ExprField(..) => {
584 (false, NodeIdHashingMode::HashTraitsInScope)
588 hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
589 id.hash_stable(hcx, hasher);
593 hcx.while_hashing_spans(true, |hcx| {
594 span.hash_stable(hcx, hasher);
595 node.hash_stable(hcx, hasher);
596 attrs.hash_stable(hcx, hasher);
599 span.hash_stable(hcx, hasher);
600 node.hash_stable(hcx, hasher);
601 attrs.hash_stable(hcx, hasher);
607 impl_stable_hash_for!(enum hir::Expr_ {
610 ExprCall(callee, args),
611 ExprMethodCall(name, ts, args),
613 ExprBinary(op, lhs, rhs),
614 ExprUnary(op, operand),
618 ExprIf(cond, then, els),
619 ExprWhile(cond, body, label),
620 ExprLoop(body, label, loop_src),
621 ExprMatch(matchee, arms, match_src),
622 ExprClosure(capture_clause, decl, body_id, span),
624 ExprAssign(lhs, rhs),
625 ExprAssignOp(op, lhs, rhs),
626 ExprField(owner, field_name),
627 ExprTupField(owner, idx),
630 ExprAddrOf(mutability, sub),
631 ExprBreak(destination, sub),
632 ExprAgain(destination),
634 ExprInlineAsm(asm, inputs, outputs),
635 ExprStruct(path, fields, base),
636 ExprRepeat(val, times)
639 impl_stable_hash_for!(enum hir::LoopSource {
645 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::MatchSource {
646 fn hash_stable<W: StableHasherResult>(&self,
647 hcx: &mut StableHashingContext<'a, 'tcx>,
648 hasher: &mut StableHasher<W>) {
649 use hir::MatchSource;
651 mem::discriminant(self).hash_stable(hcx, hasher);
653 MatchSource::Normal |
654 MatchSource::WhileLetDesugar |
655 MatchSource::ForLoopDesugar |
656 MatchSource::TryDesugar => {
657 // No fields to hash.
659 MatchSource::IfLetDesugar { contains_else_clause } => {
660 contains_else_clause.hash_stable(hcx, hasher);
666 impl_stable_hash_for!(enum hir::CaptureClause {
671 impl_stable_hash_for_spanned!(usize);
673 impl_stable_hash_for!(struct hir::Destination {
678 impl_stable_hash_for_spanned!(ast::Ident);
680 impl_stable_hash_for!(enum hir::LoopIdResult {
685 impl_stable_hash_for!(enum hir::LoopIdError {
687 UnlabeledCfInWhileCondition,
691 impl_stable_hash_for!(enum hir::ScopeTarget {
696 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::Ident {
697 fn hash_stable<W: StableHasherResult>(&self,
698 hcx: &mut StableHashingContext<'a, 'tcx>,
699 hasher: &mut StableHasher<W>) {
702 ctxt: _ // Ignore this
705 name.hash_stable(hcx, hasher);
709 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::TraitItem {
710 fn hash_stable<W: StableHasherResult>(&self,
711 hcx: &mut StableHashingContext<'a, 'tcx>,
712 hasher: &mut StableHasher<W>) {
721 hcx.hash_hir_item_like(attrs, |hcx| {
722 id.hash_stable(hcx, hasher);
723 name.hash_stable(hcx, hasher);
724 attrs.hash_stable(hcx, hasher);
725 node.hash_stable(hcx, hasher);
726 span.hash_stable(hcx, hasher);
731 impl_stable_hash_for!(enum hir::TraitMethod {
736 impl_stable_hash_for!(enum hir::TraitItemKind {
742 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::ImplItem {
743 fn hash_stable<W: StableHasherResult>(&self,
744 hcx: &mut StableHashingContext<'a, 'tcx>,
745 hasher: &mut StableHasher<W>) {
756 hcx.hash_hir_item_like(attrs, |hcx| {
757 id.hash_stable(hcx, hasher);
758 name.hash_stable(hcx, hasher);
759 vis.hash_stable(hcx, hasher);
760 defaultness.hash_stable(hcx, hasher);
761 attrs.hash_stable(hcx, hasher);
762 node.hash_stable(hcx, hasher);
763 span.hash_stable(hcx, hasher);
768 impl_stable_hash_for!(enum hir::ImplItemKind {
774 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Visibility {
775 fn hash_stable<W: StableHasherResult>(&self,
776 hcx: &mut StableHashingContext<'a, 'tcx>,
777 hasher: &mut StableHasher<W>) {
778 mem::discriminant(self).hash_stable(hcx, hasher);
780 hir::Visibility::Public |
781 hir::Visibility::Crate |
782 hir::Visibility::Inherited => {
783 // No fields to hash.
785 hir::Visibility::Restricted { ref path, id } => {
786 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashTraitsInScope, |hcx| {
787 id.hash_stable(hcx, hasher);
789 path.hash_stable(hcx, hasher);
795 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Defaultness {
796 fn hash_stable<W: StableHasherResult>(&self,
797 hcx: &mut StableHashingContext<'a, 'tcx>,
798 hasher: &mut StableHasher<W>) {
799 mem::discriminant(self).hash_stable(hcx, hasher);
801 hir::Defaultness::Final => {
802 // No fields to hash.
804 hir::Defaultness::Default { has_value } => {
805 has_value.hash_stable(hcx, hasher);
811 impl_stable_hash_for!(enum hir::ImplPolarity {
816 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Mod {
817 fn hash_stable<W: StableHasherResult>(&self,
818 hcx: &mut StableHashingContext<'a, 'tcx>,
819 hasher: &mut StableHasher<W>) {
822 // We are not hashing the IDs of the items contained in the module.
823 // This is harmless and matches the current behavior but it's not
824 // actually correct. See issue #40876.
828 inner.hash_stable(hcx, hasher);
832 impl_stable_hash_for!(struct hir::ForeignMod {
837 impl_stable_hash_for!(struct hir::EnumDef {
841 impl_stable_hash_for!(struct hir::Variant_ {
848 impl_stable_hash_for_spanned!(hir::Variant_);
850 impl_stable_hash_for!(enum hir::UseKind {
856 impl_stable_hash_for!(struct hir::StructField {
865 impl_stable_hash_for!(enum hir::VariantData {
871 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Item {
872 fn hash_stable<W: StableHasherResult>(&self,
873 hcx: &mut StableHashingContext<'a, 'tcx>,
874 hasher: &mut StableHasher<W>) {
875 let node_id_hashing_mode = match self.node {
876 hir::ItemExternCrate(..) |
877 hir::ItemStatic(..) |
881 hir::ItemForeignMod(..) |
884 hir::ItemStruct(..) |
887 hir::ItemDefaultImpl(..) |
888 hir::ItemImpl(..) => {
889 NodeIdHashingMode::Ignore
891 hir::ItemUse(..) => {
892 NodeIdHashingMode::HashTraitsInScope
905 hcx.hash_hir_item_like(attrs, |hcx| {
906 hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
907 id.hash_stable(hcx, hasher);
909 name.hash_stable(hcx, hasher);
910 attrs.hash_stable(hcx, hasher);
911 node.hash_stable(hcx, hasher);
912 vis.hash_stable(hcx, hasher);
913 span.hash_stable(hcx, hasher);
918 impl_stable_hash_for!(enum hir::Item_ {
919 ItemExternCrate(name),
920 ItemUse(path, use_kind),
921 ItemStatic(ty, mutability, body_id),
922 ItemConst(ty, body_id),
923 ItemFn(fn_decl, unsafety, constness, abi, generics, body_id),
925 ItemForeignMod(foreign_mod),
926 ItemTy(ty, generics),
927 ItemEnum(enum_def, generics),
928 ItemStruct(variant_data, generics),
929 ItemUnion(variant_data, generics),
930 ItemTrait(unsafety, generics, bounds, item_refs),
931 ItemDefaultImpl(unsafety, trait_ref),
932 ItemImpl(unsafety, impl_polarity, generics, trait_ref, ty, impl_item_refs)
935 impl_stable_hash_for!(struct hir::TraitItemRef {
943 impl_stable_hash_for!(struct hir::ImplItemRef {
952 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::AssociatedItemKind {
953 fn hash_stable<W: StableHasherResult>(&self,
954 hcx: &mut StableHashingContext<'a, 'tcx>,
955 hasher: &mut StableHasher<W>) {
956 mem::discriminant(self).hash_stable(hcx, hasher);
958 hir::AssociatedItemKind::Const |
959 hir::AssociatedItemKind::Type => {
960 // No fields to hash.
962 hir::AssociatedItemKind::Method { has_self } => {
963 has_self.hash_stable(hcx, hasher);
969 impl_stable_hash_for!(struct hir::ForeignItem {
978 impl_stable_hash_for!(enum hir::ForeignItem_ {
979 ForeignItemFn(fn_decl, arg_names, generics),
980 ForeignItemStatic(ty, is_mutbl)
983 impl_stable_hash_for!(enum hir::Stmt_ {
989 impl_stable_hash_for!(struct hir::Arg {
994 impl_stable_hash_for!(struct hir::Body {
999 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::BodyId {
1000 fn hash_stable<W: StableHasherResult>(&self,
1001 hcx: &mut StableHashingContext<'a, 'tcx>,
1002 hasher: &mut StableHasher<W>) {
1003 if hcx.hash_bodies() {
1004 hcx.tcx().hir.body(*self).hash_stable(hcx, hasher);
1009 impl_stable_hash_for!(struct hir::InlineAsmOutput {
1015 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::InlineAsm {
1016 fn hash_stable<W: StableHasherResult>(&self,
1017 hcx: &mut StableHashingContext<'a, 'tcx>,
1018 hasher: &mut StableHasher<W>) {
1019 let hir::InlineAsm {
1028 ctxt: _, // This is used for error reporting
1031 asm.hash_stable(hcx, hasher);
1032 asm_str_style.hash_stable(hcx, hasher);
1033 outputs.hash_stable(hcx, hasher);
1034 inputs.hash_stable(hcx, hasher);
1035 clobbers.hash_stable(hcx, hasher);
1036 volatile.hash_stable(hcx, hasher);
1037 alignstack.hash_stable(hcx, hasher);
1038 dialect.hash_stable(hcx, hasher);
1042 impl_stable_hash_for!(enum hir::def::CtorKind {
1048 impl_stable_hash_for!(enum hir::def::Def {
1056 AssociatedTy(def_id),
1059 SelfTy(trait_def_id, impl_def_id),
1062 Static(def_id, is_mutbl),
1063 StructCtor(def_id, ctor_kind),
1064 VariantCtor(def_id, ctor_kind),
1066 AssociatedConst(def_id),
1068 Upvar(def_id, index, expr_id),
1070 Macro(def_id, macro_kind),
1074 impl_stable_hash_for!(enum hir::Mutability {
1080 impl_stable_hash_for!(enum hir::Unsafety {
1086 impl_stable_hash_for!(enum hir::Constness {
1091 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::def_id::DefIndex {
1093 fn hash_stable<W: StableHasherResult>(&self,
1094 hcx: &mut StableHashingContext<'a, 'tcx>,
1095 hasher: &mut StableHasher<W>) {
1096 DefId::local(*self).hash_stable(hcx, hasher);
1100 impl_stable_hash_for!(struct hir::def::Export {