diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
commit | 64d98f8ee037282c35007b64c2649055c56af1db (patch) | |
tree | 5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /compiler/rustc_ty_utils/src | |
parent | Adding debian version 1.67.1+dfsg1-1. (diff) | |
download | rustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz rustc-64d98f8ee037282c35007b64c2649055c56af1db.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/src')
-rw-r--r-- | compiler/rustc_ty_utils/src/abi.rs | 81 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/consts.rs | 58 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/implied_bounds.rs | 18 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/instance.rs | 10 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/layout.rs | 201 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/lib.rs | 1 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/needs_drop.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/ty.rs | 17 |
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); |