1 use crate::ty::{self, FloatVarValue, InferConst, IntVarValue, Ty, TyCtxt};
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,
7 use rustc_span::symbol::Symbol;
8 use rustc_span::{Span, DUMMY_SP};
11 use std::marker::PhantomData;
14 fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>;
17 /// Raw `TyVid` are used as the unification key for `sub_relations`;
18 /// they carry no values.
19 impl UnifyKey for ty::TyVid {
21 fn index(&self) -> u32 {
24 fn from_index(i: u32) -> ty::TyVid {
25 ty::TyVid { index: i }
27 fn tag() -> &'static str {
32 impl UnifyKey for ty::IntVid {
33 type Value = Option<IntVarValue>;
34 fn index(&self) -> u32 {
37 fn from_index(i: u32) -> ty::IntVid {
38 ty::IntVid { index: i }
40 fn tag() -> &'static str {
45 impl EqUnifyValue for IntVarValue {}
47 #[derive(PartialEq, Copy, Clone, Debug)]
48 pub struct RegionVidKey {
49 /// The minimum region vid in the unification set. This is needed
50 /// to have a canonical name for a type to prevent infinite
52 pub min_vid: ty::RegionVid,
55 impl UnifyValue for RegionVidKey {
58 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
59 let min_vid = if value1.min_vid.index() < value2.min_vid.index() {
65 Ok(RegionVidKey { min_vid })
69 impl UnifyKey for ty::RegionVid {
70 type Value = RegionVidKey;
71 fn index(&self) -> u32 {
74 fn from_index(i: u32) -> ty::RegionVid {
75 ty::RegionVid::from(i)
77 fn tag() -> &'static str {
82 impl ToType for IntVarValue {
83 fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
85 ty::IntType(i) => tcx.mk_mach_int(i),
86 ty::UintType(i) => tcx.mk_mach_uint(i),
91 // Floating point type keys
93 impl UnifyKey for ty::FloatVid {
94 type Value = Option<FloatVarValue>;
95 fn index(&self) -> u32 {
98 fn from_index(i: u32) -> ty::FloatVid {
99 ty::FloatVid { index: i }
101 fn tag() -> &'static str {
106 impl EqUnifyValue for FloatVarValue {}
108 impl ToType for FloatVarValue {
109 fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
110 tcx.mk_mach_float(self.0)
116 #[derive(Copy, Clone, Debug)]
117 pub struct ConstVariableOrigin {
118 pub kind: ConstVariableOriginKind,
122 /// Reasons to create a const inference variable
123 #[derive(Copy, Clone, Debug)]
124 pub enum ConstVariableOriginKind {
127 // FIXME(const_generics): Consider storing the `DefId` of the param here.
128 ConstParameterDefinition(Symbol),
129 SubstitutionPlaceholder,
132 #[derive(Copy, Clone, Debug)]
133 pub enum ConstVariableValue<'tcx> {
134 Known { value: &'tcx ty::Const<'tcx> },
135 Unknown { universe: ty::UniverseIndex },
138 impl<'tcx> ConstVariableValue<'tcx> {
139 /// If this value is known, returns the const it is known to be.
140 /// Otherwise, `None`.
141 pub fn known(&self) -> Option<&'tcx ty::Const<'tcx>> {
143 ConstVariableValue::Unknown { .. } => None,
144 ConstVariableValue::Known { value } => Some(value),
148 pub fn is_unknown(&self) -> bool {
150 ConstVariableValue::Unknown { .. } => true,
151 ConstVariableValue::Known { .. } => false,
156 #[derive(Copy, Clone, Debug)]
157 pub struct ConstVarValue<'tcx> {
158 pub origin: ConstVariableOrigin,
159 pub val: ConstVariableValue<'tcx>,
162 impl<'tcx> UnifyKey for ty::ConstVid<'tcx> {
163 type Value = ConstVarValue<'tcx>;
164 fn index(&self) -> u32 {
167 fn from_index(i: u32) -> Self {
168 ty::ConstVid { index: i, phantom: PhantomData }
170 fn tag() -> &'static str {
175 impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
176 type Error = (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>);
178 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
179 let val = match (value1.val, value2.val) {
180 (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => {
181 bug!("equating two const variables, both of which have known values")
184 // If one side is known, prefer that one.
185 (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => {
188 (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => {
192 // If both sides are *unknown*, it hardly matters, does it?
194 ConstVariableValue::Unknown { universe: universe1 },
195 ConstVariableValue::Unknown { universe: universe2 },
197 // If we unify two unbound variables, ?T and ?U, then whatever
198 // value they wind up taking (which must be the same value) must
199 // be nameable by both universes. Therefore, the resulting
200 // universe is the minimum of the two universes, because that is
201 // the one which contains the fewest names in scope.
202 let universe = cmp::min(universe1, universe2);
203 Ok(ConstVariableValue::Unknown { universe })
208 origin: ConstVariableOrigin {
209 kind: ConstVariableOriginKind::ConstInference,
217 impl<'tcx> EqUnifyValue for &'tcx ty::Const<'tcx> {}
219 pub fn replace_if_possible<V, L>(
220 table: &mut UnificationTable<InPlace<ty::ConstVid<'tcx>, V, L>>,
221 c: &'tcx ty::Const<'tcx>,
222 ) -> &'tcx ty::Const<'tcx>
224 V: snapshot_vec::VecLike<unify::Delegate<ty::ConstVid<'tcx>>>,
225 L: UndoLogs<snapshot_vec::UndoLog<unify::Delegate<ty::ConstVid<'tcx>>>>,
227 if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = c {
228 match table.probe_value(*vid).val.known() {