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