Skip to content

Commit 1e22541

Browse files
committed
Auto merge of #107303 - compiler-errors:intern-canonical-var-values, r=lcnr
Intern `CanonicalVarValues` So that they are copy ✨
2 parents d6f0642 + 2d5591d commit 1e22541

File tree

7 files changed

+70
-99
lines changed

7 files changed

+70
-99
lines changed

compiler/rustc_infer/src/infer/canonical/mod.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVari
2626
use rustc_index::vec::IndexVec;
2727
use rustc_middle::ty::fold::TypeFoldable;
2828
use rustc_middle::ty::subst::GenericArg;
29-
use rustc_middle::ty::{self, BoundVar, List};
29+
use rustc_middle::ty::{self, List};
3030
use rustc_span::source_map::Span;
3131

3232
pub use rustc_middle::infer::canonical::*;
@@ -87,12 +87,13 @@ impl<'tcx> InferCtxt<'tcx> {
8787
variables: &List<CanonicalVarInfo<'tcx>>,
8888
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
8989
) -> CanonicalVarValues<'tcx> {
90-
let var_values: IndexVec<BoundVar, GenericArg<'tcx>> = variables
91-
.iter()
92-
.map(|info| self.instantiate_canonical_var(span, info, &universe_map))
93-
.collect();
94-
95-
CanonicalVarValues { var_values }
90+
CanonicalVarValues {
91+
var_values: self.tcx.mk_substs(
92+
variables
93+
.iter()
94+
.map(|info| self.instantiate_canonical_var(span, info, &universe_map)),
95+
),
96+
}
9697
}
9798

9899
/// Given the "info" about a canonical variable, creates a fresh

compiler/rustc_infer/src/infer/canonical/query_response.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -482,11 +482,8 @@ impl<'tcx> InferCtxt<'tcx> {
482482
// given variable in the loop above, use that. Otherwise, use
483483
// a fresh inference variable.
484484
let result_subst = CanonicalVarValues {
485-
var_values: query_response
486-
.variables
487-
.iter()
488-
.enumerate()
489-
.map(|(index, info)| {
485+
var_values: self.tcx.mk_substs(query_response.variables.iter().enumerate().map(
486+
|(index, info)| {
490487
if info.is_existential() {
491488
match opt_values[BoundVar::new(index)] {
492489
Some(k) => k,
@@ -499,8 +496,8 @@ impl<'tcx> InferCtxt<'tcx> {
499496
universe_map[u.as_usize()]
500497
})
501498
}
502-
})
503-
.collect(),
499+
},
500+
)),
504501
};
505502

506503
let mut obligations = vec![];

compiler/rustc_infer/src/infer/canonical/substitute.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,15 @@ where
7272
value
7373
} else {
7474
let delegate = FnMutDelegate {
75-
regions: &mut |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() {
75+
regions: &mut |br: ty::BoundRegion| match var_values[br.var].unpack() {
7676
GenericArgKind::Lifetime(l) => l,
7777
r => bug!("{:?} is a region but value is {:?}", br, r),
7878
},
79-
types: &mut |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() {
79+
types: &mut |bound_ty: ty::BoundTy| match var_values[bound_ty.var].unpack() {
8080
GenericArgKind::Type(ty) => ty,
8181
r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
8282
},
83-
consts: &mut |bound_ct: ty::BoundVar, _| match var_values.var_values[bound_ct].unpack()
84-
{
83+
consts: &mut |bound_ct: ty::BoundVar, _| match var_values[bound_ct].unpack() {
8584
GenericArgKind::Const(ct) => ct,
8685
c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
8786
},

compiler/rustc_middle/src/infer/canonical.rs

+43-45
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@ use crate::infer::MemberConstraint;
2525
use crate::mir::ConstraintCategory;
2626
use crate::ty::subst::GenericArg;
2727
use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
28-
use rustc_index::vec::IndexVec;
2928
use rustc_macros::HashStable;
3029
use smallvec::SmallVec;
31-
use std::iter;
3230
use std::ops::Index;
3331

3432
/// A "canonicalized" type `V` is one where all free inference
@@ -62,23 +60,23 @@ impl<'tcx> ty::TypeFoldable<'tcx> for CanonicalVarInfos<'tcx> {
6260
/// vectors with the original values that were replaced by canonical
6361
/// variables. You will need to supply it later to instantiate the
6462
/// canonicalized query response.
65-
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
63+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
6664
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
6765
pub struct CanonicalVarValues<'tcx> {
68-
pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
66+
pub var_values: ty::SubstsRef<'tcx>,
6967
}
7068

7169
impl CanonicalVarValues<'_> {
7270
pub fn is_identity(&self) -> bool {
73-
self.var_values.iter_enumerated().all(|(bv, arg)| match arg.unpack() {
71+
self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
7472
ty::GenericArgKind::Lifetime(r) => {
75-
matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var == bv)
73+
matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var.as_usize() == bv)
7674
}
7775
ty::GenericArgKind::Type(ty) => {
78-
matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var == bv)
76+
matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
7977
}
8078
ty::GenericArgKind::Const(ct) => {
81-
matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc == bv)
79+
matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
8280
}
8381
})
8482
}
@@ -339,64 +337,64 @@ TrivialTypeTraversalAndLiftImpls! {
339337
}
340338

