Auto merge of #107303 - compiler-errors:intern-canonical-var-values, r=lcnr
Intern `CanonicalVarValues`
So that they are copy ✨
This commit is contained in:
commit
1e225413a2
@ -26,7 +26,7 @@ use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVari
|
|||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_middle::ty::fold::TypeFoldable;
|
use rustc_middle::ty::fold::TypeFoldable;
|
||||||
use rustc_middle::ty::subst::GenericArg;
|
use rustc_middle::ty::subst::GenericArg;
|
||||||
use rustc_middle::ty::{self, BoundVar, List};
|
use rustc_middle::ty::{self, List};
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
|
|
||||||
pub use rustc_middle::infer::canonical::*;
|
pub use rustc_middle::infer::canonical::*;
|
||||||
@ -87,12 +87,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
variables: &List<CanonicalVarInfo<'tcx>>,
|
variables: &List<CanonicalVarInfo<'tcx>>,
|
||||||
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
|
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
|
||||||
) -> CanonicalVarValues<'tcx> {
|
) -> CanonicalVarValues<'tcx> {
|
||||||
let var_values: IndexVec<BoundVar, GenericArg<'tcx>> = variables
|
CanonicalVarValues {
|
||||||
.iter()
|
var_values: self.tcx.mk_substs(
|
||||||
.map(|info| self.instantiate_canonical_var(span, info, &universe_map))
|
variables
|
||||||
.collect();
|
.iter()
|
||||||
|
.map(|info| self.instantiate_canonical_var(span, info, &universe_map)),
|
||||||
CanonicalVarValues { var_values }
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given the "info" about a canonical variable, creates a fresh
|
/// Given the "info" about a canonical variable, creates a fresh
|
||||||
|
@ -482,11 +482,8 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
// given variable in the loop above, use that. Otherwise, use
|
// given variable in the loop above, use that. Otherwise, use
|
||||||
// a fresh inference variable.
|
// a fresh inference variable.
|
||||||
let result_subst = CanonicalVarValues {
|
let result_subst = CanonicalVarValues {
|
||||||
var_values: query_response
|
var_values: self.tcx.mk_substs(query_response.variables.iter().enumerate().map(
|
||||||
.variables
|
|(index, info)| {
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(index, info)| {
|
|
||||||
if info.is_existential() {
|
if info.is_existential() {
|
||||||
match opt_values[BoundVar::new(index)] {
|
match opt_values[BoundVar::new(index)] {
|
||||||
Some(k) => k,
|
Some(k) => k,
|
||||||
@ -499,8 +496,8 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
universe_map[u.as_usize()]
|
universe_map[u.as_usize()]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
.collect(),
|
)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut obligations = vec![];
|
let mut obligations = vec![];
|
||||||
|
@ -72,16 +72,15 @@ where
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
let delegate = FnMutDelegate {
|
let delegate = FnMutDelegate {
|
||||||
regions: &mut |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() {
|
regions: &mut |br: ty::BoundRegion| match var_values[br.var].unpack() {
|
||||||
GenericArgKind::Lifetime(l) => l,
|
GenericArgKind::Lifetime(l) => l,
|
||||||
r => bug!("{:?} is a region but value is {:?}", br, r),
|
r => bug!("{:?} is a region but value is {:?}", br, r),
|
||||||
},
|
},
|
||||||
types: &mut |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() {
|
types: &mut |bound_ty: ty::BoundTy| match var_values[bound_ty.var].unpack() {
|
||||||
GenericArgKind::Type(ty) => ty,
|
GenericArgKind::Type(ty) => ty,
|
||||||
r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
|
r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
|
||||||
},
|
},
|
||||||
consts: &mut |bound_ct: ty::BoundVar, _| match var_values.var_values[bound_ct].unpack()
|
consts: &mut |bound_ct: ty::BoundVar, _| match var_values[bound_ct].unpack() {
|
||||||
{
|
|
||||||
GenericArgKind::Const(ct) => ct,
|
GenericArgKind::Const(ct) => ct,
|
||||||
c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
|
c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
|
||||||
},
|
},
|
||||||
|
@ -25,10 +25,8 @@ use crate::infer::MemberConstraint;
|
|||||||
use crate::mir::ConstraintCategory;
|
use crate::mir::ConstraintCategory;
|
||||||
use crate::ty::subst::GenericArg;
|
use crate::ty::subst::GenericArg;
|
||||||
use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
|
use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
|
||||||
use rustc_index::vec::IndexVec;
|
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::iter;
|
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
|
|
||||||
/// A "canonicalized" type `V` is one where all free inference
|
/// A "canonicalized" type `V` is one where all free inference
|
||||||
@ -62,23 +60,23 @@ impl<'tcx> ty::TypeFoldable<'tcx> for CanonicalVarInfos<'tcx> {
|
|||||||
/// vectors with the original values that were replaced by canonical
|
/// vectors with the original values that were replaced by canonical
|
||||||
/// variables. You will need to supply it later to instantiate the
|
/// variables. You will need to supply it later to instantiate the
|
||||||
/// canonicalized query response.
|
/// canonicalized query response.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
|
||||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||||
pub struct CanonicalVarValues<'tcx> {
|
pub struct CanonicalVarValues<'tcx> {
|
||||||
pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
|
pub var_values: ty::SubstsRef<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CanonicalVarValues<'_> {
|
impl CanonicalVarValues<'_> {
|
||||||
pub fn is_identity(&self) -> bool {
|
pub fn is_identity(&self) -> bool {
|
||||||
self.var_values.iter_enumerated().all(|(bv, arg)| match arg.unpack() {
|
self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
|
||||||
ty::GenericArgKind::Lifetime(r) => {
|
ty::GenericArgKind::Lifetime(r) => {
|
||||||
matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var == bv)
|
matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var.as_usize() == bv)
|
||||||
}
|
}
|
||||||
ty::GenericArgKind::Type(ty) => {
|
ty::GenericArgKind::Type(ty) => {
|
||||||
matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var == bv)
|
matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
|
||||||
}
|
}
|
||||||
ty::GenericArgKind::Const(ct) => {
|
ty::GenericArgKind::Const(ct) => {
|
||||||
matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc == bv)
|
matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -339,57 +337,57 @@ TrivialTypeTraversalAndLiftImpls! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> CanonicalVarValues<'tcx> {
|
impl<'tcx> CanonicalVarValues<'tcx> {
|
||||||
|
// Given a list of canonical variables, construct a set of values which are
|
||||||
|
// the identity response.
|
||||||
|
pub fn make_identity(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
infos: CanonicalVarInfos<'tcx>,
|
||||||
|
) -> CanonicalVarValues<'tcx> {
|
||||||
|
CanonicalVarValues {
|
||||||
|
var_values: tcx.mk_substs(infos.iter().enumerate().map(
|
||||||
|
|(i, info)| -> ty::GenericArg<'tcx> {
|
||||||
|
match info.kind {
|
||||||
|
CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => tcx
|
||||||
|
.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into()))
|
||||||
|
.into(),
|
||||||
|
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
|
||||||
|
let br = ty::BoundRegion {
|
||||||
|
var: ty::BoundVar::from_usize(i),
|
||||||
|
kind: ty::BrAnon(i as u32, None),
|
||||||
|
};
|
||||||
|
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
|
||||||
|
}
|
||||||
|
CanonicalVarKind::Const(_, ty)
|
||||||
|
| CanonicalVarKind::PlaceholderConst(_, ty) => tcx
|
||||||
|
.mk_const(
|
||||||
|
ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)),
|
||||||
|
ty,
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates dummy var values which should not be used in a
|
/// Creates dummy var values which should not be used in a
|
||||||
/// canonical response.
|
/// canonical response.
|
||||||
pub fn dummy() -> CanonicalVarValues<'tcx> {
|
pub fn dummy() -> CanonicalVarValues<'tcx> {
|
||||||
CanonicalVarValues { var_values: Default::default() }
|
CanonicalVarValues { var_values: ty::List::empty() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.var_values.len()
|
self.var_values.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes an identity substitution from this one: each bound var
|
|
||||||
/// is matched to the same bound var, preserving the original kinds.
|
|
||||||
/// For example, if we have:
|
|
||||||
/// `self.var_values == [Type(u32), Lifetime('a), Type(u64)]`
|
|
||||||
/// we'll return a substitution `subst` with:
|
|
||||||
/// `subst.var_values == [Type(^0), Lifetime(^1), Type(^2)]`.
|
|
||||||
pub fn make_identity(&self, tcx: TyCtxt<'tcx>) -> Self {
|
|
||||||
use crate::ty::subst::GenericArgKind;
|
|
||||||
|
|
||||||
CanonicalVarValues {
|
|
||||||
var_values: iter::zip(&self.var_values, 0..)
|
|
||||||
.map(|(kind, i)| match kind.unpack() {
|
|
||||||
GenericArgKind::Type(..) => {
|
|
||||||
tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
|
|
||||||
}
|
|
||||||
GenericArgKind::Lifetime(..) => {
|
|
||||||
let br = ty::BoundRegion {
|
|
||||||
var: ty::BoundVar::from_u32(i),
|
|
||||||
kind: ty::BrAnon(i, None),
|
|
||||||
};
|
|
||||||
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
|
|
||||||
}
|
|
||||||
GenericArgKind::Const(ct) => tcx
|
|
||||||
.mk_const(
|
|
||||||
ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)),
|
|
||||||
ct.ty(),
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
|
impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
|
||||||
type Item = GenericArg<'tcx>;
|
type Item = GenericArg<'tcx>;
|
||||||
type IntoIter = ::std::iter::Cloned<::std::slice::Iter<'a, GenericArg<'tcx>>>;
|
type IntoIter = ::std::iter::Copied<::std::slice::Iter<'a, GenericArg<'tcx>>>;
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
self.var_values.iter().cloned()
|
self.var_values.iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,6 +395,6 @@ impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
|
|||||||
type Output = GenericArg<'tcx>;
|
type Output = GenericArg<'tcx>;
|
||||||
|
|
||||||
fn index(&self, value: BoundVar) -> &GenericArg<'tcx> {
|
fn index(&self, value: BoundVar) -> &GenericArg<'tcx> {
|
||||||
&self.var_values[value]
|
&self.var_values[value.as_usize()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,12 @@
|
|||||||
// preserves universes and creates a unique var (in the highest universe) for each
|
// preserves universes and creates a unique var (in the highest universe) for each
|
||||||
// appearance of a region.
|
// appearance of a region.
|
||||||
|
|
||||||
// FIXME: `CanonicalVarValues` should be interned and `Copy`.
|
|
||||||
|
|
||||||
// FIXME: uses of `infcx.at` need to enable deferred projection equality once that's implemented.
|
// FIXME: uses of `infcx.at` need to enable deferred projection equality once that's implemented.
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues};
|
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
|
||||||
use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse};
|
use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse};
|
||||||
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
@ -225,7 +223,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
|||||||
let external_constraints = take_external_constraints(self.infcx)?;
|
let external_constraints = take_external_constraints(self.infcx)?;
|
||||||
|
|
||||||
Ok(self.infcx.canonicalize_response(Response {
|
Ok(self.infcx.canonicalize_response(Response {
|
||||||
var_values: self.var_values.clone(),
|
var_values: self.var_values,
|
||||||
external_constraints,
|
external_constraints,
|
||||||
certainty,
|
certainty,
|
||||||
}))
|
}))
|
||||||
@ -483,32 +481,11 @@ pub(super) fn response_no_constraints<'tcx>(
|
|||||||
goal: Canonical<'tcx, impl Sized>,
|
goal: Canonical<'tcx, impl Sized>,
|
||||||
certainty: Certainty,
|
certainty: Certainty,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
let var_values = goal
|
|
||||||
.variables
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, info)| match info.kind {
|
|
||||||
CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
|
|
||||||
tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into())).into()
|
|
||||||
}
|
|
||||||
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
|
|
||||||
let br = ty::BoundRegion {
|
|
||||||
var: ty::BoundVar::from_usize(i),
|
|
||||||
kind: ty::BrAnon(i as u32, None),
|
|
||||||
};
|
|
||||||
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
|
|
||||||
}
|
|
||||||
CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => tcx
|
|
||||||
.mk_const(ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)), ty)
|
|
||||||
.into(),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(Canonical {
|
Ok(Canonical {
|
||||||
max_universe: goal.max_universe,
|
max_universe: goal.max_universe,
|
||||||
variables: goal.variables,
|
variables: goal.variables,
|
||||||
value: Response {
|
value: Response {
|
||||||
var_values: CanonicalVarValues { var_values },
|
var_values: CanonicalVarValues::make_identity(tcx, goal.variables),
|
||||||
external_constraints: Default::default(),
|
external_constraints: Default::default(),
|
||||||
certainty,
|
certainty,
|
||||||
},
|
},
|
||||||
|
@ -95,6 +95,7 @@ impl<'tcx> ProvisionalCache<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> {
|
pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> {
|
||||||
|
// FIXME: Responses should probably be `Copy` as well
|
||||||
self.entries[entry_index].response.clone()
|
self.entries[entry_index].response.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,10 @@ pub(crate) mod lowering;
|
|||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
|
||||||
use rustc_index::vec::IndexVec;
|
|
||||||
|
|
||||||
use rustc_middle::infer::canonical::{CanonicalTyVarKind, CanonicalVarKind};
|
use rustc_middle::infer::canonical::{CanonicalTyVarKind, CanonicalVarKind};
|
||||||
use rustc_middle::traits::ChalkRustInterner;
|
use rustc_middle::traits::ChalkRustInterner;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::subst::GenericArg;
|
use rustc_middle::ty::{self, ParamTy, TyCtxt, TypeFoldable, TypeVisitable};
|
||||||
use rustc_middle::ty::{self, BoundVar, ParamTy, TyCtxt, TypeFoldable, TypeVisitable};
|
|
||||||
|
|
||||||
use rustc_infer::infer::canonical::{
|
use rustc_infer::infer::canonical::{
|
||||||
Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse,
|
Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse,
|
||||||
@ -100,11 +97,13 @@ pub(crate) fn evaluate_goal<'tcx>(
|
|||||||
binders: chalk_ir::CanonicalVarKinds<_>| {
|
binders: chalk_ir::CanonicalVarKinds<_>| {
|
||||||
use rustc_middle::infer::canonical::CanonicalVarInfo;
|
use rustc_middle::infer::canonical::CanonicalVarInfo;
|
||||||
|
|
||||||
let mut var_values: IndexVec<BoundVar, GenericArg<'tcx>> = IndexVec::new();
|
|
||||||
let mut reverse_param_substitutor = ReverseParamsSubstitutor::new(tcx, params);
|
let mut reverse_param_substitutor = ReverseParamsSubstitutor::new(tcx, params);
|
||||||
subst.as_slice(interner).iter().for_each(|p| {
|
let var_values = tcx.mk_substs(
|
||||||
var_values.push(p.lower_into(interner).fold_with(&mut reverse_param_substitutor));
|
subst
|
||||||
});
|
.as_slice(interner)
|
||||||
|
.iter()
|
||||||
|
.map(|p| p.lower_into(interner).fold_with(&mut reverse_param_substitutor)),
|
||||||
|
);
|
||||||
let variables: Vec<_> = binders
|
let variables: Vec<_> = binders
|
||||||
.iter(interner)
|
.iter(interner)
|
||||||
.map(|var| {
|
.map(|var| {
|
||||||
@ -159,8 +158,7 @@ pub(crate) fn evaluate_goal<'tcx>(
|
|||||||
max_universe: ty::UniverseIndex::from_usize(0),
|
max_universe: ty::UniverseIndex::from_usize(0),
|
||||||
variables: obligation.variables,
|
variables: obligation.variables,
|
||||||
value: QueryResponse {
|
value: QueryResponse {
|
||||||
var_values: CanonicalVarValues { var_values: IndexVec::new() }
|
var_values: CanonicalVarValues::dummy(),
|
||||||
.make_identity(tcx),
|
|
||||||
region_constraints: QueryRegionConstraints::default(),
|
region_constraints: QueryRegionConstraints::default(),
|
||||||
certainty: Certainty::Ambiguous,
|
certainty: Certainty::Ambiguous,
|
||||||
opaque_types: vec![],
|
opaque_types: vec![],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user