hir_ty/next_solver/infer/
unify_key.rs1use std::cmp;
4use std::marker::PhantomData;
5
6use ena::unify::{NoError, UnifyKey, UnifyValue};
7use rustc_type_ir::{ConstVid, RegionKind, RegionVid, UniverseIndex, inherent::IntoKind};
8
9use crate::{
10 Span,
11 next_solver::{Const, Region},
12};
13
14#[derive(Clone, Copy, Debug)]
15pub(crate) enum RegionVariableValue<'db> {
16 Known { value: Region<'db>, span: Option<Span> },
17 Unknown { universe: UniverseIndex, span: Span },
18}
19
20#[derive(PartialEq, Copy, Clone, Debug)]
21pub(crate) struct RegionVidKey<'db> {
22 pub(crate) vid: RegionVid,
23 pub(crate) phantom: PhantomData<RegionVariableValue<'db>>,
24}
25
26impl<'db> From<RegionVid> for RegionVidKey<'db> {
27 fn from(vid: RegionVid) -> Self {
28 RegionVidKey { vid, phantom: PhantomData }
29 }
30}
31
32impl<'db> UnifyKey for RegionVidKey<'db> {
33 type Value = RegionVariableValue<'db>;
34 #[inline]
35 fn index(&self) -> u32 {
36 self.vid.as_u32()
37 }
38 #[inline]
39 fn from_index(i: u32) -> Self {
40 RegionVidKey::from(RegionVid::from_u32(i))
41 }
42 fn tag() -> &'static str {
43 "RegionVidKey"
44 }
45}
46
47pub(crate) struct RegionUnificationError;
48impl<'db> UnifyValue for RegionVariableValue<'db> {
49 type Error = RegionUnificationError;
50
51 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
52 match (value1, value2) {
53 (RegionVariableValue::Known { .. }, RegionVariableValue::Known { .. }) => {
54 Err(RegionUnificationError)
55 }
56
57 (
58 &RegionVariableValue::Known { value, span: span_known },
59 &RegionVariableValue::Unknown { universe, span: span_unknown },
60 )
61 | (
62 &RegionVariableValue::Unknown { universe, span: span_unknown },
63 &RegionVariableValue::Known { value, span: span_known },
64 ) => {
65 let universe_of_value = match value.kind() {
66 RegionKind::ReStatic
67 | RegionKind::ReErased
68 | RegionKind::ReLateParam(..)
69 | RegionKind::ReEarlyParam(..)
70 | RegionKind::ReError(_) => UniverseIndex::ROOT,
71 RegionKind::RePlaceholder(placeholder) => placeholder.universe,
72 RegionKind::ReVar(..) | RegionKind::ReBound(..) => {
73 panic!("not a universal region")
74 }
75 };
76
77 let span = match span_known {
78 Some(span_known) => Span::pick_best(span_known, span_unknown),
79 None => span_unknown,
80 };
81 if universe.can_name(universe_of_value) {
82 Ok(RegionVariableValue::Known { value, span: Some(span) })
83 } else {
84 Err(RegionUnificationError)
85 }
86 }
87
88 (
89 &RegionVariableValue::Unknown { universe: a, span: span1 },
90 &RegionVariableValue::Unknown { universe: b, span: span2 },
91 ) => {
92 let span = Span::pick_best(span1, span2);
98 Ok(RegionVariableValue::Unknown { universe: a.min(b), span })
99 }
100 }
101 }
102}
103
104#[derive(Clone, Copy, Debug)]
107pub(crate) enum ConstVariableValue<'db> {
108 Known { value: Const<'db> },
109 Unknown { span: Span, universe: UniverseIndex },
110}
111
112impl<'db> ConstVariableValue<'db> {
113 pub(crate) fn known(&self) -> Option<Const<'db>> {
116 match self {
117 ConstVariableValue::Unknown { .. } => None,
118 ConstVariableValue::Known { value } => Some(*value),
119 }
120 }
121}
122
123#[derive(PartialEq, Copy, Clone, Debug)]
124pub(crate) struct ConstVidKey<'db> {
125 pub(crate) vid: ConstVid,
126 pub(crate) phantom: PhantomData<Const<'db>>,
127}
128
129impl<'db> From<ConstVid> for ConstVidKey<'db> {
130 fn from(vid: ConstVid) -> Self {
131 ConstVidKey { vid, phantom: PhantomData }
132 }
133}
134
135impl<'db> UnifyKey for ConstVidKey<'db> {
136 type Value = ConstVariableValue<'db>;
137 #[inline]
138 fn index(&self) -> u32 {
139 self.vid.as_u32()
140 }
141 #[inline]
142 fn from_index(i: u32) -> Self {
143 ConstVidKey::from(ConstVid::from_u32(i))
144 }
145 fn tag() -> &'static str {
146 "ConstVidKey"
147 }
148}
149
150impl<'db> UnifyValue for ConstVariableValue<'db> {
151 type Error = NoError;
152
153 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
154 match (value1, value2) {
155 (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => {
156 panic!("equating two const variables, both of which have known values")
157 }
158
159 (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => Ok(*value1),
161 (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => Ok(*value2),
162
163 (
165 &ConstVariableValue::Unknown { span: span1, universe: universe1 },
166 &ConstVariableValue::Unknown { span: span2, universe: universe2 },
167 ) => {
168 let universe = cmp::min(universe1, universe2);
174 let span = Span::pick_best(span1, span2);
175 Ok(ConstVariableValue::Unknown { span, universe })
176 }
177 }
178 }
179}