341339
impl<'tcx> CanonicalVarValues<'tcx> {
340+
// Given a list of canonical variables, construct a set of values which are
341+
// the identity response.
342+
pub fn make_identity(
343+
tcx: TyCtxt<'tcx>,
344+
infos: CanonicalVarInfos<'tcx>,
345+
) -> CanonicalVarValues<'tcx> {
346+
CanonicalVarValues {
347+
var_values: tcx.mk_substs(infos.iter().enumerate().map(
348+
|(i, info)| -> ty::GenericArg<'tcx> {
349+
match info.kind {
350+
CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => tcx
351+
.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into()))
352+
.into(),
353+
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
354+
let br = ty::BoundRegion {
355+
var: ty::BoundVar::from_usize(i),
356+
kind: ty::BrAnon(i as u32, None),
357+
};
358+
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
359+
}
360+
CanonicalVarKind::Const(_, ty)
361+
| CanonicalVarKind::PlaceholderConst(_, ty) => tcx
362+
.mk_const(
363+
ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)),
364+
ty,
365+
)
366+
.into(),
367+
}
368+
},
369+
)),
370+
}
371+
}
372+
342373
/// Creates dummy var values which should not be used in a
343374
/// canonical response.
344375
pub fn dummy() -> CanonicalVarValues<'tcx> {
345-
CanonicalVarValues { var_values: Default::default() }
376+
CanonicalVarValues { var_values: ty::List::empty() }
346377
}
347378

348379
#[inline]
349380
pub fn len(&self) -> usize {
350381
self.var_values.len()
351382
}
352-
353-
/// Makes an identity substitution from this one: each bound var
354-
/// is matched to the same bound var, preserving the original kinds.
355-
/// For example, if we have:
356-
/// `self.var_values == [Type(u32), Lifetime('a), Type(u64)]`
357-
/// we'll return a substitution `subst` with:
358-
/// `subst.var_values == [Type(^0), Lifetime(^1), Type(^2)]`.
359-
pub fn make_identity(&self, tcx: TyCtxt<'tcx>) -> Self {
360-
use crate::ty::subst::GenericArgKind;
361-
362-
CanonicalVarValues {
363-
var_values: iter::zip(&self.var_values, 0..)
364-
.map(|(kind, i)| match kind.unpack() {
365-
GenericArgKind::Type(..) => {
366-
tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
367-
}
368-
GenericArgKind::Lifetime(..) => {
369-
let br = ty::BoundRegion {
370-
var: ty::BoundVar::from_u32(i),
371-
kind: ty::BrAnon(i, None),
372-
};
373-
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
374-
}
375-
GenericArgKind::Const(ct) => tcx
376-
.mk_const(
377-
ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)),
378-
ct.ty(),
379-
)
380-
.into(),
381-
})
382-
.collect(),
383-
}
384-
}
385383
}
386384

387385
impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
388386
type Item = GenericArg<'tcx>;
389-
type IntoIter = ::std::iter::Cloned<::std::slice::Iter<'a, GenericArg<'tcx>>>;
387+
type IntoIter = ::std::iter::Copied<::std::slice::Iter<'a, GenericArg<'tcx>>>;
390388

391389
fn into_iter(self) -> Self::IntoIter {
392-
self.var_values.iter().cloned()
390+
self.var_values.iter()
393391
}
394392
}
395393

396394
impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
397395
type Output = GenericArg<'tcx>;
398396

399397
fn index(&self, value: BoundVar) -> &GenericArg<'tcx> {
400-
&self.var_values[value]
398+
&self.var_values[value.as_usize()]
401399
}
402400
}

compiler/rustc_trait_selection/src/solve/mod.rs

+3-26
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,12 @@
1313
// preserves universes and creates a unique var (in the highest universe) for each
1414
// appearance of a region.
1515

