From 2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:50 +0200 Subject: Merging upstream version 1.69.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_ty_utils/src/abi.rs | 73 +++---- compiler/rustc_ty_utils/src/assoc.rs | 270 ++++++++++++++++++++++-- compiler/rustc_ty_utils/src/consts.rs | 4 +- compiler/rustc_ty_utils/src/errors.rs | 2 +- compiler/rustc_ty_utils/src/implied_bounds.rs | 12 +- compiler/rustc_ty_utils/src/instance.rs | 5 +- compiler/rustc_ty_utils/src/layout.rs | 108 +++++----- compiler/rustc_ty_utils/src/lib.rs | 4 + compiler/rustc_ty_utils/src/needs_drop.rs | 25 ++- compiler/rustc_ty_utils/src/representability.rs | 4 +- compiler/rustc_ty_utils/src/ty.rs | 151 ++++++++++--- 11 files changed, 517 insertions(+), 141 deletions(-) (limited to 'compiler/rustc_ty_utils/src') diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 91a505a72..35c9f95eb 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -41,7 +41,7 @@ fn fn_sig_for_fn_abi<'tcx>( // We normalize the `fn_sig` again after substituting at a later point. let mut sig = match *ty.kind() { ty::FnDef(def_id, substs) => tcx - .bound_fn_sig(def_id) + .fn_sig(def_id) .map_bound(|fn_sig| { tcx.normalize_erasing_regions(tcx.param_env(def_id), fn_sig) }) @@ -54,7 +54,7 @@ fn fn_sig_for_fn_abi<'tcx>( sig = sig.map_bound(|mut sig| { let mut inputs_and_output = sig.inputs_and_output.to_vec(); inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); - sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); + sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); sig }); } @@ -63,14 +63,14 @@ fn fn_sig_for_fn_abi<'tcx>( ty::Closure(def_id, substs) => { let sig = substs.as_closure().sig(); - let bound_vars = tcx.mk_bound_variable_kinds( + let bound_vars = tcx.mk_bound_variable_kinds_from_iter( sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), ); let br = ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BoundRegionKind::BrEnv, }; - let env_region = ty::ReLateBound(ty::INNERMOST, br); + let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br); let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap(); let sig = sig.skip_binder(); @@ -88,19 +88,18 @@ fn fn_sig_for_fn_abi<'tcx>( ty::Generator(did, substs, _) => { let sig = substs.as_generator().poly_sig(); - let bound_vars = tcx.mk_bound_variable_kinds( + let bound_vars = tcx.mk_bound_variable_kinds_from_iter( sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), ); let br = ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BoundRegionKind::BrEnv, }; - let env_region = ty::ReLateBound(ty::INNERMOST, br); - let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); + let env_ty = tcx.mk_mut_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), ty); let pin_did = tcx.require_lang_item(LangItem::Pin, None); let pin_adt_ref = tcx.adt_def(pin_did); - let pin_substs = tcx.intern_substs(&[env_ty.into()]); + let pin_substs = tcx.mk_substs(&[env_ty.into()]); let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); let sig = sig.skip_binder(); @@ -112,7 +111,7 @@ fn fn_sig_for_fn_abi<'tcx>( // The signature should be `Future::poll(_, &mut Context<'_>) -> Poll` 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 poll_substs = tcx.mk_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 @@ -134,7 +133,7 @@ fn fn_sig_for_fn_abi<'tcx>( // The signature should be `Generator::resume(_, Resume) -> GeneratorState` 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 state_substs = tcx.mk_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) @@ -142,8 +141,8 @@ fn fn_sig_for_fn_abi<'tcx>( ty::Binder::bind_with_vars( tcx.mk_fn_sig( - [env_ty, resume_ty].iter(), - &ret_ty, + [env_ty, resume_ty], + ret_ty, false, hir::Unsafety::Normal, rustc_target::spec::abi::Abi::Rust, @@ -207,11 +206,8 @@ fn fn_abi_of_instance<'tcx>( let sig = fn_sig_for_fn_abi(tcx, instance, param_env); - let caller_location = if instance.def.requires_caller_location(tcx) { - Some(tcx.caller_location_ty()) - } else { - None - }; + let caller_location = + instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty()); fn_abi_new_uncached( &LayoutCx { tcx, param_env }, @@ -244,7 +240,7 @@ fn adjust_for_rust_scalar<'tcx>( } // Only pointer types handled below. - let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return }; + let Scalar::Initialized { value: Pointer(_), valid_range} = scalar else { return }; if !valid_range.contains(0) { attrs.set(ArgAttribute::NonNull); @@ -254,15 +250,18 @@ fn adjust_for_rust_scalar<'tcx>( if let Some(kind) = pointee.safe { attrs.pointee_align = Some(pointee.align); - // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable - // for the entire duration of the function as they can be deallocated - // at any time. Same for shared mutable references. If LLVM had a - // way to say "dereferenceable on entry" we could use it here. + // `Box` are not necessarily dereferenceable for the entire duration of the function as + // they can be deallocated at any time. Same for non-frozen shared references (see + // ), and for mutable references to + // potentially self-referential types (see + // ). If LLVM had a way + // to say "dereferenceable on entry" we could use it here. attrs.pointee_size = match kind { - PointerKind::UniqueBorrowed - | PointerKind::UniqueBorrowedPinned - | PointerKind::Frozen => pointee.size, - PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO, + PointerKind::Box { .. } + | PointerKind::SharedRef { frozen: false } + | PointerKind::MutableRef { unpin: false } => Size::ZERO, + PointerKind::SharedRef { frozen: true } + | PointerKind::MutableRef { unpin: true } => pointee.size, }; // The aliasing rules for `Box` are still not decided, but currently we emit @@ -275,18 +274,16 @@ fn adjust_for_rust_scalar<'tcx>( // 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 + // `&T` where `T` contains no `UnsafeCell` is immutable, 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. However this only applies to arguments, + // not return values. // - // `&T` where `T` contains no `UnsafeCell` is immutable, - // 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 + // `&mut T` and `Box` where `T: Unpin` are unique and hence `noalias`. let no_alias = match kind { - PointerKind::SharedMutable | PointerKind::UniqueBorrowedPinned => false, - PointerKind::UniqueBorrowed => noalias_mut_ref, - PointerKind::UniqueOwned => noalias_for_box, - PointerKind::Frozen => true, + PointerKind::SharedRef { frozen } => frozen, + PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref, + PointerKind::Box { unpin } => unpin && noalias_for_box, }; // We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics // (see ). @@ -294,7 +291,7 @@ fn adjust_for_rust_scalar<'tcx>( attrs.set(ArgAttribute::NoAlias); } - if kind == PointerKind::Frozen && !is_return { + if matches!(kind, PointerKind::SharedRef { frozen: true }) && !is_return { attrs.set(ArgAttribute::ReadOnly); } } @@ -479,7 +476,7 @@ fn fn_abi_adjust_for_abi<'tcx>( } let size = arg.layout.size; - if arg.layout.is_unsized() || size > Pointer.size(cx) { + if arg.layout.is_unsized() || size > Pointer(AddressSpace::DATA).size(cx) { arg.make_indirect(); } else { // We want to pass small aggregates as immediates, but using diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 424b52309..0648784b2 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -1,13 +1,19 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; -use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::definitions::DefPathData; +use rustc_hir::intravisit::{self, Visitor}; +use rustc_middle::ty::{self, DefIdTree, ImplTraitInTraitData, InternalSubsts, TyCtxt}; +use rustc_span::symbol::kw; pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { associated_item, associated_item_def_ids, associated_items, + associated_items_for_impl_trait_in_trait, + associated_item_for_impl_trait_in_trait, impl_item_implementor_ids, ..*providers }; @@ -16,20 +22,79 @@ pub fn provide(providers: &mut ty::query::Providers) { fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { let item = tcx.hir().expect_item(def_id.expect_local()); match item.kind { - hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter( - trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()), - ), - hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter( - impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()), - ), - hir::ItemKind::TraitAlias(..) => &[], + hir::ItemKind::Trait(.., ref trait_item_refs) => { + if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty { + // We collect RPITITs for each trait method's return type and create a + // corresponding associated item using associated_items_for_impl_trait_in_trait + // query. + tcx.arena.alloc_from_iter( + trait_item_refs + .iter() + .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()) + .chain( + trait_item_refs + .iter() + .filter(|trait_item_ref| { + matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. }) + }) + .flat_map(|trait_item_ref| { + let trait_fn_def_id = + trait_item_ref.id.owner_id.def_id.to_def_id(); + tcx.associated_items_for_impl_trait_in_trait(trait_fn_def_id) + }) + .map(|def_id| *def_id), + ), + ) + } else { + tcx.arena.alloc_from_iter( + trait_item_refs + .iter() + .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()), + ) + } + } + hir::ItemKind::Impl(ref impl_) => { + if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty { + // We collect RPITITs for each trait method's return type, on the impl side too and + // create a corresponding associated item using + // associated_items_for_impl_trait_in_trait query. + tcx.arena.alloc_from_iter( + impl_ + .items + .iter() + .map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()) + .chain(impl_.of_trait.iter().flat_map(|_| { + impl_ + .items + .iter() + .filter(|impl_item_ref| { + matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. }) + }) + .flat_map(|impl_item_ref| { + let impl_fn_def_id = + impl_item_ref.id.owner_id.def_id.to_def_id(); + tcx.associated_items_for_impl_trait_in_trait(impl_fn_def_id) + }) + .map(|def_id| *def_id) + })), + ) + } else { + tcx.arena.alloc_from_iter( + impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()), + ) + } + } _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), } } -fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> { - let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)); - ty::AssocItems::new(items) +fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems { + if tcx.is_trait_alias(def_id) { + ty::AssocItems::new(Vec::new()) + } else { + let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)); + ty::AssocItems::new(items) + } } fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap { @@ -109,3 +174,184 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A fn_has_self_parameter: has_self, } } + +/// Given an `fn_def_id` of a trait or of an impl that implements a given trait: +/// if `fn_def_id` is the def id of a function defined inside a trait, then it creates and returns +/// the associated items that correspond to each impl trait in return position for that trait. +/// if `fn_def_id` is the def id of a function defined inside an impl that implements a trait, then it +/// creates and returns the associated items that correspond to each impl trait in return position +/// of the implemented trait. +fn associated_items_for_impl_trait_in_trait(tcx: TyCtxt<'_>, fn_def_id: DefId) -> &'_ [DefId] { + let parent_def_id = tcx.parent(fn_def_id); + + match tcx.def_kind(parent_def_id) { + DefKind::Trait => { + struct RPITVisitor { + rpits: Vec, + } + + impl<'v> Visitor<'v> for RPITVisitor { + fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { + if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind { + self.rpits.push(item_id.owner_id.def_id) + } + intravisit::walk_ty(self, ty) + } + } + + let mut visitor = RPITVisitor { rpits: Vec::new() }; + + if let Some(output) = tcx.hir().get_fn_output(fn_def_id.expect_local()) { + visitor.visit_fn_ret_ty(output); + + tcx.arena.alloc_from_iter(visitor.rpits.iter().map(|opaque_ty_def_id| { + tcx.associated_item_for_impl_trait_in_trait(opaque_ty_def_id).to_def_id() + })) + } else { + &[] + } + } + + DefKind::Impl { .. } => { + let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else { return &[] }; + + tcx.arena.alloc_from_iter( + tcx.associated_items_for_impl_trait_in_trait(trait_fn_def_id).iter().map( + move |trait_assoc_def_id| { + impl_associated_item_for_impl_trait_in_trait( + tcx, + trait_assoc_def_id.expect_local(), + fn_def_id.expect_local(), + ) + .to_def_id() + }, + ), + ) + } + + def_kind => bug!( + "associated_items_for_impl_trait_in_trait: {:?} should be Trait or Impl but is {:?}", + parent_def_id, + def_kind + ), + } +} + +/// Given an `opaque_ty_def_id` corresponding to an impl trait in trait, create and return the +/// corresponding associated item. +fn associated_item_for_impl_trait_in_trait( + tcx: TyCtxt<'_>, + opaque_ty_def_id: LocalDefId, +) -> LocalDefId { + let fn_def_id = tcx.impl_trait_in_trait_parent(opaque_ty_def_id.to_def_id()); + let trait_def_id = tcx.parent(fn_def_id); + assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait); + + let span = tcx.def_span(opaque_ty_def_id); + let trait_assoc_ty = + tcx.at(span).create_def(trait_def_id.expect_local(), DefPathData::ImplTraitAssocTy); + + let local_def_id = trait_assoc_ty.def_id(); + let def_id = local_def_id.to_def_id(); + + trait_assoc_ty.opt_def_kind(Some(DefKind::AssocTy)); + + // There's no HIR associated with this new synthesized `def_id`, so feed + // `opt_local_def_id_to_hir_id` with `None`. + trait_assoc_ty.opt_local_def_id_to_hir_id(None); + + // Copy span of the opaque. + trait_assoc_ty.def_ident_span(Some(span)); + + // Add the def_id of the function and opaque that generated this synthesized associated type. + trait_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Trait { + fn_def_id, + opaque_def_id: opaque_ty_def_id.to_def_id(), + })); + + trait_assoc_ty.associated_item(ty::AssocItem { + name: kw::Empty, + kind: ty::AssocKind::Type, + def_id, + trait_item_def_id: None, + container: ty::TraitContainer, + fn_has_self_parameter: false, + }); + + // Copy visility of the containing function. + trait_assoc_ty.visibility(tcx.visibility(fn_def_id)); + + // Copy impl_defaultness of the containing function. + trait_assoc_ty.impl_defaultness(tcx.impl_defaultness(fn_def_id)); + + // Copy type_of of the opaque. + trait_assoc_ty.type_of(ty::EarlyBinder(tcx.mk_opaque( + opaque_ty_def_id.to_def_id(), + InternalSubsts::identity_for_item(tcx, opaque_ty_def_id.to_def_id()), + ))); + + // Copy generics_of of the opaque. + trait_assoc_ty.generics_of(tcx.generics_of(opaque_ty_def_id).clone()); + + // There are no predicates for the synthesized associated type. + trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates { + parent: Some(trait_def_id), + predicates: &[], + }); + + // There are no inferred outlives for the synthesized associated type. + trait_assoc_ty.inferred_outlives_of(&[]); + + // FIXME implement this. + trait_assoc_ty.explicit_item_bounds(&[]); + + local_def_id +} + +/// Given an `trait_assoc_def_id` that corresponds to a previously synthesized impl trait in trait +/// into an associated type and an `impl_def_id` corresponding to an impl block, create and return +/// the corresponding associated item inside the impl block. +fn impl_associated_item_for_impl_trait_in_trait( + tcx: TyCtxt<'_>, + trait_assoc_def_id: LocalDefId, + impl_fn_def_id: LocalDefId, +) -> LocalDefId { + let impl_def_id = tcx.local_parent(impl_fn_def_id); + + // FIXME fix the span, we probably want the def_id of the return type of the function + let span = tcx.def_span(impl_fn_def_id); + let impl_assoc_ty = tcx.at(span).create_def(impl_def_id, DefPathData::ImplTraitAssocTy); + + let local_def_id = impl_assoc_ty.def_id(); + let def_id = local_def_id.to_def_id(); + + impl_assoc_ty.opt_def_kind(Some(DefKind::AssocTy)); + + // There's no HIR associated with this new synthesized `def_id`, so feed + // `opt_local_def_id_to_hir_id` with `None`. + impl_assoc_ty.opt_local_def_id_to_hir_id(None); + + // Add the def_id of the function that generated this synthesized associated type. + impl_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Impl { + fn_def_id: impl_fn_def_id.to_def_id(), + })); + + impl_assoc_ty.associated_item(ty::AssocItem { + name: kw::Empty, + kind: ty::AssocKind::Type, + def_id, + trait_item_def_id: Some(trait_assoc_def_id.to_def_id()), + container: ty::ImplContainer, + fn_has_self_parameter: false, + }); + + // Copy impl_defaultness of the containing function. + impl_assoc_ty.impl_defaultness(tcx.impl_defaultness(impl_fn_def_id)); + + // Copy generics_of the trait's associated item. + // FIXME: This is not correct, in particular the parent is going to be wrong. So we would need + // to copy from trait_assoc_def_id and adjust things. + impl_assoc_ty.generics_of(tcx.generics_of(trait_assoc_def_id).clone()); + + local_def_id +} diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index a9fbad55d..f26352716 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; use rustc_middle::thir::visit; use rustc_middle::thir::visit::Visitor; use rustc_middle::ty::abstract_const::CastKind; -use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitableExt}; use rustc_middle::{mir, thir}; use rustc_span::Span; use rustc_target::abi::VariantIdx; @@ -144,7 +144,7 @@ fn recurse_build<'tcx>( for &id in args.iter() { new_args.push(recurse_build(tcx, body, id, root_span)?); } - let new_args = tcx.mk_const_list(new_args.iter()); + let new_args = tcx.mk_const_list(&new_args); tcx.mk_const(Expr::FunctionCall(fun, new_args), node.ty) } &ExprKind::Binary { op, lhs, rhs } if check_binop(op) => { diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs index c05eeb353..ab3e62f04 100644 --- a/compiler/rustc_ty_utils/src/errors.rs +++ b/compiler/rustc_ty_utils/src/errors.rs @@ -16,7 +16,7 @@ pub struct NeedsDropOverflow<'tcx> { pub struct GenericConstantTooComplex { #[primary_span] pub span: Span, - #[note(maybe_supported)] + #[note(ty_utils_maybe_supported)] pub maybe_supported: Option<()>, #[subdiagnostic] pub sub: GenericConstantTooComplexSub, diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 7a2464580..7fecee2a3 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -9,26 +9,26 @@ pub fn provide(providers: &mut ty::query::Providers) { fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List> { match tcx.def_kind(def_id) { DefKind::Fn => { - let sig = tcx.fn_sig(def_id); + let sig = tcx.fn_sig(def_id).subst_identity(); let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); liberated_sig.inputs_and_output } DefKind::AssocFn => { - let sig = tcx.fn_sig(def_id); + let sig = tcx.fn_sig(def_id).subst_identity(); let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); let mut assumed_wf_types: Vec<_> = tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into(); assumed_wf_types.extend(liberated_sig.inputs_and_output); - tcx.intern_type_list(&assumed_wf_types) + tcx.mk_type_list(&assumed_wf_types) } - DefKind::Impl => { + 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) + tcx.mk_type_list(&types) } // Only the impl self type - None => tcx.intern_type_list(&[tcx.type_of(def_id)]), + None => tcx.mk_type_list(&[tcx.type_of(def_id).subst_identity()]), } } DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)), diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 8d46ba320..2eaeca73d 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -3,7 +3,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt}; use rustc_span::sym; use rustc_trait_selection::traits; use traits::{translate_substs, Reveal}; @@ -53,7 +53,8 @@ fn inner_resolve_instance<'tcx>( ) } 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); + let item_type = + tcx.subst_and_normalize_erasing_regions(substs, param_env, ty.skip_binder()); let def = match *item_type.kind() { ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => { diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 6aa016133..e3132fcc4 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -7,9 +7,9 @@ use rustc_middle::ty::layout::{ IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES, }; use rustc_middle::ty::{ - self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable, + self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitableExt, }; -use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; +use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::symbol::Symbol; use rustc_span::DUMMY_SP; use rustc_target::abi::*; @@ -78,10 +78,10 @@ fn invert_mapping(map: &[u32]) -> Vec { fn univariant_uninterned<'tcx>( cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, ty: Ty<'tcx>, - fields: &[TyAndLayout<'_>], + fields: &[Layout<'_>], repr: &ReprOptions, kind: StructKind, -) -> Result, LayoutError<'tcx>> { +) -> Result> { let dl = cx.data_layout(); let pack = repr.pack; if pack.is_some() && repr.align.is_some() { @@ -104,23 +104,23 @@ fn layout_of_uncached<'tcx>( assert!(size.bits() <= 128); Scalar::Initialized { value, valid_range: WrappingRange::full(size) } }; - let scalar = |value: Primitive| tcx.intern_layout(LayoutS::scalar(cx, scalar_unit(value))); + let scalar = |value: Primitive| tcx.mk_layout(LayoutS::scalar(cx, scalar_unit(value))); - let univariant = |fields: &[TyAndLayout<'_>], repr: &ReprOptions, kind| { - Ok(tcx.intern_layout(univariant_uninterned(cx, ty, fields, repr, kind)?)) + let univariant = |fields: &[Layout<'_>], repr: &ReprOptions, kind| { + Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, repr, kind)?)) }; debug_assert!(!ty.has_non_region_infer()); Ok(match *ty.kind() { // Basic scalars. - ty::Bool => tcx.intern_layout(LayoutS::scalar( + ty::Bool => tcx.mk_layout(LayoutS::scalar( cx, Scalar::Initialized { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 }, }, )), - ty::Char => tcx.intern_layout(LayoutS::scalar( + ty::Char => tcx.mk_layout(LayoutS::scalar( cx, Scalar::Initialized { value: Int(I32, false), @@ -134,24 +134,24 @@ fn layout_of_uncached<'tcx>( ty::FloatTy::F64 => F64, }), ty::FnPtr(_) => { - let mut ptr = scalar_unit(Pointer); + let mut ptr = scalar_unit(Pointer(dl.instruction_address_space)); ptr.valid_range_mut().start = 1; - tcx.intern_layout(LayoutS::scalar(cx, ptr)) + tcx.mk_layout(LayoutS::scalar(cx, ptr)) } // The never type. - ty::Never => tcx.intern_layout(cx.layout_of_never_type()), + ty::Never => tcx.mk_layout(cx.layout_of_never_type()), // Potentially-wide pointers. ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { - let mut data_ptr = scalar_unit(Pointer); + let mut data_ptr = scalar_unit(Pointer(AddressSpace::DATA)); if !ty.is_unsafe_ptr() { data_ptr.valid_range_mut().start = 1; } let pointee = tcx.normalize_erasing_regions(param_env, pointee); if pointee.is_sized(tcx, param_env) { - return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr))); + return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); } let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); @@ -164,7 +164,7 @@ fn layout_of_uncached<'tcx>( 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))); + return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); } let Abi::Scalar(metadata) = metadata_layout.abi else { @@ -174,11 +174,11 @@ fn layout_of_uncached<'tcx>( } else { match unsized_part.kind() { ty::Foreign(..) => { - return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr))); + return Ok(tcx.mk_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); + let mut vtable = scalar_unit(Pointer(AddressSpace::DATA)); vtable.valid_range_mut().start = 1; vtable } @@ -189,15 +189,15 @@ fn layout_of_uncached<'tcx>( }; // Effectively a (ptr, meta) tuple. - tcx.intern_layout(cx.scalar_pair(data_ptr, metadata)) + tcx.mk_layout(cx.scalar_pair(data_ptr, metadata)) } ty::Dynamic(_, _, ty::DynStar) => { - let mut data = scalar_unit(Int(dl.ptr_sized_integer(), false)); + let mut data = scalar_unit(Pointer(AddressSpace::DATA)); data.valid_range_mut().start = 0; - let mut vtable = scalar_unit(Pointer); + let mut vtable = scalar_unit(Pointer(AddressSpace::DATA)); vtable.valid_range_mut().start = 1; - tcx.intern_layout(cx.scalar_pair(data, vtable)) + tcx.mk_layout(cx.scalar_pair(data, vtable)) } // Arrays and slices. @@ -209,7 +209,8 @@ fn layout_of_uncached<'tcx>( } } - let count = count.try_eval_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?; + let count = + count.try_eval_target_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?; let element = cx.layout_of(element)?; let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow(ty))?; @@ -221,7 +222,7 @@ fn layout_of_uncached<'tcx>( let largest_niche = if count != 0 { element.largest_niche } else { None }; - tcx.intern_layout(LayoutS { + tcx.mk_layout(LayoutS { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Array { stride: element.size, count }, abi, @@ -232,7 +233,7 @@ fn layout_of_uncached<'tcx>( } ty::Slice(element) => { let element = cx.layout_of(element)?; - tcx.intern_layout(LayoutS { + tcx.mk_layout(LayoutS { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Array { stride: element.size, count: 0 }, abi: Abi::Aggregate { sized: false }, @@ -241,7 +242,7 @@ fn layout_of_uncached<'tcx>( size: Size::ZERO, }) } - ty::Str => tcx.intern_layout(LayoutS { + ty::Str => tcx.mk_layout(LayoutS { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, abi: Abi::Aggregate { sized: false }, @@ -264,7 +265,7 @@ fn layout_of_uncached<'tcx>( Abi::Aggregate { ref mut sized } => *sized = false, _ => bug!(), } - tcx.intern_layout(unit) + tcx.mk_layout(unit) } ty::Generator(def_id, substs, _) => generator_layout(cx, ty, def_id, substs)?, @@ -272,7 +273,7 @@ fn layout_of_uncached<'tcx>( ty::Closure(_, ref substs) => { let tys = substs.as_closure().upvar_tys(); univariant( - &tys.map(|ty| cx.layout_of(ty)).collect::, _>>()?, + &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).collect::, _>>()?, &ReprOptions::default(), StructKind::AlwaysSized, )? @@ -283,7 +284,7 @@ fn layout_of_uncached<'tcx>( if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; univariant( - &tys.iter().map(|k| cx.layout_of(k)).collect::, _>>()?, + &tys.iter().map(|k| Ok(cx.layout_of(k)?.layout)).collect::, _>>()?, &ReprOptions::default(), kind, )? @@ -393,7 +394,7 @@ fn layout_of_uncached<'tcx>( FieldsShape::Array { stride: e_ly.size, count: e_len } }; - tcx.intern_layout(LayoutS { + tcx.mk_layout(LayoutS { variants: Variants::Single { index: VariantIdx::new(0) }, fields, abi: Abi::Vector { element: e_abi, count: e_len }, @@ -412,7 +413,7 @@ fn layout_of_uncached<'tcx>( .map(|v| { v.fields .iter() - .map(|field| cx.layout_of(field.ty(tcx, substs))) + .map(|field| Ok(cx.layout_of(field.ty(tcx, substs))?.layout)) .collect::, _>>() }) .collect::, _>>()?; @@ -426,12 +427,12 @@ fn layout_of_uncached<'tcx>( return Err(LayoutError::Unknown(ty)); } - return Ok(tcx.intern_layout( + return Ok(tcx.mk_layout( cx.layout_of_union(&def.repr(), &variants).ok_or(LayoutError::Unknown(ty))?, )); } - tcx.intern_layout( + tcx.mk_layout( cx.layout_of_struct_or_enum( &def.repr(), &variants, @@ -452,9 +453,10 @@ fn layout_of_uncached<'tcx>( let param_env = tcx.param_env(def.did()); def.is_struct() && match def.variants().iter().next().and_then(|x| x.fields.last()) { - Some(last_field) => { - tcx.type_of(last_field.did).is_sized(tcx, param_env) - } + Some(last_field) => tcx + .type_of(last_field.did) + .subst_identity() + .is_sized(tcx, param_env), None => false, } }, @@ -470,11 +472,11 @@ fn layout_of_uncached<'tcx>( return Err(LayoutError::Unknown(ty)); } - ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Infer(_) => { + ty::Bound(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Infer(_) => { bug!("Layout::compute: unexpected type `{}`", ty) } - ty::Bound(..) | ty::Param(_) | ty::Error(_) => { + ty::Placeholder(..) | ty::Param(_) | ty::Error(_) => { return Err(LayoutError::Unknown(ty)); } }) @@ -630,23 +632,21 @@ fn generator_layout<'tcx>( // `info.variant_fields` already accounts for the reserved variants, so no need to add them. let max_discr = (info.variant_fields.len() - 1) as u128; let discr_int = Integer::fit_unsigned(max_discr); - let discr_int_ty = discr_int.to_ty(tcx, false); let tag = Scalar::Initialized { value: Primitive::Int(discr_int, false), valid_range: WrappingRange { start: 0, end: max_discr }, }; - let tag_layout = cx.tcx.intern_layout(LayoutS::scalar(cx, tag)); - let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout }; + let tag_layout = cx.tcx.mk_layout(LayoutS::scalar(cx, tag)); let promoted_layouts = ineligible_locals .iter() - .map(|local| subst_field(info.field_tys[local])) + .map(|local| subst_field(info.field_tys[local].ty)) .map(|ty| tcx.mk_maybe_uninit(ty)) - .map(|ty| cx.layout_of(ty)); + .map(|ty| Ok(cx.layout_of(ty)?.layout)); let prefix_layouts = substs .as_generator() .prefix_tys() - .map(|ty| cx.layout_of(ty)) + .map(|ty| Ok(cx.layout_of(ty)?.layout)) .chain(iter::once(Ok(tag_layout))) .chain(promoted_layouts) .collect::, _>>()?; @@ -710,12 +710,14 @@ fn generator_layout<'tcx>( Assigned(_) => bug!("assignment does not match variant"), Ineligible(_) => false, }) - .map(|local| subst_field(info.field_tys[*local])); + .map(|local| subst_field(info.field_tys[*local].ty)); let mut variant = univariant_uninterned( cx, ty, - &variant_only_tys.map(|ty| cx.layout_of(ty)).collect::, _>>()?, + &variant_only_tys + .map(|ty| Ok(cx.layout_of(ty)?.layout)) + .collect::, _>>()?, &ReprOptions::default(), StructKind::Prefixed(prefix_size, prefix_align.abi), )?; @@ -782,7 +784,7 @@ fn generator_layout<'tcx>( Abi::Aggregate { sized: true } }; - let layout = tcx.intern_layout(LayoutS { + let layout = tcx.mk_layout(LayoutS { variants: Variants::Multiple { tag, tag_encoding: TagEncoding::Direct, @@ -878,6 +880,7 @@ fn variant_info_for_adt<'tcx>( let offset = layout.fields.offset(i); min_size = min_size.max(offset + field_layout.size); FieldInfo { + kind: FieldKind::AdtField, name, offset: offset.bytes(), size: field_layout.size.bytes(), @@ -957,6 +960,7 @@ fn variant_info_for_generator<'tcx>( let offset = layout.fields.offset(field_idx); upvars_size = upvars_size.max(offset + field_layout.size); FieldInfo { + kind: FieldKind::Upvar, name: Symbol::intern(&name), offset: offset.bytes(), size: field_layout.size.bytes(), @@ -965,7 +969,7 @@ fn variant_info_for_generator<'tcx>( }) .collect(); - let variant_infos: Vec<_> = generator + let mut variant_infos: Vec<_> = generator .variant_fields .iter_enumerated() .map(|(variant_idx, variant_def)| { @@ -980,6 +984,7 @@ fn variant_info_for_generator<'tcx>( // The struct is as large as the last field's end variant_size = variant_size.max(offset + field_layout.size); FieldInfo { + kind: FieldKind::GeneratorLocal, name: state_specific_names.get(*local).copied().flatten().unwrap_or( Symbol::intern(&format!(".generator_field{}", local.as_usize())), ), @@ -1027,6 +1032,15 @@ fn variant_info_for_generator<'tcx>( } }) .collect(); + + // The first three variants are hardcoded to be `UNRESUMED`, `RETURNED` and `POISONED`. + // We will move the `RETURNED` and `POISONED` elements to the end so we + // are left with a sorting order according to the generators yield points: + // First `Unresumed`, then the `SuspendN` followed by `Returned` and `Panicked` (POISONED). + let end_states = variant_infos.drain(1..=2); + let end_states: Vec<_> = end_states.collect(); + variant_infos.extend(end_states); + ( variant_infos, match tag_encoding { diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 0853de601..35f468aa9 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -15,6 +15,8 @@ extern crate rustc_middle; #[macro_use] extern crate tracing; +use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; +use rustc_macros::fluent_messages; use rustc_middle::ty::query::Providers; mod abi; @@ -31,6 +33,8 @@ pub mod representability; mod structural_match; mod ty; +fluent_messages! { "../locales/en-US.ftl" } + pub fn provide(providers: &mut Providers) { abi::provide(providers); assoc::provide(providers); diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 0df060fc5..de7fd0031 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -109,6 +109,13 @@ where for component in components { match *component.kind() { + // The information required to determine whether a generator has drop is + // computed on MIR, while this very method is used to build MIR. + // To avoid cycles, we consider that generators always require drop. + ty::Generator(..) if tcx.sess.opts.unstable_opts.drop_tracking_mir => { + return Some(Err(AlwaysRequiresDrop)); + } + _ if component.is_copy_modulo_regions(tcx, self.param_env) => (), ty::Closure(_, substs) => { @@ -235,7 +242,7 @@ fn drop_tys_helper<'tcx>( Ok(Vec::new()) } else { let field_tys = adt_def.all_fields().map(|field| { - let r = tcx.bound_type_of(field.did).subst(tcx, substs); + let r = tcx.type_of(field.did).subst(tcx, substs); debug!("drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", field, substs, r); r }); @@ -288,9 +295,15 @@ fn adt_drop_tys<'tcx>( let adt_has_dtor = |adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant); // `tcx.type_of(def_id)` identical to `tcx.make_adt(def, identity_substs)` - drop_tys_helper(tcx, tcx.type_of(def_id), tcx.param_env(def_id), adt_has_dtor, false) - .collect::, _>>() - .map(|components| tcx.intern_type_list(&components)) + drop_tys_helper( + tcx, + tcx.type_of(def_id).subst_identity(), + tcx.param_env(def_id), + adt_has_dtor, + false, + ) + .collect::, _>>() + .map(|components| tcx.mk_type_list(&components)) } // If `def_id` refers to a generic ADT, the queries above and below act as if they had been handed // a `tcx.make_ty(def, identity_substs)` and as such it is legal to substitute the generic parameters @@ -301,13 +314,13 @@ fn adt_significant_drop_tys( ) -> Result<&ty::List>, AlwaysRequiresDrop> { drop_tys_helper( tcx, - tcx.type_of(def_id), // identical to `tcx.make_adt(def, identity_substs)` + tcx.type_of(def_id).subst_identity(), // identical to `tcx.make_adt(def, identity_substs)` tcx.param_env(def_id), adt_consider_insignificant_dtor(tcx), true, ) .collect::, _>>() - .map(|components| tcx.intern_type_list(&components)) + .map(|components| tcx.mk_type_list(&components)) } pub(crate) fn provide(providers: &mut ty::query::Providers) { diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index 7f48fb804..591017eec 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -31,7 +31,7 @@ fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability { } Representability::Representable } - DefKind::Field => representability_ty(tcx, tcx.type_of(def_id)), + DefKind::Field => representability_ty(tcx, tcx.type_of(def_id).subst_identity()), def_kind => bug!("unexpected {def_kind:?}"), } } @@ -91,7 +91,7 @@ fn params_in_repr(tcx: TyCtxt<'_>, def_id: DefId) -> BitSet { let mut params_in_repr = BitSet::new_empty(generics.params.len()); for variant in adt_def.variants() { for field in variant.fields.iter() { - params_in_repr_ty(tcx, tcx.type_of(field.did), &mut params_in_repr); + params_in_repr_ty(tcx, tcx.type_of(field.did).subst_identity(), &mut params_in_repr); } } params_in_repr diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index eb5454bf2..18159778a 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -1,8 +1,13 @@ -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::{FxHashSet, 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_hir::def::DefKind; +use rustc_index::bit_set::BitSet; +use rustc_middle::ty::{ + self, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, + TypeSuperVisitable, TypeVisitable, TypeVisitor, +}; use rustc_session::config::TraitSolver; +use rustc_span::def_id::{DefId, CRATE_DEF_ID}; use rustc_trait_selection::traits; fn sized_constraint_for_ty<'tcx>( @@ -16,7 +21,13 @@ fn sized_constraint_for_ty<'tcx>( Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..) | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![], - Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | GeneratorWitness(..) => { + Str + | Dynamic(..) + | Slice(_) + | Foreign(..) + | Error(_) + | GeneratorWitness(..) + | GeneratorWitnessMIR(..) => { // these are never sized - return the target type vec![ty] } @@ -87,16 +98,16 @@ fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness { fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] { if let Some(def_id) = def_id.as_local() { if matches!(tcx.representability(def_id), ty::Representability::Infinite) { - return tcx.intern_type_list(&[tcx.ty_error()]); + return tcx.mk_type_list(&[tcx.ty_error_misc()]); } } let def = tcx.adt_def(def_id); - let result = tcx.mk_type_list( + let result = tcx.mk_type_list_from_iter( def.variants() .iter() .flat_map(|v| v.fields.last()) - .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did))), + .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).subst_identity())), ); debug!("adt_sized_constraint: {:?} => {:?}", def, result); @@ -127,6 +138,19 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { predicates.extend(environment); } + if tcx.def_kind(def_id) == DefKind::AssocFn + && tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer + { + let sig = tcx.fn_sig(def_id).subst_identity(); + sig.visit_with(&mut ImplTraitInTraitFinder { + tcx, + fn_def_id: def_id, + bound_vars: sig.bound_vars(), + predicates: &mut predicates, + seen: FxHashSet::default(), + }); + } + let local_did = def_id.as_local(); let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)); @@ -202,24 +226,54 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { None => hir::Constness::NotConst, }; - let unnormalized_env = ty::ParamEnv::new( - tcx.intern_predicates(&predicates), - traits::Reveal::UserFacing, - constness, - ); - - let body_id = - local_did.and_then(|id| tcx.hir().maybe_body_owned_by(id).map(|body| body.hir_id)); - let body_id = match body_id { - Some(id) => id, - None if hir_id.is_some() => hir_id.unwrap(), - _ => hir::CRATE_HIR_ID, - }; + let unnormalized_env = + ty::ParamEnv::new(tcx.mk_predicates(&predicates), traits::Reveal::UserFacing, constness); + let body_id = local_did.unwrap_or(CRATE_DEF_ID); let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); traits::normalize_param_env_or_error(tcx, unnormalized_env, cause) } +/// Walk through a function type, gathering all RPITITs and installing a +/// `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))` predicate into the +/// predicates list. This allows us to observe that an RPITIT projects to +/// its corresponding opaque within the body of a default-body trait method. +struct ImplTraitInTraitFinder<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + predicates: &'a mut Vec>, + fn_def_id: DefId, + bound_vars: &'tcx ty::List, + seen: FxHashSet, +} + +impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { + if let ty::Alias(ty::Projection, alias_ty) = *ty.kind() + && self.tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder + && self.tcx.impl_trait_in_trait_parent(alias_ty.def_id) == self.fn_def_id + && self.seen.insert(alias_ty.def_id) + { + self.predicates.push( + ty::Binder::bind_with_vars( + ty::ProjectionPredicate { + projection_ty: alias_ty, + term: self.tcx.mk_alias(ty::Opaque, alias_ty).into(), + }, + self.bound_vars, + ) + .to_predicate(self.tcx), + ); + + for bound in self.tcx.item_bounds(alias_ty.def_id).subst_iter(self.tcx, alias_ty.substs) + { + bound.visit_with(self); + } + } + + ty.super_visit_with(self) + } +} + /// Elaborate the environment. /// /// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s @@ -299,14 +353,14 @@ fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List { - let self_ty = tcx.type_of(def_id); + let self_ty = tcx.type_of(def_id).subst_identity(); inputs.extend(self_ty.walk()); } // In an fn, we assume that the arguments and all their constituents are // well-formed. NodeKind::Fn => { - let fn_sig = tcx.fn_sig(def_id); + let fn_sig = tcx.fn_sig(def_id).subst_identity(); let fn_sig = tcx.liberate_late_bound_regions(def_id, fn_sig); inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk())); @@ -329,7 +383,7 @@ fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List, def_id: DefId) -> ty::ParamEnv<'_> { @@ -355,7 +409,7 @@ fn instance_def_size_estimate<'tcx>( /// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`. /// /// See [`ty::ImplOverlapKind::Issue33140`] for more details. -fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { +fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option>> { debug!("issue33140_self_ty({:?})", def_id); let trait_ref = tcx @@ -394,7 +448,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { if self_ty_matches { debug!("issue33140_self_ty - MATCHES!"); - Some(self_ty) + Some(EarlyBinder(self_ty)) } else { debug!("issue33140_self_ty - non-matching self type"); None @@ -407,6 +461,52 @@ 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, + }, + }; + + // 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.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.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, @@ -416,6 +516,7 @@ pub fn provide(providers: &mut ty::query::Providers) { instance_def_size_estimate, issue33140_self_ty, impl_defaultness, + unsizing_params_for_adt, ..*providers }; } -- cgit v1.2.3