]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/infer/unify_key.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / infer / unify_key.rs
CommitLineData
5869c6ff 1use crate::ty::{self, InferConst, Ty, TyCtxt};
f9f354fc
XL
2use rustc_data_structures::snapshot_vec;
3use rustc_data_structures::undo_log::UndoLogs;
4use rustc_data_structures::unify::{
5 self, EqUnifyValue, InPlace, NoError, UnificationTable, UnifyKey, UnifyValue,
6};
1b1a35ee 7use rustc_span::def_id::DefId;
dfeec247 8use rustc_span::symbol::Symbol;
1b1a35ee 9use rustc_span::Span;
48663c56
XL
10
11use std::cmp;
12use std::marker::PhantomData;
d9579d0f 13
a7813a04 14pub 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 19pub struct UnifiedRegion<'tcx>(pub Option<ty::Region<'tcx>>);
0531ce1d 20
17df50a5
XL
21#[derive(PartialEq, Copy, Clone, Debug)]
22pub struct RegionVidKey<'tcx> {
23 pub vid: ty::RegionVid,
24 pub phantom: PhantomData<UnifiedRegion<'tcx>>,
25}
9cc50fc6 26
17df50a5
XL
27impl<'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
33impl<'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
48impl<'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 66impl 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 75impl 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)]
84pub 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
91pub enum ConstVariableOriginKind {
92 MiscVariable,
93 ConstInference,
1b1a35ee 94 ConstParameterDefinition(Symbol, DefId),
dc9dc135 95 SubstitutionPlaceholder,
48663c56
XL
96}
97
98#[derive(Copy, Clone, Debug)]
99pub enum ConstVariableValue<'tcx> {
5099ac24 100 Known { value: ty::Const<'tcx> },
48663c56
XL
101 Unknown { universe: ty::UniverseIndex },
102}
103
104impl<'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)]
116pub struct ConstVarValue<'tcx> {
117 pub origin: ConstVariableOrigin,
118 pub val: ConstVariableValue<'tcx>,
119}
120
121impl<'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
136impl<'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 169impl<'tcx> EqUnifyValue for ty::Const<'tcx> {}
48663c56 170
a2a8927a 171pub 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
175where
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}