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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! Proxies for Rustc types used within the PDG.
//!
//! Each type has an identical set of fields to the corresponding Rustc type.
//! Paralegal serializes the PDG into these types, which are read by downstream property checkers.

use serde::{Deserialize, Serialize};

#[cfg(feature = "rustc")]
use crate::{
    rustc::{def_id, hir, mir},
    rustc_impls::*,
};

/// Generates a struct that is a proxy for a Rustc type.
///
/// This works by telling Serde to the proxy struct as "remote" for the Rustc type.
/// Each field of the struct is either the actual Rustc type if the "rustc" feature is enabled,
/// or the proxy type otherwise.
macro_rules! proxy_struct {
    ($(
      $(#[$attr:meta])*
      $name:ident($rustc:expr) {
        $($field:ident : $rustc_ty:ty  => $proxy_ty:ty , $proxy_str:expr),*
      }
    )*) => {
        $(
            #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Serialize, Deserialize)]
            #[cfg_attr(feature = "rustc", serde(remote = $rustc))]
            $(#[$attr])*
            pub struct $name {
                $(
                    #[cfg(feature = "rustc")]
                    #[serde(with = $proxy_str)]
                    pub $field: $rustc_ty,
                    #[cfg(not(feature = "rustc"))]
                    pub $field: $proxy_ty,
                )*
            }
        )*
    }
}

/// Generates a struct that is a proxy for a Rustc index type.
macro_rules! proxy_index {
    ($(
        $(#[$attr:meta])*
        $name:ident($rustc:expr) from $fn:expr
    );*) => {
        $(
            #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Serialize, Deserialize)]
            #[cfg_attr(feature = "rustc", serde(remote = $rustc))]
            $(#[$attr])*
            pub struct $name {
                #[cfg_attr(feature = "rustc", serde(getter = $fn))]
                pub(crate) private: u32
            }

            #[cfg(not(feature = "rustc"))]
            impl $name {
                pub fn index(self) -> usize {
                    self.private as usize
                }
            }
        )*
    }
}

proxy_index! {
    /// Proxy for `mir::BasicBlock`
    BasicBlock("mir::BasicBlock") from "bbref_to_u32";

    /// Proxy for `hir::ItemLocalId`
    ItemLocalId("hir::ItemLocalId") from "item_local_id_as_u32";

    /// Proxy for `def_id::DefIndex`
    DefIndex("def_id::DefIndex") from "def_index_as_u32";

    /// Proxy for `hir::def_id::CrateNum`
    CrateNum("hir::def_id::CrateNum") from "crate_num_as_u32"
}

proxy_struct! {
    /// Proxy for `mir::Location`
    #[derive(PartialOrd, Ord)]
    Location("mir::Location") {
        block: mir::BasicBlock => BasicBlock, "BasicBlock",
        statement_index: usize => usize, "usize"
    }

    /// Proxy for `def_id::LocalDefId`
    LocalDefId("def_id::LocalDefId") {
        local_def_index: def_id::DefIndex => DefIndex, "DefIndex"
    }

    /// Proxy for `hir_id::OwnerHid`
    OwnerId("hir::hir_id::OwnerId") {
        def_id: def_id::LocalDefId => LocalDefId, "LocalDefId"
    }

    /// Proxy for `hir::HirId`
    HirId("hir::HirId") {
        owner: hir::OwnerId => OwnerId, "OwnerId",
        local_id: hir::ItemLocalId => ItemLocalId, "ItemLocalId"
    }

    /// Proxy for `hir::BodyId`
    BodyId("hir::BodyId") {
        hir_id: hir::HirId => HirId, "HirId"
    }

    #[derive(Ord, PartialOrd)]
    /// Proxy for `def_id::DefId`
    DefId("def_id::DefId") {
        index: def_id::DefIndex => DefIndex, "DefIndex",
        krate: hir::def_id::CrateNum => CrateNum, "CrateNum"
    }
}

impl HirId {
    fn index(self) -> (usize, usize) {
        (
            self.owner.def_id.local_def_index.index(),
            self.local_id.index(),
        )
    }
}

impl Ord for HirId {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        (self.index()).cmp(&(other.index()))
    }
}

impl PartialOrd for HirId {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

#[cfg(not(feature = "rustc"))]
pub(crate) const LOCAL_CRATE: CrateNum = CrateNum { private: 0 };

impl LocalDefId {
    #[cfg(not(feature = "rustc"))]
    pub fn to_def_id(self) -> DefId {
        DefId {
            index: self.local_def_index,
            krate: LOCAL_CRATE,
        }
    }
}