1 use crate::ty::{self, Ty, TyCtxt};
2 use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue};
3 use rustc_span::def_id::DefId;
4 use rustc_span::symbol::Symbol;
7 use std::marker::PhantomData;
10 fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>;
13 #[derive(PartialEq, Copy, Clone, Debug)]
14 pub struct UnifiedRegion<'tcx>(pub Option<ty::Region<'tcx>>);
16 #[derive(PartialEq, Copy, Clone, Debug)]
17 pub struct RegionVidKey<'tcx> {
18 pub vid: ty::RegionVid,
19 pub phantom: PhantomData<UnifiedRegion<'tcx>>,
22 impl<'tcx> From<ty::RegionVid> for RegionVidKey<'tcx> {
23 fn from(vid: ty::RegionVid) -> Self {
24 RegionVidKey { vid, phantom: PhantomData }
28 impl<'tcx> UnifyKey for RegionVidKey<'tcx> {
29 type Value = UnifiedRegion<'tcx>;
31 fn index(&self) -> u32 {
35 fn from_index(i: u32) -> Self {
36 RegionVidKey::from(ty::RegionVid::from_u32(i))
38 fn tag() -> &'static str {
43 impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
46 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
47 Ok(match (value1.0, value2.0) {
48 // Here we can just pick one value, because the full constraints graph
49 // will be handled later. Ideally, we might want a `MultipleValues`
50 // variant or something. For now though, this is fine.
51 (Some(_), Some(_)) => *value1,
53 (Some(_), _) => *value1,
54 (_, Some(_)) => *value2,
56 (None, None) => *value1,
61 impl ToType for ty::IntVarValue {
62 fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
64 ty::IntType(i) => tcx.mk_mach_int(i),
65 ty::UintType(i) => tcx.mk_mach_uint(i),
70 impl ToType for ty::FloatVarValue {
71 fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
72 tcx.mk_mach_float(self.0)
78 #[derive(Copy, Clone, Debug)]
79 pub struct ConstVariableOrigin {
80 pub kind: ConstVariableOriginKind,
84 /// Reasons to create a const inference variable
85 #[derive(Copy, Clone, Debug)]
86 pub enum ConstVariableOriginKind {
89 ConstParameterDefinition(Symbol, DefId),
90 SubstitutionPlaceholder,
93 #[derive(Copy, Clone, Debug)]
94 pub enum ConstVariableValue<'tcx> {
95 Known { value: ty::Const<'tcx> },
96 Unknown { universe: ty::UniverseIndex },
99 impl<'tcx> ConstVariableValue<'tcx> {
100 /// If this value is known, returns the const it is known to be.
101 /// Otherwise, `None`.
102 pub fn known(&self) -> Option<ty::Const<'tcx>> {
104 ConstVariableValue::Unknown { .. } => None,
105 ConstVariableValue::Known { value } => Some(value),
110 #[derive(Copy, Clone, Debug)]
111 pub struct ConstVarValue<'tcx> {
112 pub origin: ConstVariableOrigin,
113 pub val: ConstVariableValue<'tcx>,
116 impl<'tcx> UnifyKey for ty::ConstVid<'tcx> {
117 type Value = ConstVarValue<'tcx>;
119 fn index(&self) -> u32 {
123 fn from_index(i: u32) -> Self {
124 ty::ConstVid { index: i, phantom: PhantomData }
126 fn tag() -> &'static str {
131 impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
132 type Error = (ty::Const<'tcx>, ty::Const<'tcx>);
134 fn unify_values(&value1: &Self, &value2: &Self) -> Result<Self, Self::Error> {
135 Ok(match (value1.val, value2.val) {
136 (ConstVariableValue::Known { .. }, 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 { .. }) => value1,
142 (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => value2,
144 // If both sides are *unknown*, it hardly matters, does it?
146 ConstVariableValue::Unknown { universe: universe1 },
147 ConstVariableValue::Unknown { universe: universe2 },
149 // If we unify two unbound variables, ?T and ?U, then whatever
150 // value they wind up taking (which must be the same value) must
151 // be nameable by both universes. Therefore, the resulting
152 // universe is the minimum of the two universes, because that is
153 // the one which contains the fewest names in scope.
154 let universe = cmp::min(universe1, universe2);
156 val: ConstVariableValue::Unknown { universe },
157 origin: value1.origin,