16-
// FIXME: `CanonicalVarValues` should be interned and `Copy`.
17-
1816
// FIXME: uses of `infcx.at` need to enable deferred projection equality once that's implemented.
1917

2018
use std::mem;
2119

2220
use rustc_hir::def_id::DefId;
23-
use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues};
21+
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
2422
use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse};
2523
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
2624
use rustc_infer::traits::query::NoSolution;
@@ -225,7 +223,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
225223
let external_constraints = take_external_constraints(self.infcx)?;
226224

227225
Ok(self.infcx.canonicalize_response(Response {
228-
var_values: self.var_values.clone(),
226+
var_values: self.var_values,
229227
external_constraints,
230228
certainty,
231229
}))
@@ -483,32 +481,11 @@ pub(super) fn response_no_constraints<'tcx>(
483481
goal: Canonical<'tcx, impl Sized>,
484482
certainty: Certainty,
485483
) -> QueryResult<'tcx> {
486-
let var_values = goal
487-
.variables
488-
.iter()
489-
.enumerate()
490-
.map(|(i, info)| match info.kind {
491-
CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
492-
tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into())).into()
493-
}
494-
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
495-
let br = ty::BoundRegion {
496-
var: ty::BoundVar::from_usize(i),
497-
kind: ty::BrAnon(i as u32, None),
498-
};
499-
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
500-
}
501-
CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => tcx
502-
.mk_const(ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)), ty)
503-
.into(),
504-
})
505-
.collect();
506-
507484
Ok(Canonical {
508485
max_universe: goal.max_universe,
509486
variables: goal.variables,
510487
value: Response {
511-
var_values: CanonicalVarValues { var_values },
488+
var_values: CanonicalVarValues::make_identity(tcx, goal.variables),
512489
external_constraints: Default::default(),
513490
certainty,
514491
},

compiler/rustc_trait_selection/src/solve/search_graph/cache.rs

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ impl<'tcx> ProvisionalCache<'tcx> {
9595
}
9696

9797
pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> {
98+
// FIXME: Responses should probably be `Copy` as well
9899
self.entries[entry_index].response.clone()
99100
}
100101
}

compiler/rustc_traits/src/chalk/mod.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,10 @@ pub(crate) mod lowering;
88

99
use rustc_data_structures::fx::FxHashMap;
1010

11-
use rustc_index::vec::IndexVec;
12-
1311
use rustc_middle::infer::canonical::{CanonicalTyVarKind, CanonicalVarKind};
1412
use rustc_middle::traits::ChalkRustInterner;
1513
use rustc_middle::ty::query::Providers;
16-
use rustc_middle::ty::subst::GenericArg;
17-
use rustc_middle::ty::{self, BoundVar, ParamTy, TyCtxt, TypeFoldable, TypeVisitable};
14+
use rustc_middle::ty::{self, ParamTy, TyCtxt, TypeFoldable, TypeVisitable};
1815

1916
use rustc_infer::infer::canonical::{
2017
Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse,
@@ -100,11 +97,13 @@ pub(crate) fn evaluate_goal<'tcx>(
10097
binders: chalk_ir::CanonicalVarKinds<_>| {
10198
use rustc_middle::infer::canonical::CanonicalVarInfo;
10299

103-
let mut var_values: IndexVec<BoundVar, GenericArg<'tcx>> = IndexVec::new();
104100
let mut reverse_param_substitutor = ReverseParamsSubstitutor::new(tcx, params);
105-
subst.as_slice(interner).iter().for_each(|p| {
106-
var_values.push(p.lower_into(interner).fold_with(&mut reverse_param_substitutor));
107-
});
101+
let var_values = tcx.mk_substs(
102+
subst
103+
.as_slice(interner)
104+
.iter()
105+
.map(|p| p.lower_into(interner).fold_with(&mut reverse_param_substitutor)),
106+
);
108107
let variables: Vec<_> = binders
109108
.iter(interner)
110109
.map(|var| {
@@ -159,8 +158,7 @@ pub(crate) fn evaluate_goal<'tcx>(
159158
max_universe: ty::UniverseIndex::from_usize(0),
160159
variables: obligation.variables,
161160
value: QueryResponse {
162-
var_values: CanonicalVarValues { var_values: IndexVec::new() }
163-
.make_identity(tcx),
161+
var_values: CanonicalVarValues::dummy(),
164162
region_constraints: QueryRegionConstraints::default(),
165163
certainty: Certainty::Ambiguous,
166164
opaque_types: vec![],

0 commit comments

Comments
 (0)