summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ty_utils
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /compiler/rustc_ty_utils
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_ty_utils')
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs81
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs58
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs18
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs10
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs201
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs1
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs17
8 files changed, 291 insertions, 97 deletions
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 73c7eb699..91a505a72 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -35,7 +35,7 @@ fn fn_sig_for_fn_abi<'tcx>(
// HACK(davidtwco,eddyb): This is a workaround for polymorphization considering
// parameters unused if they show up in the signature, but not in the `mir::Body`
// (i.e. due to being inside a projection that got normalized, see
- // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping
+ // `tests/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping
// track of a polymorphization `ParamEnv` to allow normalizing later.
//
// We normalize the `fn_sig` again after substituting at a later point.
@@ -85,7 +85,7 @@ fn fn_sig_for_fn_abi<'tcx>(
bound_vars,
)
}
- ty::Generator(_, substs, _) => {
+ ty::Generator(did, substs, _) => {
let sig = substs.as_generator().poly_sig();
let bound_vars = tcx.mk_bound_variable_kinds(
@@ -104,13 +104,45 @@ fn fn_sig_for_fn_abi<'tcx>(
let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
let sig = sig.skip_binder();
- let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
- let state_adt_ref = tcx.adt_def(state_did);
- let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
- let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
+ // The `FnSig` and the `ret_ty` here is for a generators main
+ // `Generator::resume(...) -> GeneratorState` function in case we
+ // have an ordinary generator, or the `Future::poll(...) -> Poll`
+ // function in case this is a special generator backing an async construct.
+ let (resume_ty, ret_ty) = if tcx.generator_is_async(did) {
+ // The signature should be `Future::poll(_, &mut Context<'_>) -> Poll<Output>`
+ let poll_did = tcx.require_lang_item(LangItem::Poll, None);
+ let poll_adt_ref = tcx.adt_def(poll_did);
+ let poll_substs = tcx.intern_substs(&[sig.return_ty.into()]);
+ let ret_ty = tcx.mk_adt(poll_adt_ref, poll_substs);
+
+ // We have to replace the `ResumeTy` that is used for type and borrow checking
+ // with `&mut Context<'_>` which is used in codegen.
+ #[cfg(debug_assertions)]
+ {
+ if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
+ let expected_adt =
+ tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, None));
+ assert_eq!(*resume_ty_adt, expected_adt);
+ } else {
+ panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty);
+ };
+ }
+ let context_mut_ref = tcx.mk_task_context();
+
+ (context_mut_ref, ret_ty)
+ } else {
+ // The signature should be `Generator::resume(_, Resume) -> GeneratorState<Yield, Return>`
+ let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
+ let state_adt_ref = tcx.adt_def(state_did);
+ let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
+ let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
+
+ (sig.resume_ty, ret_ty)
+ };
+
ty::Binder::bind_with_vars(
tcx.mk_fn_sig(
- [env_ty, sig.resume_ty].iter(),
+ [env_ty, resume_ty].iter(),
&ret_ty,
false,
hir::Unsafety::Normal,
@@ -207,8 +239,7 @@ fn adjust_for_rust_scalar<'tcx>(
return;
}
- // Scalars which have invalid values cannot be undef.
- if !scalar.is_always_valid(&cx) {
+ if !scalar.is_uninit_valid() {
attrs.set(ArgAttribute::NoUndef);
}
@@ -234,15 +265,15 @@ fn adjust_for_rust_scalar<'tcx>(
PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
};
- // `Box`, `&T`, and `&mut T` cannot be undef.
- // Note that this only applies to the value of the pointer itself;
- // this attribute doesn't make it UB for the pointed-to data to be undef.
- attrs.set(ArgAttribute::NoUndef);
-
// The aliasing rules for `Box<T>` are still not decided, but currently we emit
// `noalias` for it. This can be turned off using an unstable flag.
// See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
- let noalias_for_box = cx.tcx.sess.opts.unstable_opts.box_noalias.unwrap_or(true);
+ let noalias_for_box = cx.tcx.sess.opts.unstable_opts.box_noalias;
+
+ // LLVM prior to version 12 had known miscompiles in the presence of noalias attributes
+ // (see #54878), so it was conditionally disabled, but we don't support earlier
+ // versions at all anymore. We still support turning it off using -Zmutable-noalias.
+ let noalias_mut_ref = cx.tcx.sess.opts.unstable_opts.mutable_noalias;
// `&mut` pointer parameters never alias other parameters,
// or mutable global data
@@ -251,29 +282,21 @@ fn adjust_for_rust_scalar<'tcx>(
// and can be marked as both `readonly` and `noalias`, as
// LLVM's definition of `noalias` is based solely on memory
// dependencies rather than pointer equality
- //
- // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
- // for UniqueBorrowed arguments, so that the codegen backend can decide whether
- // or not to actually emit the attribute. It can also be controlled with the
- // `-Zmutable-noalias` debugging option.
let no_alias = match kind {
- PointerKind::SharedMutable
- | PointerKind::UniqueBorrowed
- | PointerKind::UniqueBorrowedPinned => false,
+ PointerKind::SharedMutable | PointerKind::UniqueBorrowedPinned => false,
+ PointerKind::UniqueBorrowed => noalias_mut_ref,
PointerKind::UniqueOwned => noalias_for_box,
- PointerKind::Frozen => !is_return,
+ PointerKind::Frozen => true,
};
- if no_alias {
+ // We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics
+ // (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>).
+ if no_alias && !is_return {
attrs.set(ArgAttribute::NoAlias);
}
if kind == PointerKind::Frozen && !is_return {
attrs.set(ArgAttribute::ReadOnly);
}
-
- if kind == PointerKind::UniqueBorrowed && !is_return {
- attrs.set(ArgAttribute::NoAliasMutRef);
- }
}
}
}
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index f8ff31f97..a9fbad55d 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -267,8 +267,8 @@ struct IsThirPolymorphic<'a, 'tcx> {
thir: &'a thir::Thir<'tcx>,
}
-fn error<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn error(
+ tcx: TyCtxt<'_>,
sub: GenericConstantTooComplexSub,
root_span: Span,
) -> Result<!, ErrorGuaranteed> {
@@ -281,8 +281,8 @@ fn error<'tcx>(
Err(reported)
}
-fn maybe_supported_error<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn maybe_supported_error(
+ tcx: TyCtxt<'_>,
sub: GenericConstantTooComplexSub,
root_span: Span,
) -> Result<!, ErrorGuaranteed> {
@@ -302,13 +302,53 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
}
match expr.kind {
- thir::ExprKind::NamedConst { substs, .. } => substs.has_non_region_param(),
+ thir::ExprKind::NamedConst { substs, .. }
+ | thir::ExprKind::ConstBlock { substs, .. } => substs.has_non_region_param(),
thir::ExprKind::ConstParam { .. } => true,
thir::ExprKind::Repeat { value, count } => {
self.visit_expr(&self.thir()[value]);
count.has_non_region_param()
}
- _ => false,
+ thir::ExprKind::Scope { .. }
+ | thir::ExprKind::Box { .. }
+ | thir::ExprKind::If { .. }
+ | thir::ExprKind::Call { .. }
+ | thir::ExprKind::Deref { .. }
+ | thir::ExprKind::Binary { .. }
+ | thir::ExprKind::LogicalOp { .. }
+ | thir::ExprKind::Unary { .. }
+ | thir::ExprKind::Cast { .. }
+ | thir::ExprKind::Use { .. }
+ | thir::ExprKind::NeverToAny { .. }
+ | thir::ExprKind::Pointer { .. }
+ | thir::ExprKind::Loop { .. }
+ | thir::ExprKind::Let { .. }
+ | thir::ExprKind::Match { .. }
+ | thir::ExprKind::Block { .. }
+ | thir::ExprKind::Assign { .. }
+ | thir::ExprKind::AssignOp { .. }
+ | thir::ExprKind::Field { .. }
+ | thir::ExprKind::Index { .. }
+ | thir::ExprKind::VarRef { .. }
+ | thir::ExprKind::UpvarRef { .. }
+ | thir::ExprKind::Borrow { .. }
+ | thir::ExprKind::AddressOf { .. }
+ | thir::ExprKind::Break { .. }
+ | thir::ExprKind::Continue { .. }
+ | thir::ExprKind::Return { .. }
+ | thir::ExprKind::Array { .. }
+ | thir::ExprKind::Tuple { .. }
+ | thir::ExprKind::Adt(_)
+ | thir::ExprKind::PlaceTypeAscription { .. }
+ | thir::ExprKind::ValueTypeAscription { .. }
+ | thir::ExprKind::Closure(_)
+ | thir::ExprKind::Literal { .. }
+ | thir::ExprKind::NonHirLiteral { .. }
+ | thir::ExprKind::ZstLiteral { .. }
+ | thir::ExprKind::StaticRef { .. }
+ | thir::ExprKind::InlineAsm(_)
+ | thir::ExprKind::ThreadLocalRef(_)
+ | thir::ExprKind::Yield { .. } => false,
}
}
fn pat_is_poly(&mut self, pat: &thir::Pat<'tcx>) -> bool {
@@ -349,10 +389,10 @@ impl<'a, 'tcx> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> {
}
/// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead.
-pub fn thir_abstract_const<'tcx>(
- tcx: TyCtxt<'tcx>,
+pub fn thir_abstract_const(
+ tcx: TyCtxt<'_>,
def: ty::WithOptConstParam<LocalDefId>,
-) -> Result<Option<ty::Const<'tcx>>, ErrorGuaranteed> {
+) -> Result<Option<ty::Const<'_>>, ErrorGuaranteed> {
if tcx.features().generic_const_exprs {
match tcx.def_kind(def.did) {
// FIXME(generic_const_exprs): We currently only do this for anonymous constants,
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index f0d8c240e..7a2464580 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -6,7 +6,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers { assumed_wf_types, ..*providers };
}
-fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List<Ty<'tcx>> {
+fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
match tcx.def_kind(def_id) {
DefKind::Fn => {
let sig = tcx.fn_sig(def_id);
@@ -21,14 +21,16 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List<Ty
assumed_wf_types.extend(liberated_sig.inputs_and_output);
tcx.intern_type_list(&assumed_wf_types)
}
- DefKind::Impl => match tcx.impl_trait_ref(def_id) {
- Some(trait_ref) => {
- let types: Vec<_> = trait_ref.substs.types().collect();
- tcx.intern_type_list(&types)
+ DefKind::Impl => {
+ match tcx.impl_trait_ref(def_id) {
+ Some(trait_ref) => {
+ let types: Vec<_> = trait_ref.skip_binder().substs.types().collect();
+ tcx.intern_type_list(&types)
+ }
+ // Only the impl self type
+ None => tcx.intern_type_list(&[tcx.type_of(def_id)]),
}
- // Only the impl self type
- None => tcx.intern_type_list(&[tcx.type_of(def_id)]),
- },
+ }
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
DefKind::Mod
| DefKind::Struct
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index c6f2b16ca..8d46ba320 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -44,7 +44,13 @@ fn inner_resolve_instance<'tcx>(
let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
- resolve_associated_item(tcx, def.did, param_env, trait_def_id, substs)
+ resolve_associated_item(
+ tcx,
+ def.did,
+ param_env,
+ trait_def_id,
+ tcx.normalize_erasing_regions(param_env, substs),
+ )
} else {
let ty = tcx.type_of(def.def_id_for_type_of());
let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
@@ -188,7 +194,7 @@ fn resolve_associated_item<'tcx>(
&& trait_item_id != leaf_def.item.def_id
&& let Some(leaf_def_item) = leaf_def.item.def_id.as_local()
{
- tcx.compare_assoc_const_impl_item_with_trait_item((
+ tcx.compare_impl_const((
leaf_def_item,
trait_item_id,
))?;
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index fbc055b5d..6aa016133 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -1,3 +1,4 @@
+use hir::def_id::DefId;
use rustc_hir as hir;
use rustc_index::bit_set::BitSet;
use rustc_index::vec::{Idx, IndexVec};
@@ -6,7 +7,7 @@ use rustc_middle::ty::layout::{
IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
};
use rustc_middle::ty::{
- self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
+ self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
};
use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
use rustc_span::symbol::Symbol;
@@ -154,17 +155,37 @@ fn layout_of_uncached<'tcx>(
}
let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
- let metadata = match unsized_part.kind() {
- ty::Foreign(..) => {
+
+ let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
+ let metadata_ty = tcx.normalize_erasing_regions(
+ param_env,
+ tcx.mk_projection(metadata_def_id, [pointee]),
+ );
+ let metadata_layout = cx.layout_of(metadata_ty)?;
+ // If the metadata is a 1-zst, then the pointer is thin.
+ if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 {
return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr)));
}
- ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
- ty::Dynamic(..) => {
- let mut vtable = scalar_unit(Pointer);
- vtable.valid_range_mut().start = 1;
- vtable
+
+ let Abi::Scalar(metadata) = metadata_layout.abi else {
+ return Err(LayoutError::Unknown(unsized_part));
+ };
+ metadata
+ } else {
+ match unsized_part.kind() {
+ ty::Foreign(..) => {
+ return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr)));
+ }
+ ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
+ ty::Dynamic(..) => {
+ let mut vtable = scalar_unit(Pointer);
+ vtable.valid_range_mut().start = 1;
+ vtable
+ }
+ _ => {
+ return Err(LayoutError::Unknown(unsized_part));
+ }
}
- _ => return Err(LayoutError::Unknown(unsized_part)),
};
// Effectively a (ptr, meta) tuple.
@@ -443,7 +464,7 @@ fn layout_of_uncached<'tcx>(
}
// Types with no meaningful known layout.
- ty::Projection(_) | ty::Opaque(..) => {
+ ty::Alias(..) => {
// NOTE(eddyb) `layout_of` query should've normalized these away,
// if that was possible, so there's no reason to try again here.
return Err(LayoutError::Unknown(ty));
@@ -488,8 +509,8 @@ enum SavedLocalEligibility {
// of any variant.
/// Compute the eligibility and assignment of each local.
-fn generator_saved_local_eligibility<'tcx>(
- info: &GeneratorLayout<'tcx>,
+fn generator_saved_local_eligibility(
+ info: &GeneratorLayout<'_>,
) -> (BitSet<GeneratorSavedLocal>, IndexVec<GeneratorSavedLocal, SavedLocalEligibility>) {
use SavedLocalEligibility::*;
@@ -814,27 +835,39 @@ fn record_layout_for_printing_outlined<'tcx>(
);
};
- let adt_def = match *layout.ty.kind() {
- ty::Adt(ref adt_def, _) => {
+ match *layout.ty.kind() {
+ ty::Adt(adt_def, _) => {
debug!("print-type-size t: `{:?}` process adt", layout.ty);
- adt_def
+ let adt_kind = adt_def.adt_kind();
+ let adt_packed = adt_def.repr().pack.is_some();
+ let (variant_infos, opt_discr_size) = variant_info_for_adt(cx, layout, adt_def);
+ record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos);
+ }
+
+ ty::Generator(def_id, substs, _) => {
+ debug!("print-type-size t: `{:?}` record generator", layout.ty);
+ // Generators always have a begin/poisoned/end state with additional suspend points
+ let (variant_infos, opt_discr_size) =
+ variant_info_for_generator(cx, layout, def_id, substs);
+ record(DataTypeKind::Generator, false, opt_discr_size, variant_infos);
}
ty::Closure(..) => {
debug!("print-type-size t: `{:?}` record closure", layout.ty);
record(DataTypeKind::Closure, false, None, vec![]);
- return;
}
_ => {
debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
- return;
}
};
+}
- let adt_kind = adt_def.adt_kind();
- let adt_packed = adt_def.repr().pack.is_some();
-
+fn variant_info_for_adt<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ layout: TyAndLayout<'tcx>,
+ adt_def: AdtDef<'tcx>,
+) -> (Vec<VariantInfo>, Option<Size>) {
let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
let mut min_size = Size::ZERO;
let field_info: Vec<_> = flds
@@ -843,10 +876,7 @@ fn record_layout_for_printing_outlined<'tcx>(
.map(|(i, &name)| {
let field_layout = layout.field(cx, i);
let offset = layout.fields.offset(i);
- let field_end = offset + field_layout.size;
- if min_size < field_end {
- min_size = field_end;
- }
+ min_size = min_size.max(offset + field_layout.size);
FieldInfo {
name,
offset: offset.bytes(),
@@ -871,16 +901,9 @@ fn record_layout_for_printing_outlined<'tcx>(
debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name);
let variant_def = &adt_def.variant(index);
let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
- record(
- adt_kind.into(),
- adt_packed,
- None,
- vec![build_variant_info(Some(variant_def.name), &fields, layout)],
- );
+ (vec![build_variant_info(Some(variant_def.name), &fields, layout)], None)
} else {
- // (This case arises for *empty* enums; so give it
- // zero variants.)
- record(adt_kind.into(), adt_packed, None, vec![]);
+ (vec![], None)
}
}
@@ -898,15 +921,117 @@ fn record_layout_for_printing_outlined<'tcx>(
build_variant_info(Some(variant_def.name), &fields, layout.for_variant(cx, i))
})
.collect();
- record(
- adt_kind.into(),
- adt_packed,
+
+ (
+ variant_infos,
match tag_encoding {
TagEncoding::Direct => Some(tag.size(cx)),
_ => None,
},
- variant_infos,
- );
+ )
}
}
}
+
+fn variant_info_for_generator<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ layout: TyAndLayout<'tcx>,
+ def_id: DefId,
+ substs: ty::SubstsRef<'tcx>,
+) -> (Vec<VariantInfo>, Option<Size>) {
+ let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else {
+ return (vec![], None);
+ };
+
+ let (generator, state_specific_names) = cx.tcx.generator_layout_and_saved_local_names(def_id);
+ let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
+
+ let mut upvars_size = Size::ZERO;
+ let upvar_fields: Vec<_> = substs
+ .as_generator()
+ .upvar_tys()
+ .zip(upvar_names)
+ .enumerate()
+ .map(|(field_idx, (_, name))| {
+ let field_layout = layout.field(cx, field_idx);
+ let offset = layout.fields.offset(field_idx);
+ upvars_size = upvars_size.max(offset + field_layout.size);
+ FieldInfo {
+ name: Symbol::intern(&name),
+ offset: offset.bytes(),
+ size: field_layout.size.bytes(),
+ align: field_layout.align.abi.bytes(),
+ }
+ })
+ .collect();
+
+ let variant_infos: Vec<_> = generator
+ .variant_fields
+ .iter_enumerated()
+ .map(|(variant_idx, variant_def)| {
+ let variant_layout = layout.for_variant(cx, variant_idx);
+ let mut variant_size = Size::ZERO;
+ let fields = variant_def
+ .iter()
+ .enumerate()
+ .map(|(field_idx, local)| {
+ let field_layout = variant_layout.field(cx, field_idx);
+ let offset = variant_layout.fields.offset(field_idx);
+ // The struct is as large as the last field's end
+ variant_size = variant_size.max(offset + field_layout.size);
+ FieldInfo {
+ name: state_specific_names.get(*local).copied().flatten().unwrap_or(
+ Symbol::intern(&format!(".generator_field{}", local.as_usize())),
+ ),
+ offset: offset.bytes(),
+ size: field_layout.size.bytes(),
+ align: field_layout.align.abi.bytes(),
+ }
+ })
+ .chain(upvar_fields.iter().copied())
+ .collect();
+
+ // If the variant has no state-specific fields, then it's the size of the upvars.
+ if variant_size == Size::ZERO {
+ variant_size = upvars_size;
+ }
+
+ // This `if` deserves some explanation.
+ //
+ // The layout code has a choice of where to place the discriminant of this generator.
+ // If the discriminant of the generator is placed early in the layout (before the
+ // variant's own fields), then it'll implicitly be counted towards the size of the
+ // variant, since we use the maximum offset to calculate size.
+ // (side-note: I know this is a bit problematic given upvars placement, etc).
+ //
+ // This is important, since the layout printing code always subtracts this discriminant
+ // size from the variant size if the struct is "enum"-like, so failing to account for it
+ // will either lead to numerical underflow, or an underreported variant size...
+ //
+ // However, if the discriminant is placed past the end of the variant, then we need
+ // to factor in the size of the discriminant manually. This really should be refactored
+ // better, but this "works" for now.
+ if layout.fields.offset(tag_field) >= variant_size {
+ variant_size += match tag_encoding {
+ TagEncoding::Direct => tag.size(cx),
+ _ => Size::ZERO,
+ };
+ }
+
+ VariantInfo {
+ name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(variant_idx))),
+ kind: SizeKind::Exact,
+ size: variant_size.bytes(),
+ align: variant_layout.align.abi.bytes(),
+ fields,
+ }
+ })
+ .collect();
+ (
+ variant_infos,
+ match tag_encoding {
+ TagEncoding::Direct => Some(tag.size(cx)),
+ _ => None,
+ },
+ )
+}
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 7ad5cbc01..0853de601 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -6,7 +6,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(let_chains)]
-#![feature(control_flow_enum)]
#![feature(never_type)]
#![feature(box_patterns)]
#![recursion_limit = "256"]
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 024dcd591..0df060fc5 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -152,7 +152,7 @@ where
queue_type(self, required);
}
}
- ty::Array(..) | ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => {
+ ty::Array(..) | ty::Alias(..) | ty::Param(_) => {
if ty == component {
// Return the type to the caller: they may be able
// to normalize further than we can.
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 5fc9bcac1..eb5454bf2 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
+use rustc_session::config::TraitSolver;
use rustc_trait_selection::traits;
fn sized_constraint_for_ty<'tcx>(
@@ -37,7 +38,7 @@ fn sized_constraint_for_ty<'tcx>(
.collect()
}
- Projection(..) | Opaque(..) => {
+ Alias(..) => {
// must calculate explicitly.
// FIXME: consider special-casing always-Sized projections
vec![ty]
@@ -121,7 +122,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
// are any errors at that point, so outside of type inference you can be
// sure that this will succeed without errors anyway.
- if tcx.sess.opts.unstable_opts.chalk {
+ if tcx.sess.opts.unstable_opts.trait_solver == TraitSolver::Chalk {
let environment = well_formed_types_in_env(tcx, def_id);
predicates.extend(environment);
}
@@ -161,7 +162,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..),
..
}) => {
- let parent_hir_id = tcx.hir().get_parent_node(hir_id);
+ let parent_hir_id = tcx.hir().parent_id(hir_id);
match tcx.hir().get(parent_hir_id) {
hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { constness, .. }),
@@ -225,10 +226,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
/// that are assumed to be well-formed (because they come from the environment).
///
/// Used only in chalk mode.
-fn well_formed_types_in_env<'tcx>(
- tcx: TyCtxt<'tcx>,
- def_id: DefId,
-) -> &'tcx ty::List<Predicate<'tcx>> {
+fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Predicate<'_>> {
use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind};
use rustc_middle::ty::subst::GenericArgKind;
@@ -291,7 +289,7 @@ fn well_formed_types_in_env<'tcx>(
// In a trait impl, we assume that the header trait ref and all its
// constituents are well-formed.
NodeKind::TraitImpl => {
- let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
+ let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl").subst_identity();
// FIXME(chalk): this has problems because of late-bound regions
//inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk()));
@@ -362,7 +360,8 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
let trait_ref = tcx
.impl_trait_ref(def_id)
- .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id));
+ .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id))
+ .skip_binder();
debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);