1 use crate::ty::{self, FloatVarValue, IntVarValue, Ty, TyCtxt, InferConst};
2 use crate::mir::interpret::ConstValue;
3 use rustc_data_structures::unify::{NoError, EqUnifyValue, UnifyKey, UnifyValue, UnificationTable};
4 use rustc_data_structures::unify::InPlace;
5 use syntax_pos::{Span, DUMMY_SP};
6 use syntax::symbol::InternedString;
9 use std::marker::PhantomData;
10 use std::cell::RefMut;
13 fn to_type<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>;
16 impl UnifyKey for ty::IntVid {
17 type Value = Option<IntVarValue>;
18 fn index(&self) -> u32 { self.index }
19 fn from_index(i: u32) -> ty::IntVid { ty::IntVid { index: i } }
20 fn tag() -> &'static str { "IntVid" }
23 impl EqUnifyValue for IntVarValue {}
25 #[derive(PartialEq, Copy, Clone, Debug)]
26 pub struct RegionVidKey {
27 /// The minimum region vid in the unification set. This is needed
28 /// to have a canonical name for a type to prevent infinite
30 pub min_vid: ty::RegionVid
33 impl UnifyValue for RegionVidKey {
36 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
37 let min_vid = if value1.min_vid.index() < value2.min_vid.index() {
43 Ok(RegionVidKey { min_vid })
47 impl UnifyKey for ty::RegionVid {
48 type Value = RegionVidKey;
49 fn index(&self) -> u32 { u32::from(*self) }
50 fn from_index(i: u32) -> ty::RegionVid { ty::RegionVid::from(i) }
51 fn tag() -> &'static str { "RegionVid" }
54 impl ToType for IntVarValue {
55 fn to_type<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
57 ty::IntType(i) => tcx.mk_mach_int(i),
58 ty::UintType(i) => tcx.mk_mach_uint(i),
63 // Floating point type keys
65 impl UnifyKey for ty::FloatVid {
66 type Value = Option<FloatVarValue>;
67 fn index(&self) -> u32 { self.index }
68 fn from_index(i: u32) -> ty::FloatVid { ty::FloatVid { index: i } }
69 fn tag() -> &'static str { "FloatVid" }
72 impl EqUnifyValue for FloatVarValue {}
74 impl ToType for FloatVarValue {
75 fn to_type<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
76 tcx.mk_mach_float(self.0)
82 /// Reasons to create a const inference variable
83 #[derive(Copy, Clone, Debug)]
84 pub enum ConstVariableOrigin {
87 ConstParameterDefinition(Span, InternedString),
88 SubstitutionPlaceholder(Span),
91 #[derive(Copy, Clone, Debug)]
92 pub enum ConstVariableValue<'tcx> {
93 Known { value: &'tcx ty::Const<'tcx> },
94 Unknown { universe: ty::UniverseIndex },
97 impl<'tcx> ConstVariableValue<'tcx> {
98 /// If this value is known, returns the const it is known to be.
99 /// Otherwise, `None`.
100 pub fn known(&self) -> Option<&'tcx ty::Const<'tcx>> {
102 ConstVariableValue::Unknown { .. } => None,
103 ConstVariableValue::Known { value } => Some(value),
107 pub fn is_unknown(&self) -> bool {
109 ConstVariableValue::Unknown { .. } => true,
110 ConstVariableValue::Known { .. } => false,
115 #[derive(Copy, Clone, Debug)]
116 pub struct ConstVarValue<'tcx> {
117 pub origin: ConstVariableOrigin,
118 pub val: ConstVariableValue<'tcx>,
121 impl<'tcx> UnifyKey for ty::ConstVid<'tcx> {
122 type Value = ConstVarValue<'tcx>;
123 fn index(&self) -> u32 { self.index }
124 fn from_index(i: u32) -> Self { ty::ConstVid { index: i, phantom: PhantomData } }
125 fn tag() -> &'static str { "ConstVid" }
128 impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
129 type Error = (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>);
131 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
132 let val = match (value1.val, value2.val) {
134 ConstVariableValue::Known { .. },
135 ConstVariableValue::Known { .. }
137 bug!("equating two const variables, both of which have known values")
140 // If one side is known, prefer that one.
141 (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => {
144 (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => {
148 // If both sides are *unknown*, it hardly matters, does it?
149 (ConstVariableValue::Unknown { universe: universe1 },
150 ConstVariableValue::Unknown { universe: universe2 }) => {
151 // If we unify two unbound variables, ?T and ?U, then whatever
152 // value they wind up taking (which must be the same value) must
153 // be nameable by both universes. Therefore, the resulting
154 // universe is the minimum of the two universes, because that is
155 // the one which contains the fewest names in scope.
156 let universe = cmp::min(universe1, universe2);
157 Ok(ConstVariableValue::Unknown { universe })
162 origin: ConstVariableOrigin::ConstInference(DUMMY_SP),
168 impl<'tcx> EqUnifyValue for &'tcx ty::Const<'tcx> {}
170 pub fn replace_if_possible(
171 mut table: RefMut<'_, UnificationTable<InPlace<ty::ConstVid<'tcx>>>>,
172 c: &'tcx ty::Const<'tcx>
173 ) -> &'tcx ty::Const<'tcx> {
174 if let ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } = c {
175 match table.probe_value(*vid).val.known() {