]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/infer/unify_key.rs
remove `unify_key::replace_if_possible`
[rust.git] / compiler / rustc_middle / src / infer / unify_key.rs
1 use crate::ty::{self, Ty, TyCtxt};
2 use rustc_data_structures::unify::{EqUnifyValue, NoError, UnifyKey, UnifyValue};
3 use rustc_span::def_id::DefId;
4 use rustc_span::symbol::Symbol;
5 use rustc_span::Span;
6 use std::cmp;
7 use std::marker::PhantomData;
8
9 pub trait ToType {
10     fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>;
11 }
12
13 #[derive(PartialEq, Copy, Clone, Debug)]
14 pub struct UnifiedRegion<'tcx>(pub Option<ty::Region<'tcx>>);
15
16 #[derive(PartialEq, Copy, Clone, Debug)]
17 pub struct RegionVidKey<'tcx> {
18     pub vid: ty::RegionVid,
19     pub phantom: PhantomData<UnifiedRegion<'tcx>>,
20 }
21
22 impl<'tcx> From<ty::RegionVid> for RegionVidKey<'tcx> {
23     fn from(vid: ty::RegionVid) -> Self {
24         RegionVidKey { vid, phantom: PhantomData }
25     }
26 }
27
28 impl<'tcx> UnifyKey for RegionVidKey<'tcx> {
29     type Value = UnifiedRegion<'tcx>;
30     #[inline]
31     fn index(&self) -> u32 {
32         self.vid.as_u32()
33     }
34     #[inline]
35     fn from_index(i: u32) -> Self {
36         RegionVidKey::from(ty::RegionVid::from_u32(i))
37     }
38     fn tag() -> &'static str {
39         "RegionVidKey"
40     }
41 }
42
43 impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
44     type Error = NoError;
45
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,
52
53             (Some(_), _) => *value1,
54             (_, Some(_)) => *value2,
55
56             (None, None) => *value1,
57         })
58     }
59 }
60
61 impl ToType for ty::IntVarValue {
62     fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
63         match *self {
64             ty::IntType(i) => tcx.mk_mach_int(i),
65             ty::UintType(i) => tcx.mk_mach_uint(i),
66         }
67     }
68 }
69
70 impl ToType for ty::FloatVarValue {
71     fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
72         tcx.mk_mach_float(self.0)
73     }
74 }
75
76 // Generic consts.
77
78 #[derive(Copy, Clone, Debug)]
79 pub struct ConstVariableOrigin {
80     pub kind: ConstVariableOriginKind,
81     pub span: Span,
82 }
83
84 /// Reasons to create a const inference variable
85 #[derive(Copy, Clone, Debug)]
86 pub enum ConstVariableOriginKind {
87     MiscVariable,
88     ConstInference,
89     ConstParameterDefinition(Symbol, DefId),
90     SubstitutionPlaceholder,
91 }
92
93 #[derive(Copy, Clone, Debug)]
94 pub enum ConstVariableValue<'tcx> {
95     Known { value: ty::Const<'tcx> },
96     Unknown { universe: ty::UniverseIndex },
97 }
98
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>> {
103         match *self {
104             ConstVariableValue::Unknown { .. } => None,
105             ConstVariableValue::Known { value } => Some(value),
106         }
107     }
108 }
109
110 #[derive(Copy, Clone, Debug)]
111 pub struct ConstVarValue<'tcx> {
112     pub origin: ConstVariableOrigin,
113     pub val: ConstVariableValue<'tcx>,
114 }
115
116 impl<'tcx> UnifyKey for ty::ConstVid<'tcx> {
117     type Value = ConstVarValue<'tcx>;
118     #[inline]
119     fn index(&self) -> u32 {
120         self.index
121     }
122     #[inline]
123     fn from_index(i: u32) -> Self {
124         ty::ConstVid { index: i, phantom: PhantomData }
125     }
126     fn tag() -> &'static str {
127         "ConstVid"
128     }
129 }
130
131 impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
132     type Error = (ty::Const<'tcx>, ty::Const<'tcx>);
133
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")
138             }
139
140             // If one side is known, prefer that one.
141             (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => value1,
142             (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => value2,
143
144             // If both sides are *unknown*, it hardly matters, does it?
145             (
146                 ConstVariableValue::Unknown { universe: universe1 },
147                 ConstVariableValue::Unknown { universe: universe2 },
148             ) => {
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);
155                 ConstVarValue {
156                     val: ConstVariableValue::Unknown { universe },
157                     origin: value1.origin,
158                 }
159             }
160         })
161     }
162 }
163
164 impl<'tcx> EqUnifyValue for ty::Const<'tcx> {}