Skip to content

Commit a89c639

Browse files
Make unsizing_params_for_adt into a query
1 parent 027c850 commit a89c639

File tree

3 files changed

+71
-44
lines changed

3 files changed

+71
-44
lines changed

compiler/rustc_middle/src/query/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,15 @@ rustc_queries! {
183183
separate_provide_extern
184184
}
185185

186+
query unsizing_params_for_adt(key: DefId) -> rustc_index::bit_set::BitSet<u32>
187+
{
188+
arena_cache
189+
desc { |tcx|
190+
"determining what parameters of `{}` can participate in unsizing",
191+
tcx.def_path_str(key),
192+
}
193+
}
194+
186195
query analysis(key: ()) -> Result<(), ErrorGuaranteed> {
187196
eval_always
188197
desc { "running analysis passes on this crate" }

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+10-44
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@
88
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
99
use rustc_data_structures::stack::ensure_sufficient_stack;
1010
use rustc_hir::lang_items::LangItem;
11-
use rustc_index::bit_set::GrowableBitSet;
1211
use rustc_infer::infer::InferOk;
1312
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
1413
use rustc_middle::ty::{
15-
self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef,
16-
ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt,
14+
self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
15+
TraitRef, Ty, TyCtxt,
1716
};
1817
use rustc_session::config::TraitSolver;
1918
use rustc_span::def_id::DefId;
@@ -1064,51 +1063,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10641063

10651064
// `Struct<T>` -> `Struct<U>`
10661065
(&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
1067-
let maybe_unsizing_param_idx = |arg: GenericArg<'tcx>| match arg.unpack() {
1068-
GenericArgKind::Type(ty) => match ty.kind() {
1069-
ty::Param(p) => Some(p.index),
1070-
_ => None,
1071-
},
1072-
1073-
// Lifetimes aren't allowed to change during unsizing.
1074-
GenericArgKind::Lifetime(_) => None,
1075-
1076-
GenericArgKind::Const(ct) => match ct.kind() {
1077-
ty::ConstKind::Param(p) => Some(p.index),
1078-
_ => None,
1079-
},
1080-
};
1081-
1082-
// FIXME(eddyb) cache this (including computing `unsizing_params`)
1083-
// by putting it in a query; it would only need the `DefId` as it
1084-
// looks at declared field types, not anything substituted.
1085-
1086-
// The last field of the structure has to exist and contain type/const parameters.
1087-
let (tail_field, prefix_fields) =
1088-
def.non_enum_variant().fields.split_last().ok_or(Unimplemented)?;
1089-
let tail_field_ty = tcx.bound_type_of(tail_field.did);
1090-
1091-
let mut unsizing_params = GrowableBitSet::new_empty();
1092-
for arg in tail_field_ty.0.walk() {
1093-
if let Some(i) = maybe_unsizing_param_idx(arg) {
1094-
unsizing_params.insert(i);
1095-
}
1096-
}
1097-
1098-
// Ensure none of the other fields mention the parameters used
1099-
// in unsizing.
1100-
for field in prefix_fields {
1101-
for arg in tcx.type_of(field.did).walk() {
1102-
if let Some(i) = maybe_unsizing_param_idx(arg) {
1103-
unsizing_params.remove(i);
1104-
}
1105-
}
1106-
}
1107-
1066+
let unsizing_params = tcx.unsizing_params_for_adt(def.did());
11081067
if unsizing_params.is_empty() {
11091068
return Err(Unimplemented);
11101069
}
11111070

1071+
let tail_field = def
1072+
.non_enum_variant()
1073+
.fields
1074+
.last()
1075+
.expect("expected unsized ADT to have a tail field");
1076+
let tail_field_ty = tcx.bound_type_of(tail_field.did);
1077+
11121078
// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
11131079
// normalizing in the process, since `type_of` returns something directly from
11141080
// astconv (which means it's un-normalized).

compiler/rustc_ty_utils/src/ty.rs

+52
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_data_structures::fx::FxIndexSet;
22
use rustc_hir as hir;
3+
use rustc_index::bit_set::BitSet;
34
use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
45
use rustc_session::config::TraitSolver;
56
use rustc_span::def_id::{DefId, CRATE_DEF_ID};
@@ -400,6 +401,56 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
400401
node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness)
401402
}
402403

404+
fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32> {
405+
let def = tcx.adt_def(def_id);
406+
let num_params = tcx.generics_of(def_id).count();
407+
408+
let maybe_unsizing_param_idx = |arg: ty::GenericArg<'tcx>| match arg.unpack() {
409+
ty::GenericArgKind::Type(ty) => match ty.kind() {
410+
ty::Param(p) => Some(p.index),
411+
_ => None,
412+
},
413+
414+
// We can't unsize a lifetime
415+
ty::GenericArgKind::Lifetime(_) => None,
416+
417+
ty::GenericArgKind::Const(ct) => match ct.kind() {
418+
ty::ConstKind::Param(p) => Some(p.index),
419+
_ => None,
420+
},
421+
};
422+
423+
// FIXME(eddyb) cache this (including computing `unsizing_params`)
424+
// by putting it in a query; it would only need the `DefId` as it
425+
// looks at declared field types, not anything substituted.
426+
427+
// The last field of the structure has to exist and contain type/const parameters.
428+
let Some((tail_field, prefix_fields)) =
429+
def.non_enum_variant().fields.split_last() else
430+
{
431+
return BitSet::new_empty(num_params);
432+
};
433+
434+
let mut unsizing_params = BitSet::new_empty(num_params);
435+
for arg in tcx.bound_type_of(tail_field.did).subst_identity().walk() {
436+
if let Some(i) = maybe_unsizing_param_idx(arg) {
437+
unsizing_params.insert(i);
438+
}
439+
}
440+
441+
// Ensure none of the other fields mention the parameters used
442+
// in unsizing.
443+
for field in prefix_fields {
444+
for arg in tcx.bound_type_of(field.did).subst_identity().walk() {
445+
if let Some(i) = maybe_unsizing_param_idx(arg) {
446+
unsizing_params.remove(i);
447+
}
448+
}
449+
}
450+
451+
unsizing_params
452+
}
453+
403454
pub fn provide(providers: &mut ty::query::Providers) {
404455
*providers = ty::query::Providers {
405456
asyncness,
@@ -409,6 +460,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
409460
instance_def_size_estimate,
410461
issue33140_self_ty,
411462
impl_defaultness,
463+
unsizing_params_for_adt,
412464
..*providers
413465
};
414466
}

0 commit comments

Comments
 (0)