]>
Commit | Line | Data |
---|---|---|
5869c6ff | 1 | use crate::ty::{self, InferConst, Ty, TyCtxt}; |
f9f354fc XL |
2 | use rustc_data_structures::snapshot_vec; |
3 | use rustc_data_structures::undo_log::UndoLogs; | |
4 | use rustc_data_structures::unify::{ | |
5 | self, EqUnifyValue, InPlace, NoError, UnificationTable, UnifyKey, UnifyValue, | |
6 | }; | |
1b1a35ee | 7 | use rustc_span::def_id::DefId; |
dfeec247 | 8 | use rustc_span::symbol::Symbol; |
1b1a35ee | 9 | use rustc_span::Span; |
48663c56 XL |
10 | |
11 | use std::cmp; | |
12 | use std::marker::PhantomData; | |
d9579d0f | 13 | |
a7813a04 | 14 | pub trait ToType { |
dc9dc135 | 15 | fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; |
d9579d0f AL |
16 | } |
17 | ||
9cc50fc6 | 18 | #[derive(PartialEq, Copy, Clone, Debug)] |
17df50a5 | 19 | pub struct UnifiedRegion<'tcx>(pub Option<ty::Region<'tcx>>); |
0531ce1d | 20 | |
17df50a5 XL |
21 | #[derive(PartialEq, Copy, Clone, Debug)] |
22 | pub struct RegionVidKey<'tcx> { | |
23 | pub vid: ty::RegionVid, | |
24 | pub phantom: PhantomData<UnifiedRegion<'tcx>>, | |
25 | } | |
9cc50fc6 | 26 | |
17df50a5 XL |
27 | impl<'tcx> From<ty::RegionVid> for RegionVidKey<'tcx> { |
28 | fn from(vid: ty::RegionVid) -> Self { | |
29 | RegionVidKey { vid, phantom: PhantomData } | |
9cc50fc6 SL |
30 | } |
31 | } | |
32 | ||
17df50a5 XL |
33 | impl<'tcx> UnifyKey for RegionVidKey<'tcx> { |
34 | type Value = UnifiedRegion<'tcx>; | |
5099ac24 | 35 | #[inline] |
dfeec247 | 36 | fn index(&self) -> u32 { |
17df50a5 | 37 | self.vid.as_u32() |
dfeec247 | 38 | } |
5099ac24 | 39 | #[inline] |
17df50a5 XL |
40 | fn from_index(i: u32) -> Self { |
41 | RegionVidKey::from(ty::RegionVid::from_u32(i)) | |
dfeec247 XL |
42 | } |
43 | fn tag() -> &'static str { | |
17df50a5 XL |
44 | "RegionVidKey" |
45 | } | |
46 | } | |
47 | ||
48 | impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { | |
49 | type Error = NoError; | |
50 | ||
51 | fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> { | |
52 | Ok(match (value1.0, value2.0) { | |
53 | // Here we can just pick one value, because the full constraints graph | |
54 | // will be handled later. Ideally, we might want a `MultipleValues` | |
55 | // variant or something. For now though, this is fine. | |
56 | (Some(_), Some(_)) => *value1, | |
57 | ||
58 | (Some(_), _) => *value1, | |
59 | (_, Some(_)) => *value2, | |
60 | ||
61 | (None, None) => *value1, | |
62 | }) | |
dfeec247 | 63 | } |
9cc50fc6 SL |
64 | } |
65 | ||
5869c6ff | 66 | impl ToType for ty::IntVarValue { |
dc9dc135 | 67 | fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { |
d9579d0f | 68 | match *self { |
c1a9b12d SL |
69 | ty::IntType(i) => tcx.mk_mach_int(i), |
70 | ty::UintType(i) => tcx.mk_mach_uint(i), | |
d9579d0f AL |
71 | } |
72 | } | |
73 | } | |
74 | ||
5869c6ff | 75 | impl ToType for ty::FloatVarValue { |
dc9dc135 | 76 | fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { |
0531ce1d XL |
77 | tcx.mk_mach_float(self.0) |
78 | } | |
54a0048b | 79 | } |
48663c56 XL |
80 | |
81 | // Generic consts. | |
82 | ||
dc9dc135 XL |
83 | #[derive(Copy, Clone, Debug)] |
84 | pub struct ConstVariableOrigin { | |
85 | pub kind: ConstVariableOriginKind, | |
86 | pub span: Span, | |
87 | } | |
88 | ||
48663c56 XL |
89 | /// Reasons to create a const inference variable |
90 | #[derive(Copy, Clone, Debug)] | |
dc9dc135 XL |
91 | pub enum ConstVariableOriginKind { |
92 | MiscVariable, | |
93 | ConstInference, | |
1b1a35ee | 94 | ConstParameterDefinition(Symbol, DefId), |
dc9dc135 | 95 | SubstitutionPlaceholder, |
48663c56 XL |
96 | } |
97 | ||
98 | #[derive(Copy, Clone, Debug)] | |
99 | pub enum ConstVariableValue<'tcx> { | |
5099ac24 | 100 | Known { value: ty::Const<'tcx> }, |
48663c56 XL |
101 | Unknown { universe: ty::UniverseIndex }, |
102 | } | |
103 | ||
104 | impl<'tcx> ConstVariableValue<'tcx> { | |
105 | /// If this value is known, returns the const it is known to be. | |
106 | /// Otherwise, `None`. | |
5099ac24 | 107 | pub fn known(&self) -> Option<ty::Const<'tcx>> { |
48663c56 XL |
108 | match *self { |
109 | ConstVariableValue::Unknown { .. } => None, | |
110 | ConstVariableValue::Known { value } => Some(value), | |
111 | } | |
112 | } | |
48663c56 XL |
113 | } |
114 | ||
115 | #[derive(Copy, Clone, Debug)] | |
116 | pub struct ConstVarValue<'tcx> { | |
117 | pub origin: ConstVariableOrigin, | |
118 | pub val: ConstVariableValue<'tcx>, | |
119 | } | |
120 | ||
121 | impl<'tcx> UnifyKey for ty::ConstVid<'tcx> { | |
122 | type Value = ConstVarValue<'tcx>; | |
5099ac24 | 123 | #[inline] |
dfeec247 XL |
124 | fn index(&self) -> u32 { |
125 | self.index | |
126 | } | |
5099ac24 | 127 | #[inline] |
dfeec247 XL |
128 | fn from_index(i: u32) -> Self { |
129 | ty::ConstVid { index: i, phantom: PhantomData } | |
130 | } | |
131 | fn tag() -> &'static str { | |
132 | "ConstVid" | |
133 | } | |
48663c56 XL |
134 | } |
135 | ||
136 | impl<'tcx> UnifyValue for ConstVarValue<'tcx> { | |
5099ac24 | 137 | type Error = (ty::Const<'tcx>, ty::Const<'tcx>); |
48663c56 | 138 | |
29967ef6 XL |
139 | fn unify_values(&value1: &Self, &value2: &Self) -> Result<Self, Self::Error> { |
140 | Ok(match (value1.val, value2.val) { | |
dfeec247 | 141 | (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => { |
48663c56 XL |
142 | bug!("equating two const variables, both of which have known values") |
143 | } | |
144 | ||
145 | // If one side is known, prefer that one. | |
29967ef6 XL |
146 | (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => value1, |
147 | (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => value2, | |
48663c56 XL |
148 | |
149 | // If both sides are *unknown*, it hardly matters, does it? | |
dfeec247 XL |
150 | ( |
151 | ConstVariableValue::Unknown { universe: universe1 }, | |
152 | ConstVariableValue::Unknown { universe: universe2 }, | |
153 | ) => { | |
48663c56 XL |
154 | // If we unify two unbound variables, ?T and ?U, then whatever |
155 | // value they wind up taking (which must be the same value) must | |
156 | // be nameable by both universes. Therefore, the resulting | |
157 | // universe is the minimum of the two universes, because that is | |
158 | // the one which contains the fewest names in scope. | |
159 | let universe = cmp::min(universe1, universe2); | |
29967ef6 XL |
160 | ConstVarValue { |
161 | val: ConstVariableValue::Unknown { universe }, | |
162 | origin: value1.origin, | |
163 | } | |
48663c56 | 164 | } |
48663c56 XL |
165 | }) |
166 | } | |
167 | } | |
168 | ||
5099ac24 | 169 | impl<'tcx> EqUnifyValue for ty::Const<'tcx> {} |
48663c56 | 170 | |
a2a8927a | 171 | pub fn replace_if_possible<'tcx, V, L>( |
f9f354fc | 172 | table: &mut UnificationTable<InPlace<ty::ConstVid<'tcx>, V, L>>, |
5099ac24 FG |
173 | c: ty::Const<'tcx>, |
174 | ) -> ty::Const<'tcx> | |
f9f354fc XL |
175 | where |
176 | V: snapshot_vec::VecLike<unify::Delegate<ty::ConstVid<'tcx>>>, | |
177 | L: UndoLogs<snapshot_vec::UndoLog<unify::Delegate<ty::ConstVid<'tcx>>>>, | |
178 | { | |
5099ac24 FG |
179 | if let ty::ConstKind::Infer(InferConst::Var(vid)) = c.val() { |
180 | match table.probe_value(vid).val.known() { | |
48663c56 XL |
181 | Some(c) => c, |
182 | None => c, | |
183 | } | |
184 | } else { | |
185 | c | |
186 | } | |
187 | } |