]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/infer/unify_key.rs
New upstream version 1.59.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>;
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
46impl<'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 64impl 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 73impl 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)]
82pub 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
89pub enum ConstVariableOriginKind {
90 MiscVariable,
91 ConstInference,
1b1a35ee 92 ConstParameterDefinition(Symbol, DefId),
dc9dc135 93 SubstitutionPlaceholder,
48663c56
XL
94}
95
96#[derive(Copy, Clone, Debug)]
97pub enum ConstVariableValue<'tcx> {
98 Known { value: &'tcx ty::Const<'tcx> },
99 Unknown { universe: ty::UniverseIndex },
100}
101
102impl<'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)]
114pub struct ConstVarValue<'tcx> {
115 pub origin: ConstVariableOrigin,
116 pub val: ConstVariableValue<'tcx>,
117}
118
119impl<'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
132impl<'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
165impl<'tcx> EqUnifyValue for &'tcx ty::Const<'tcx> {}
166
a2a8927a 167pub 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>
171where
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}