summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/infer
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/infer')
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs24
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs37
2 files changed, 51 insertions, 10 deletions
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 7f8fc1774..b5b712c36 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -35,9 +35,9 @@ use std::ops::Index;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct Canonical<'tcx, V> {
+ pub value: V,
pub max_universe: ty::UniverseIndex,
pub variables: CanonicalVarInfos<'tcx>,
- pub value: V,
}
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
@@ -80,6 +80,18 @@ impl CanonicalVarValues<'_> {
}
})
}
+
+ pub fn is_identity_modulo_regions(&self) -> bool {
+ self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
+ ty::GenericArgKind::Lifetime(_) => true,
+ ty::GenericArgKind::Type(ty) => {
+ matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
+ }
+ ty::GenericArgKind::Const(ct) => {
+ matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
+ }
+ })
+ }
}
/// When we canonicalize a value to form a query, we wind up replacing
@@ -149,15 +161,15 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
}
}
- pub fn expect_anon_placeholder(self) -> u32 {
+ pub fn expect_placeholder_index(self) -> usize {
match self.kind {
CanonicalVarKind::Ty(_)
| CanonicalVarKind::Region(_)
| CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
- CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.name.expect_anon(),
- CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.name.expect_anon(),
- CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.name.as_u32(),
+ CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(),
+ CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(),
+ CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.as_usize(),
}
}
}
@@ -411,7 +423,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(i),
- kind: ty::BrAnon(i as u32, None),
+ kind: ty::BrAnon(None),
};
tcx.mk_re_late_bound(ty::INNERMOST, br).into()
}
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index 41d8c7ffd..a873854f0 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -1,4 +1,4 @@
-use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{self, Region, Ty, TyCtxt};
use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue};
use rustc_span::def_id::DefId;
use rustc_span::symbol::Symbol;
@@ -11,7 +11,20 @@ pub trait ToType {
}
#[derive(PartialEq, Copy, Clone, Debug)]
-pub struct UnifiedRegion<'tcx>(pub Option<ty::Region<'tcx>>);
+pub struct UnifiedRegion<'tcx> {
+ value: Option<ty::Region<'tcx>>,
+}
+
+impl<'tcx> UnifiedRegion<'tcx> {
+ pub fn new(value: Option<Region<'tcx>>) -> Self {
+ Self { value }
+ }
+
+ /// The caller is responsible for checking universe compatibility before using this value.
+ pub fn get_value_ignoring_universes(self) -> Option<Region<'tcx>> {
+ self.value
+ }
+}
#[derive(PartialEq, Copy, Clone, Debug)]
pub struct RegionVidKey<'tcx> {
@@ -44,11 +57,27 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
type Error = NoError;
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
- Ok(match (value1.0, value2.0) {
+ // We pick the value of the least universe because it is compatible with more variables.
+ // This is *not* necessary for soundness, but it allows more region variables to be
+ // resolved to the said value.
+ #[cold]
+ fn min_universe<'tcx>(r1: Region<'tcx>, r2: Region<'tcx>) -> Region<'tcx> {
+ cmp::min_by_key(r1, r2, |r| match r.kind() {
+ ty::ReStatic
+ | ty::ReErased
+ | ty::ReFree(..)
+ | ty::ReEarlyBound(..)
+ | ty::ReError(_) => ty::UniverseIndex::ROOT,
+ ty::RePlaceholder(placeholder) => placeholder.universe,
+ ty::ReVar(..) | ty::ReLateBound(..) => bug!("not a universal region"),
+ })
+ }
+
+ Ok(match (value1.value, value2.value) {
// Here we can just pick one value, because the full constraints graph
// will be handled later. Ideally, we might want a `MultipleValues`
// variant or something. For now though, this is fine.
- (Some(_), Some(_)) => *value1,
+ (Some(val1), Some(val2)) => Self { value: Some(min_universe(val1, val2)) },
(Some(_), _) => *value1,
(_, Some(_)) => *value2,