Skip to main content

rustc_infer/infer/
unify_key.rs

1use std::cmp;
2use std::marker::PhantomData;
3
4use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue};
5use rustc_middle::{bug, ty};
6use rustc_span::Span;
7use rustc_span::def_id::DefId;
8
9#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for RegionVariableValue<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for RegionVariableValue<'tcx> {
    #[inline]
    fn clone(&self) -> RegionVariableValue<'tcx> {
        let _: ::core::clone::AssertParamIsClone<ty::Region<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<ty::UniverseIndex>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for RegionVariableValue<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            RegionVariableValue::Known { value: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Known",
                    "value", &__self_0),
            RegionVariableValue::Unknown { universe: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Unknown", "universe", &__self_0),
        }
    }
}Debug)]
10pub(crate) enum RegionVariableValue<'tcx> {
11    Known { value: ty::Region<'tcx> },
12    Unknown { universe: ty::UniverseIndex },
13}
14
15#[derive(#[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for RegionVidKey<'tcx> {
    #[inline]
    fn eq(&self, other: &RegionVidKey<'tcx>) -> bool {
        self.vid == other.vid && self.phantom == other.phantom
    }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for RegionVidKey<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for RegionVidKey<'tcx> {
    #[inline]
    fn clone(&self) -> RegionVidKey<'tcx> {
        let _: ::core::clone::AssertParamIsClone<ty::RegionVid>;
        let _:
                ::core::clone::AssertParamIsClone<PhantomData<RegionVariableValue<'tcx>>>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for RegionVidKey<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "RegionVidKey",
            "vid", &self.vid, "phantom", &&self.phantom)
    }
}Debug)]
16pub(crate) struct RegionVidKey<'tcx> {
17    pub vid: ty::RegionVid,
18    pub phantom: PhantomData<RegionVariableValue<'tcx>>,
19}
20
21impl<'tcx> From<ty::RegionVid> for RegionVidKey<'tcx> {
22    fn from(vid: ty::RegionVid) -> Self {
23        RegionVidKey { vid, phantom: PhantomData }
24    }
25}
26
27impl<'tcx> UnifyKey for RegionVidKey<'tcx> {
28    type Value = RegionVariableValue<'tcx>;
29    #[inline]
30    fn index(&self) -> u32 {
31        self.vid.as_u32()
32    }
33    #[inline]
34    fn from_index(i: u32) -> Self {
35        RegionVidKey::from(ty::RegionVid::from_u32(i))
36    }
37    fn tag() -> &'static str {
38        "RegionVidKey"
39    }
40}
41
42pub(crate) struct RegionUnificationError;
43
44impl<'tcx> UnifyValue for RegionVariableValue<'tcx> {
45    type Error = RegionUnificationError;
46
47    fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
48        match (*value1, *value2) {
49            (RegionVariableValue::Known { .. }, RegionVariableValue::Known { .. }) => {
50                Err(RegionUnificationError)
51            }
52
53            (RegionVariableValue::Known { value }, RegionVariableValue::Unknown { universe })
54            | (RegionVariableValue::Unknown { universe }, RegionVariableValue::Known { value }) => {
55                let universe_of_value = match value.kind() {
56                    ty::ReStatic
57                    | ty::ReErased
58                    | ty::ReLateParam(..)
59                    | ty::ReEarlyParam(..)
60                    | ty::ReError(_) => ty::UniverseIndex::ROOT,
61                    ty::RePlaceholder(placeholder) => placeholder.universe,
62                    ty::ReVar(..) | ty::ReBound(..) => ::rustc_middle::util::bug::bug_fmt(format_args!("not a universal region"))bug!("not a universal region"),
63                };
64
65                if universe.can_name(universe_of_value) {
66                    Ok(RegionVariableValue::Known { value })
67                } else {
68                    Err(RegionUnificationError)
69                }
70            }
71
72            (
73                RegionVariableValue::Unknown { universe: a },
74                RegionVariableValue::Unknown { universe: b },
75            ) => {
76                // If we unify two unconstrained regions then whatever
77                // value they wind up taking (which must be the same value) must
78                // be nameable by both universes. Therefore, the resulting
79                // universe is the minimum of the two universes, because that is
80                // the one which contains the fewest names in scope.
81                Ok(RegionVariableValue::Unknown { universe: a.min(b) })
82            }
83        }
84    }
85}
86
87// Generic consts.
88
89#[derive(#[automatically_derived]
impl ::core::marker::Copy for ConstVariableOrigin { }Copy, #[automatically_derived]
impl ::core::clone::Clone for ConstVariableOrigin {
    #[inline]
    fn clone(&self) -> ConstVariableOrigin {
        let _: ::core::clone::AssertParamIsClone<Span>;
        let _: ::core::clone::AssertParamIsClone<Option<DefId>>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for ConstVariableOrigin {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "ConstVariableOrigin", "span", &self.span, "param_def_id",
            &&self.param_def_id)
    }
}Debug)]
90pub struct ConstVariableOrigin {
91    pub span: Span,
92    /// `DefId` of the const parameter this was instantiated for, if any.
93    ///
94    /// This should only be used for diagnostics.
95    pub param_def_id: Option<DefId>,
96}
97
98#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for ConstVariableValue<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for ConstVariableValue<'tcx> {
    #[inline]
    fn clone(&self) -> ConstVariableValue<'tcx> {
        let _: ::core::clone::AssertParamIsClone<ty::Const<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<ConstVariableOrigin>;
        let _: ::core::clone::AssertParamIsClone<ty::UniverseIndex>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for ConstVariableValue<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            ConstVariableValue::Known { value: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Known",
                    "value", &__self_0),
            ConstVariableValue::Unknown { origin: __self_0, universe: __self_1
                } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "Unknown", "origin", __self_0, "universe", &__self_1),
        }
    }
}Debug)]
99pub(crate) enum ConstVariableValue<'tcx> {
100    Known { value: ty::Const<'tcx> },
101    Unknown { origin: ConstVariableOrigin, universe: ty::UniverseIndex },
102}
103
104impl<'tcx> ConstVariableValue<'tcx> {
105    /// If this value is known, returns the const it is known to be.
106    /// Otherwise, `None`.
107    pub(crate) fn known(&self) -> Option<ty::Const<'tcx>> {
108        match *self {
109            ConstVariableValue::Unknown { .. } => None,
110            ConstVariableValue::Known { value } => Some(value),
111        }
112    }
113}
114
115#[derive(#[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for ConstVidKey<'tcx> {
    #[inline]
    fn eq(&self, other: &ConstVidKey<'tcx>) -> bool {
        self.vid == other.vid && self.phantom == other.phantom
    }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for ConstVidKey<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for ConstVidKey<'tcx> {
    #[inline]
    fn clone(&self) -> ConstVidKey<'tcx> {
        let _: ::core::clone::AssertParamIsClone<ty::ConstVid>;
        let _:
                ::core::clone::AssertParamIsClone<PhantomData<ty::Const<'tcx>>>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for ConstVidKey<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "ConstVidKey",
            "vid", &self.vid, "phantom", &&self.phantom)
    }
}Debug)]
116pub(crate) struct ConstVidKey<'tcx> {
117    pub vid: ty::ConstVid,
118    pub phantom: PhantomData<ty::Const<'tcx>>,
119}
120
121impl<'tcx> From<ty::ConstVid> for ConstVidKey<'tcx> {
122    fn from(vid: ty::ConstVid) -> Self {
123        ConstVidKey { vid, phantom: PhantomData }
124    }
125}
126
127impl<'tcx> UnifyKey for ConstVidKey<'tcx> {
128    type Value = ConstVariableValue<'tcx>;
129    #[inline]
130    fn index(&self) -> u32 {
131        self.vid.as_u32()
132    }
133    #[inline]
134    fn from_index(i: u32) -> Self {
135        ConstVidKey::from(ty::ConstVid::from_u32(i))
136    }
137    fn tag() -> &'static str {
138        "ConstVidKey"
139    }
140    fn order_roots(a: Self, _: &Self::Value, b: Self, _: &Self::Value) -> Option<(Self, Self)> {
141        if a.vid.as_u32() < b.vid.as_u32() { Some((a, b)) } else { Some((b, a)) }
142    }
143}
144
145impl<'tcx> UnifyValue for ConstVariableValue<'tcx> {
146    type Error = NoError;
147
148    fn unify_values(&value1: &Self, &value2: &Self) -> Result<Self, Self::Error> {
149        match (value1, value2) {
150            (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => {
151                ::rustc_middle::util::bug::bug_fmt(format_args!("equating two const variables, both of which have known values"))bug!("equating two const variables, both of which have known values")
152            }
153
154            // If one side is known, prefer that one.
155            (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => Ok(value1),
156            (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => Ok(value2),
157
158            // If both sides are *unknown*, it hardly matters, does it?
159            (
160                ConstVariableValue::Unknown { origin, universe: universe1 },
161                ConstVariableValue::Unknown { origin: _, universe: universe2 },
162            ) => {
163                // If we unify two unbound variables, ?T and ?U, then whatever
164                // value they wind up taking (which must be the same value) must
165                // be nameable by both universes. Therefore, the resulting
166                // universe is the minimum of the two universes, because that is
167                // the one which contains the fewest names in scope.
168                let universe = cmp::min(universe1, universe2);
169                Ok(ConstVariableValue::Unknown { origin, universe })
170            }
171        }
172    }
173}