From 32bf8c767f080459c3dd443ca6f478175b647754 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 21 Jan 2023 05:43:37 +0000 Subject: [PATCH] Make unsizing_params_for_adt into a query --- compiler/rustc_middle/src/query/mod.rs | 9 ++++ .../src/traits/select/confirmation.rs | 54 ++++--------------- compiler/rustc_ty_utils/src/ty.rs | 52 ++++++++++++++++++ 3 files changed, 71 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 460a5147766b5..a8c562940e0ed 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -183,6 +183,15 @@ rustc_queries! { separate_provide_extern } + query unsizing_params_for_adt(key: DefId) -> rustc_index::bit_set::BitSet + { + arena_cache + desc { |tcx| + "determining what parameters of `{}` can participate in unsizing", + tcx.def_path_str(key), + } + } + query analysis(key: ()) -> Result<(), ErrorGuaranteed> { eval_always desc { "running analysis passes on this crate" } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 61d3531cfc44e..2c41d28400c82 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -8,12 +8,11 @@ //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; -use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_middle::ty::{ - self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef, - ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeVisitable, + self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate, + TraitRef, Ty, TyCtxt, TypeVisitable, }; use rustc_session::config::TraitSolver; use rustc_span::def_id::DefId; @@ -1064,51 +1063,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // `Struct` -> `Struct` (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => { - let maybe_unsizing_param_idx = |arg: GenericArg<'tcx>| match arg.unpack() { - GenericArgKind::Type(ty) => match ty.kind() { - ty::Param(p) => Some(p.index), - _ => None, - }, - - // Lifetimes aren't allowed to change during unsizing. - GenericArgKind::Lifetime(_) => None, - - GenericArgKind::Const(ct) => match ct.kind() { - ty::ConstKind::Param(p) => Some(p.index), - _ => None, - }, - }; - - // FIXME(eddyb) cache this (including computing `unsizing_params`) - // by putting it in a query; it would only need the `DefId` as it - // looks at declared field types, not anything substituted. - - // The last field of the structure has to exist and contain type/const parameters. - let (tail_field, prefix_fields) = - def.non_enum_variant().fields.split_last().ok_or(Unimplemented)?; - let tail_field_ty = tcx.bound_type_of(tail_field.did); - - let mut unsizing_params = GrowableBitSet::new_empty(); - for arg in tail_field_ty.0.walk() { - if let Some(i) = maybe_unsizing_param_idx(arg) { - unsizing_params.insert(i); - } - } - - // Ensure none of the other fields mention the parameters used - // in unsizing. - for field in prefix_fields { - for arg in tcx.type_of(field.did).walk() { - if let Some(i) = maybe_unsizing_param_idx(arg) { - unsizing_params.remove(i); - } - } - } - + let unsizing_params = tcx.unsizing_params_for_adt(def.did()); if unsizing_params.is_empty() { return Err(Unimplemented); } + let tail_field = def + .non_enum_variant() + .fields + .last() + .expect("expected unsized ADT to have a tail field"); + let tail_field_ty = tcx.bound_type_of(tail_field.did); + // Extract `TailField` and `TailField` from `Struct` and `Struct`, // normalizing in the process, since `type_of` returns something directly from // astconv (which means it's un-normalized). diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 89abffebdc684..b5005c1d8d804 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -1,5 +1,6 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; +use rustc_index::bit_set::BitSet; use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt}; use rustc_session::config::TraitSolver; use rustc_span::def_id::{DefId, CRATE_DEF_ID}; @@ -406,6 +407,56 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness) } +fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet { + let def = tcx.adt_def(def_id); + let num_params = tcx.generics_of(def_id).count(); + + let maybe_unsizing_param_idx = |arg: ty::GenericArg<'tcx>| match arg.unpack() { + ty::GenericArgKind::Type(ty) => match ty.kind() { + ty::Param(p) => Some(p.index), + _ => None, + }, + + // We can't unsize a lifetime + ty::GenericArgKind::Lifetime(_) => None, + + ty::GenericArgKind::Const(ct) => match ct.kind() { + ty::ConstKind::Param(p) => Some(p.index), + _ => None, + }, + }; + + // FIXME(eddyb) cache this (including computing `unsizing_params`) + // by putting it in a query; it would only need the `DefId` as it + // looks at declared field types, not anything substituted. + + // The last field of the structure has to exist and contain type/const parameters. + let Some((tail_field, prefix_fields)) = + def.non_enum_variant().fields.split_last() else + { + return BitSet::new_empty(num_params); + }; + + let mut unsizing_params = BitSet::new_empty(num_params); + for arg in tcx.bound_type_of(tail_field.did).subst_identity().walk() { + if let Some(i) = maybe_unsizing_param_idx(arg) { + unsizing_params.insert(i); + } + } + + // Ensure none of the other fields mention the parameters used + // in unsizing. + for field in prefix_fields { + for arg in tcx.bound_type_of(field.did).subst_identity().walk() { + if let Some(i) = maybe_unsizing_param_idx(arg) { + unsizing_params.remove(i); + } + } + } + + unsizing_params +} + pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { asyncness, @@ -415,6 +466,7 @@ pub fn provide(providers: &mut ty::query::Providers) { instance_def_size_estimate, issue33140_self_ty, impl_defaultness, + unsizing_params_for_adt, ..*providers }; }