rustc_infer/infer/
unify_key.rs
1use std::cmp;
2use std::marker::PhantomData;
3
4use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue};
5use rustc_middle::{bug, ty};
6use rustc_span::Span;
7use rustc_span::def_id::DefId;
8
9#[derive(Copy, Clone, Debug)]
10pub(crate) enum RegionVariableValue<'tcx> {
11 Known { value: ty::Region<'tcx> },
12 Unknown { universe: ty::UniverseIndex },
13}
14
15#[derive(PartialEq, Copy, Clone, Debug)]
16pub(crate) struct RegionVidKey<'tcx> {
17 pub vid: ty::RegionVid,
18 pub phantom: PhantomData<RegionVariableValue<'tcx>>,
19}
20
21impl<'tcx> From<ty::RegionVid> for RegionVidKey<'tcx> {
22 fn from(vid: ty::RegionVid) -> Self {
23 RegionVidKey { vid, phantom: PhantomData }
24 }
25}
26
27impl<'tcx> UnifyKey for RegionVidKey<'tcx> {
28 type Value = RegionVariableValue<'tcx>;
29 #[inline]
30 fn index(&self) -> u32 {
31 self.vid.as_u32()
32 }
33 #[inline]
34 fn from_index(i: u32) -> Self {
35 RegionVidKey::from(ty::RegionVid::from_u32(i))
36 }
37 fn tag() -> &'static str {
38 "RegionVidKey"
39 }
40}
41
42pub(crate) struct RegionUnificationError;
43
44impl<'tcx> UnifyValue for RegionVariableValue<'tcx> {
45 type Error = RegionUnificationError;
46
47 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
48 match (*value1, *value2) {
49 (RegionVariableValue::Known { .. }, RegionVariableValue::Known { .. }) => {
50 Err(RegionUnificationError)
51 }
52
53 (RegionVariableValue::Known { value }, RegionVariableValue::Unknown { universe })
54 | (RegionVariableValue::Unknown { universe }, RegionVariableValue::Known { value }) => {
55 let universe_of_value = match value.kind() {
56 ty::ReStatic
57 | ty::ReErased
58 | ty::ReLateParam(..)
59 | ty::ReEarlyParam(..)
60 | ty::ReError(_) => ty::UniverseIndex::ROOT,
61 ty::RePlaceholder(placeholder) => placeholder.universe,
62 ty::ReVar(..) | ty::ReBound(..) => bug!("not a universal region"),
63 };
64
65 if universe.can_name(universe_of_value) {
66 Ok(RegionVariableValue::Known { value })
67 } else {
68 Err(RegionUnificationError)
69 }
70 }
71
72 (
73 RegionVariableValue::Unknown { universe: a },
74 RegionVariableValue::Unknown { universe: b },
75 ) => {
76 Ok(RegionVariableValue::Unknown { universe: a.min(b) })
82 }
83 }
84 }
85}
86
87#[derive(Copy, Clone, Debug)]
90pub struct ConstVariableOrigin {
91 pub span: Span,
92 pub param_def_id: Option<DefId>,
96}
97
98#[derive(Copy, Clone, Debug)]
99pub(crate) enum ConstVariableValue<'tcx> {
100 Known { value: ty::Const<'tcx> },
101 Unknown { origin: ConstVariableOrigin, universe: ty::UniverseIndex },
102}
103
104impl<'tcx> ConstVariableValue<'tcx> {
105 pub(crate) fn known(&self) -> Option<ty::Const<'tcx>> {
108 match *self {
109 ConstVariableValue::Unknown { .. } => None,
110 ConstVariableValue::Known { value } => Some(value),
111 }
112 }
113}
114
115#[derive(PartialEq, Copy, Clone, Debug)]
116pub(crate) struct ConstVidKey<'tcx> {
117 pub vid: ty::ConstVid,
118 pub phantom: PhantomData<ty::Const<'tcx>>,
119}
120
121impl<'tcx> From<ty::ConstVid> for ConstVidKey<'tcx> {
122 fn from(vid: ty::ConstVid) -> Self {
123 ConstVidKey { vid, phantom: PhantomData }
124 }
125}
126
127impl<'tcx> UnifyKey for ConstVidKey<'tcx> {
128 type Value = ConstVariableValue<'tcx>;
129 #[inline]
130 fn index(&self) -> u32 {
131 self.vid.as_u32()
132 }
133 #[inline]
134 fn from_index(i: u32) -> Self {
135 ConstVidKey::from(ty::ConstVid::from_u32(i))
136 }
137 fn tag() -> &'static str {
138 "ConstVidKey"
139 }
140}
141
142impl<'tcx> UnifyValue for ConstVariableValue<'tcx> {
143 type Error = NoError;
144
145 fn unify_values(&value1: &Self, &value2: &Self) -> Result<Self, Self::Error> {
146 match (value1, value2) {
147 (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => {
148 bug!("equating two const variables, both of which have known values")
149 }
150
151 (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => Ok(value1),
153 (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => Ok(value2),
154
155 (
157 ConstVariableValue::Unknown { origin, universe: universe1 },
158 ConstVariableValue::Unknown { origin: _, universe: universe2 },
159 ) => {
160 let universe = cmp::min(universe1, universe2);
166 Ok(ConstVariableValue::Unknown { origin, universe })
167 }
168 }
169 }
170}