Rollup merge of #107146 - compiler-errors:unsizing-params, r=cjgillot
Make `unsizing_params_for_adt` into a query Addresses a FIXME in confirmation. r? ``@ghost``
This commit is contained in:
commit
e19ae977ec
3 changed files with 71 additions and 44 deletions
|
@ -183,6 +183,15 @@ rustc_queries! {
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query unsizing_params_for_adt(key: DefId) -> rustc_index::bit_set::BitSet<u32>
|
||||||
|
{
|
||||||
|
arena_cache
|
||||||
|
desc { |tcx|
|
||||||
|
"determining what parameters of `{}` can participate in unsizing",
|
||||||
|
tcx.def_path_str(key),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
query analysis(key: ()) -> Result<(), ErrorGuaranteed> {
|
query analysis(key: ()) -> Result<(), ErrorGuaranteed> {
|
||||||
eval_always
|
eval_always
|
||||||
desc { "running analysis passes on this crate" }
|
desc { "running analysis passes on this crate" }
|
||||||
|
|
|
@ -8,12 +8,11 @@
|
||||||
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
|
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_index::bit_set::GrowableBitSet;
|
|
||||||
use rustc_infer::infer::InferOk;
|
use rustc_infer::infer::InferOk;
|
||||||
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
|
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef,
|
self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
|
||||||
ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeVisitable,
|
TraitRef, Ty, TyCtxt, TypeVisitable,
|
||||||
};
|
};
|
||||||
use rustc_session::config::TraitSolver;
|
use rustc_session::config::TraitSolver;
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
|
@ -1064,51 +1063,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
|
|
||||||
// `Struct<T>` -> `Struct<U>`
|
// `Struct<T>` -> `Struct<U>`
|
||||||
(&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
|
(&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
|
||||||
let maybe_unsizing_param_idx = |arg: GenericArg<'tcx>| match arg.unpack() {
|
let unsizing_params = tcx.unsizing_params_for_adt(def.did());
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if unsizing_params.is_empty() {
|
if unsizing_params.is_empty() {
|
||||||
return Err(Unimplemented);
|
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<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
|
// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
|
||||||
// normalizing in the process, since `type_of` returns something directly from
|
// normalizing in the process, since `type_of` returns something directly from
|
||||||
// astconv (which means it's un-normalized).
|
// astconv (which means it's un-normalized).
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
|
||||||
use rustc_session::config::TraitSolver;
|
use rustc_session::config::TraitSolver;
|
||||||
use rustc_span::def_id::{DefId, CRATE_DEF_ID};
|
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)
|
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<u32> {
|
||||||
|
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) {
|
pub fn provide(providers: &mut ty::query::Providers) {
|
||||||
*providers = ty::query::Providers {
|
*providers = ty::query::Providers {
|
||||||
asyncness,
|
asyncness,
|
||||||
|
@ -415,6 +466,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
||||||
instance_def_size_estimate,
|
instance_def_size_estimate,
|
||||||
issue33140_self_ty,
|
issue33140_self_ty,
|
||||||
impl_defaultness,
|
impl_defaultness,
|
||||||
|
unsizing_params_for_adt,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue