1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! This module contains `HashStable` implementations for various HIR data
//! types in no particular order.

use crate::ich::hcx::BodyResolver;
use crate::ich::{NodeIdHashingMode, StableHashingContext};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir as hir;
use std::mem;

impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
    #[inline]
    fn hash_hir_id(&mut self, hir_id: hir::HirId, hasher: &mut StableHasher) {
        let hcx = self;
        match hcx.hashing_controls.node_id_hashing_mode {
            NodeIdHashingMode::Ignore => {
                // Don't do anything.
            }
            NodeIdHashingMode::HashDefPath => {
                let hir::HirId { owner, local_id } = hir_id;

                hcx.local_def_path_hash(owner).hash_stable(hcx, hasher);
                local_id.hash_stable(hcx, hasher);
            }
        }
    }

    #[inline]
    fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) {
        let hcx = self;
        match hcx.body_resolver {
            BodyResolver::Forbidden => panic!("Hashing HIR bodies is forbidden."),
            BodyResolver::Traverse { hash_bodies: false, .. } => {}
            BodyResolver::Traverse { hash_bodies: true, owner, bodies } => {
                assert_eq!(id.hir_id.owner, owner);
                bodies[&id.hir_id.local_id].hash_stable(hcx, hasher);
            }
        }
    }

    #[inline]
    fn hash_reference_to_item(&mut self, id: hir::HirId, hasher: &mut StableHasher) {
        let hcx = self;

        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
            id.hash_stable(hcx, hasher);
        })
    }

    fn hash_hir_expr(&mut self, expr: &hir::Expr<'_>, hasher: &mut StableHasher) {
        self.while_hashing_hir_bodies(true, |hcx| {
            let hir::Expr { hir_id: _, ref span, ref kind } = *expr;

            span.hash_stable(hcx, hasher);
            kind.hash_stable(hcx, hasher);
        })
    }

    fn hash_hir_ty(&mut self, ty: &hir::Ty<'_>, hasher: &mut StableHasher) {
        self.while_hashing_hir_bodies(true, |hcx| {
            let hir::Ty { hir_id: _, ref kind, ref span } = *ty;

            kind.hash_stable(hcx, hasher);
            span.hash_stable(hcx, hasher);
        })
    }

    fn hash_hir_visibility_kind(
        &mut self,
        vis: &hir::VisibilityKind<'_>,
        hasher: &mut StableHasher,
    ) {
        let hcx = self;
        mem::discriminant(vis).hash_stable(hcx, hasher);
        match *vis {
            hir::VisibilityKind::Public | hir::VisibilityKind::Inherited => {
                // No fields to hash.
            }
            hir::VisibilityKind::Crate(sugar) => {
                sugar.hash_stable(hcx, hasher);
            }
            hir::VisibilityKind::Restricted { ref path, hir_id } => {
                hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
                    hir_id.hash_stable(hcx, hasher);
                });
                path.hash_stable(hcx, hasher);
            }
        }
    }

    #[inline]
    fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) {
        let prev_hash_node_ids = self.hashing_controls.node_id_hashing_mode;
        self.hashing_controls.node_id_hashing_mode = NodeIdHashingMode::Ignore;

        f(self);

        self.hashing_controls.node_id_hashing_mode = prev_hash_node_ids;
    }

    #[inline]
    fn hash_hir_trait_candidate(&mut self, tc: &hir::TraitCandidate, hasher: &mut StableHasher) {
        self.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
            let hir::TraitCandidate { def_id, import_ids } = tc;

            def_id.hash_stable(hcx, hasher);
            import_ids.hash_stable(hcx, hasher);
        });
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::Body<'_> {
    #[inline]
    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
        let hir::Body { params, value, generator_kind } = self;

        hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| {
            params.hash_stable(hcx, hasher);
            value.hash_stable(hcx, hasher);
            generator_kind.hash_stable(hcx, hasher);
        });
    }
}