Skip to content

Commit 31d103b

Browse files
authoredJan 29, 2023
Rollup merge of rust-lang#107146 - compiler-errors:unsizing-params, r=cjgillot
Make `unsizing_params_for_adt` into a query Addresses a FIXME in confirmation. r? `@ghost`
2 parents 7389172 + 32bf8c7 commit 31d103b

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, TypeVisitable,
14+
self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
15+
TraitRef, Ty, TyCtxt, TypeVisitable,
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};
@@ -406,6 +407,56 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
406407
node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness)
407408
}
408409

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

0 commit comments

Comments
 (0)