1 use crate::ty::{self, FloatVarValue, InferConst, IntVarValue, Ty, TyCtxt};
2 use rustc_data_structures::unify::InPlace;
3 use rustc_data_structures::unify::{EqUnifyValue, NoError, UnificationTable, UnifyKey, UnifyValue};
4 use rustc_span::symbol::Symbol;
5 use rustc_span::{Span, DUMMY_SP};
9 use std::marker::PhantomData;
12 fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>;
15 impl UnifyKey for ty::IntVid {
16 type Value = Option<IntVarValue>;
17 fn index(&self) -> u32 {
20 fn from_index(i: u32) -> ty::IntVid {
21 ty::IntVid { index: i }
23 fn tag() -> &'static str {
28 impl EqUnifyValue for IntVarValue {}
30 #[derive(PartialEq, Copy, Clone, Debug)]
31 pub struct RegionVidKey {
32 /// The minimum region vid in the unification set. This is needed
33 /// to have a canonical name for a type to prevent infinite
35 pub min_vid: ty::RegionVid,
38 impl UnifyValue for RegionVidKey {
41 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
42 let min_vid = if value1.min_vid.index() < value2.min_vid.index() {
48 Ok(RegionVidKey { min_vid })
52 impl UnifyKey for ty::RegionVid {
53 type Value = RegionVidKey;
54 fn index(&self) -> u32 {
57 fn from_index(i: u32) -> ty::RegionVid {
58 ty::RegionVid::from(i)
60 fn tag() -> &'static str {
65 impl ToType for IntVarValue {
66 fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
68 ty::IntType(i) => tcx.mk_mach_int(i),
69 ty::UintType(i) => tcx.mk_mach_uint(i),
74 // Floating point type keys
76 impl UnifyKey for ty::FloatVid {
77 type Value = Option<FloatVarValue>;
78 fn index(&self) -> u32 {
81 fn from_index(i: u32) -> ty::FloatVid {
82 ty::FloatVid { index: i }
84 fn tag() -> &'static str {
89 impl EqUnifyValue for FloatVarValue {}
91 impl ToType for FloatVarValue {
92 fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
93 tcx.mk_mach_float(self.0)
99 #[derive(Copy, Clone, Debug)]
100 pub struct ConstVariableOrigin {
101 pub kind: ConstVariableOriginKind,
105 /// Reasons to create a const inference variable
106 #[derive(Copy, Clone, Debug)]
107 pub enum ConstVariableOriginKind {
110 ConstParameterDefinition(Symbol),
111 SubstitutionPlaceholder,
114 #[derive(Copy, Clone, Debug)]
115 pub enum ConstVariableValue<'tcx> {
116 Known { value: &'tcx ty::Const<'tcx> },
117 Unknown { universe: ty::UniverseIndex },
120 impl<'tcx> ConstVariableValue<'tcx> {
121 /// If this value is known, returns the const it is known to be.
122 /// Otherwise, `None`.
123 pub fn known(&self) -> Option<&'tcx ty::Const<'tcx>> {
125 ConstVariableValue::Unknown { .. } => None,
126 ConstVariableValue::Known { value } => Some(value),
130 pub fn is_unknown(&self) -> bool {
132 ConstVariableValue::Unknown { .. } => true,
133 ConstVariableValue::Known { .. } => false,
138 #[derive(Copy, Clone, Debug)]
139 pub struct ConstVarValue<'tcx> {
140 pub origin: ConstVariableOrigin,
141 pub val: ConstVariableValue<'tcx>,
144 impl<'tcx> UnifyKey for ty::ConstVid<'tcx> {
145 type Value = ConstVarValue<'tcx>;
146 fn index(&self) -> u32 {
149 fn from_index(i: u32) -> Self {
150 ty::ConstVid { index: i, phantom: PhantomData }
152 fn tag() -> &'static str {
157 impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
158 type Error = (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>);
160 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
161 let val = match (value1.val, value2.val) {
162 (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => {
163 bug!("equating two const variables, both of which have known values")
166 // If one side is known, prefer that one.
167 (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => {
170 (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => {
174 // If both sides are *unknown*, it hardly matters, does it?
176 ConstVariableValue::Unknown { universe: universe1 },
177 ConstVariableValue::Unknown { universe: universe2 },
179 // If we unify two unbound variables, ?T and ?U, then whatever
180 // value they wind up taking (which must be the same value) must
181 // be nameable by both universes. Therefore, the resulting
182 // universe is the minimum of the two universes, because that is
183 // the one which contains the fewest names in scope.
184 let universe = cmp::min(universe1, universe2);
185 Ok(ConstVariableValue::Unknown { universe })
190 origin: ConstVariableOrigin {
191 kind: ConstVariableOriginKind::ConstInference,
199 impl<'tcx> EqUnifyValue for &'tcx ty::Const<'tcx> {}
201 pub fn replace_if_possible(
202 mut table: RefMut<'_, UnificationTable<InPlace<ty::ConstVid<'tcx>>>>,
203 c: &'tcx ty::Const<'tcx>,
204 ) -> &'tcx ty::Const<'tcx> {
205 if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = c {
206 match table.probe_value(*vid).val.known() {