From d1b2d29528b7794b41e66fc2136e395a02f8529b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:59:35 +0200 Subject: Merging upstream version 1.73.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_ty_utils/src/abi.rs | 29 ++-- compiler/rustc_ty_utils/src/assoc.rs | 128 ++++++++-------- compiler/rustc_ty_utils/src/consts.rs | 15 +- compiler/rustc_ty_utils/src/implied_bounds.rs | 92 ++++++++++-- compiler/rustc_ty_utils/src/instance.rs | 145 +++++++++--------- compiler/rustc_ty_utils/src/layout.rs | 80 ++++++---- compiler/rustc_ty_utils/src/layout_sanity_check.rs | 4 +- compiler/rustc_ty_utils/src/lib.rs | 1 + compiler/rustc_ty_utils/src/needs_drop.rs | 98 ++++++++---- compiler/rustc_ty_utils/src/opaque_types.rs | 45 +++--- compiler/rustc_ty_utils/src/representability.rs | 16 +- compiler/rustc_ty_utils/src/ty.rs | 165 +++++---------------- 12 files changed, 442 insertions(+), 376 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 55484f5c7..4d0b84753 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -9,6 +9,7 @@ use rustc_session::config::OptLevel; use rustc_span::def_id::DefId; use rustc_target::abi::call::{ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind, + RiscvInterruptKind, }; use rustc_target::abi::*; use rustc_target::spec::abi::Abi as SpecAbi; @@ -51,12 +52,12 @@ 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 + ty::FnDef(def_id, args) => tcx .fn_sig(def_id) .map_bound(|fn_sig| { tcx.normalize_erasing_regions(tcx.param_env(def_id), fn_sig) }) - .subst(tcx, substs), + .instantiate(tcx, args), _ => unreachable!(), }; @@ -71,8 +72,8 @@ fn fn_sig_for_fn_abi<'tcx>( } sig } - ty::Closure(def_id, substs) => { - let sig = substs.as_closure().sig(); + ty::Closure(def_id, args) => { + let sig = args.as_closure().sig(); let bound_vars = tcx.mk_bound_variable_kinds_from_iter( sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), @@ -82,7 +83,7 @@ fn fn_sig_for_fn_abi<'tcx>( kind: ty::BoundRegionKind::BrEnv, }; let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br); - let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap(); + let env_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap(); let sig = sig.skip_binder(); ty::Binder::bind_with_vars( @@ -96,8 +97,8 @@ fn fn_sig_for_fn_abi<'tcx>( bound_vars, ) } - ty::Generator(did, substs, _) => { - let sig = substs.as_generator().poly_sig(); + ty::Generator(did, args, _) => { + let sig = args.as_generator().poly_sig(); let bound_vars = tcx.mk_bound_variable_kinds_from_iter( sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), @@ -111,8 +112,8 @@ fn fn_sig_for_fn_abi<'tcx>( let pin_did = tcx.require_lang_item(LangItem::Pin, None); let pin_adt_ref = tcx.adt_def(pin_did); - let pin_substs = tcx.mk_substs(&[env_ty.into()]); - let env_ty = Ty::new_adt(tcx, pin_adt_ref, pin_substs); + let pin_args = tcx.mk_args(&[env_ty.into()]); + let env_ty = Ty::new_adt(tcx, pin_adt_ref, pin_args); let sig = sig.skip_binder(); // The `FnSig` and the `ret_ty` here is for a generators main @@ -123,8 +124,8 @@ 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.mk_substs(&[sig.return_ty.into()]); - let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_substs); + let poll_args = tcx.mk_args(&[sig.return_ty.into()]); + let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_args); // We have to replace the `ResumeTy` that is used for type and borrow checking // with `&mut Context<'_>` which is used in codegen. @@ -145,8 +146,8 @@ 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.mk_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); - let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_substs); + let state_args = tcx.mk_args(&[sig.yield_ty.into(), sig.return_ty.into()]); + let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_args); (sig.resume_ty, ret_ty) }; @@ -193,6 +194,8 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { AmdGpuKernel => Conv::AmdGpuKernel, AvrInterrupt => Conv::AvrInterrupt, AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt, + RiscvInterruptM => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine }, + RiscvInterruptS => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor }, Wasm => Conv::C, // These API constants ought to be more specific... diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 897e7aad4..780f7ea42 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -5,7 +5,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::definitions::DefPathData; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, Ty, TyCtxt}; +use rustc_middle::ty::{self, GenericArgs, ImplTraitInTraitData, Ty, TyCtxt}; use rustc_span::symbol::kw; pub fn provide(providers: &mut Providers) { @@ -24,70 +24,54 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] { let item = tcx.hir().expect_item(def_id); match item.kind { hir::ItemKind::Trait(.., ref trait_item_refs) => { - if tcx.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_types_for_impl_traits_in_associated_fn - // 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_types_for_impl_traits_in_associated_fn( - 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()), - ) - } + // We collect RPITITs for each trait method's return type and create a + // corresponding associated item using associated_types_for_impl_traits_in_associated_fn + // 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_types_for_impl_traits_in_associated_fn( + trait_fn_def_id, + ) + }) + .map(|def_id| *def_id), + ), + ) } hir::ItemKind::Impl(ref impl_) => { - if tcx.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_types_for_impl_traits_in_associated_fn 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_types_for_impl_traits_in_associated_fn( - 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()), - ) - } + // We collect RPITITs for each trait method's return type, on the impl side too and + // create a corresponding associated item using + // associated_types_for_impl_traits_in_associated_fn 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_types_for_impl_traits_in_associated_fn( + impl_fn_def_id, + ) + }) + .map(|def_id| *def_id) + })), + ) } _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), } @@ -231,7 +215,9 @@ fn associated_types_for_impl_traits_in_associated_fn( } DefKind::Impl { .. } => { - let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else { return &[] }; + 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_types_for_impl_traits_in_associated_fn(trait_fn_def_id).iter().map( @@ -304,7 +290,7 @@ fn associated_type_for_impl_trait_in_trait( trait_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_opaque( tcx, opaque_ty_def_id.to_def_id(), - InternalSubsts::identity_for_item(tcx, opaque_ty_def_id), + GenericArgs::identity_for_item(tcx, opaque_ty_def_id), ))); trait_assoc_ty.is_type_alias_impl_trait(false); @@ -360,8 +346,16 @@ fn associated_type_for_impl_trait_in_impl( ) -> LocalDefId { let impl_local_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 decl = tcx + .hir() + .find_by_def_id(impl_fn_def_id) + .expect("expected item") + .fn_decl() + .expect("expected decl"); + let span = match decl.output { + hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id), + hir::FnRetTy::Return(ty) => ty.span, + }; let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, DefPathData::ImplTraitAssocTy); let local_def_id = impl_assoc_ty.def_id(); diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 426c98012..383cc996b 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -42,7 +42,7 @@ pub(crate) fn destructure_const<'tcx>( (field_consts, None) } ty::Adt(def, _) if def.variants().is_empty() => bug!("unreachable"), - ty::Adt(def, substs) => { + ty::Adt(def, args) => { let (variant_idx, branches) = if def.is_enum() { let (head, rest) = branches.split_first().unwrap(); (VariantIdx::from_u32(head.unwrap_leaf().try_to_u32().unwrap()), rest) @@ -53,7 +53,7 @@ pub(crate) fn destructure_const<'tcx>( let mut field_consts = Vec::with_capacity(fields.len()); for (field, field_valtree) in iter::zip(fields, branches) { - let field_ty = field.ty(tcx, substs); + let field_ty = field.ty(tcx, args); let field_const = ty::Const::new_value(tcx, *field_valtree, field_ty); field_consts.push(field_const); } @@ -133,8 +133,8 @@ fn recurse_build<'tcx>( let val = ty::ValTree::zst(); ty::Const::new_value(tcx, val, node.ty) } - &ExprKind::NamedConst { def_id, substs, user_ty: _ } => { - let uneval = ty::UnevaluatedConst::new(def_id, substs); + &ExprKind::NamedConst { def_id, args, user_ty: _ } => { + let uneval = ty::UnevaluatedConst::new(def_id, args); ty::Const::new_unevaluated(tcx, uneval, node.ty) } ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param, node.ty), @@ -174,7 +174,7 @@ fn recurse_build<'tcx>( } // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a // "coercion cast" i.e. using a coercion or is a no-op. - // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested) + // This is important so that `N as usize as usize` doesn't unify with `N as usize`. (untested) &ExprKind::Use { source } => { let arg = recurse_build(tcx, body, source, root_span)?; ty::Const::new_expr(tcx, Expr::Cast(CastKind::Use, arg, node.ty), node.ty) @@ -306,8 +306,9 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> { } match expr.kind { - thir::ExprKind::NamedConst { substs, .. } - | thir::ExprKind::ConstBlock { substs, .. } => substs.has_non_region_param(), + thir::ExprKind::NamedConst { args, .. } | thir::ExprKind::ConstBlock { args, .. } => { + args.has_non_region_param() + } thir::ExprKind::ConstParam { .. } => true, thir::ExprKind::Repeat { value, count } => { self.visit_expr(&self.thir()[value]); diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 10dec9a7a..436f10a4f 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -1,3 +1,4 @@ +use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; @@ -7,13 +8,20 @@ use rustc_span::Span; use std::iter; pub fn provide(providers: &mut Providers) { - *providers = Providers { assumed_wf_types, ..*providers }; + *providers = Providers { + assumed_wf_types, + assumed_wf_types_for_rpitit: |tcx, def_id| { + assert!(tcx.is_impl_trait_in_trait(def_id.to_def_id())); + tcx.assumed_wf_types(def_id) + }, + ..*providers + }; } fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { match tcx.def_kind(def_id) { DefKind::Fn => { - let sig = tcx.fn_sig(def_id).subst_identity(); + let sig = tcx.fn_sig(def_id).instantiate_identity(); let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); tcx.arena.alloc_from_iter(itertools::zip_eq( liberated_sig.inputs_and_output, @@ -21,7 +29,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' )) } DefKind::AssocFn => { - let sig = tcx.fn_sig(def_id).subst_identity(); + let sig = tcx.fn_sig(def_id).instantiate_identity(); let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); let mut assumed_wf_types: Vec<_> = tcx.assumed_wf_types(tcx.local_parent(def_id)).into(); @@ -35,23 +43,90 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' // Trait arguments and the self type for trait impls or only the self type for // inherent impls. let tys = match tcx.impl_trait_ref(def_id) { - Some(trait_ref) => trait_ref.skip_binder().substs.types().collect(), - None => vec![tcx.type_of(def_id).subst_identity()], + Some(trait_ref) => trait_ref.skip_binder().args.types().collect(), + None => vec![tcx.type_of(def_id).instantiate_identity()], }; let mut impl_spans = impl_spans(tcx, def_id); tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap()))) } + DefKind::AssocTy if let Some(data) = tcx.opt_rpitit_info(def_id.to_def_id()) => match data { + ty::ImplTraitInTraitData::Trait { fn_def_id, .. } => { + // We need to remap all of the late-bound lifetimes in theassumed wf types + // of the fn (which are represented as ReFree) to the early-bound lifetimes + // of the RPITIT (which are represented by ReEarlyBound owned by the opaque). + // Luckily, this is very easy to do because we already have that mapping + // stored in the HIR of this RPITIT. + // + // Side-note: We don't really need to do this remapping for early-bound + // lifetimes because they're already "linked" by the bidirectional outlives + // predicates we insert in the `explicit_predicates_of` query for RPITITs. + let mut mapping = FxHashMap::default(); + let generics = tcx.generics_of(def_id); + + // For each captured opaque lifetime, if it's late-bound (`ReFree` in this case, + // since it has been liberated), map it back to the early-bound lifetime of + // the GAT. Since RPITITs also have all of the fn's generics, we slice only + // the end of the list corresponding to the opaque's generics. + for param in &generics.params[tcx.generics_of(fn_def_id).params.len()..] { + let orig_lt = tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()); + if matches!(*orig_lt, ty::ReFree(..)) { + mapping.insert( + orig_lt, + ty::Region::new_early_bound( + tcx, + ty::EarlyBoundRegion { + def_id: param.def_id, + index: param.index, + name: param.name, + }, + ), + ); + } + } + // FIXME: This could use a real folder, I guess. + let remapped_wf_tys = tcx.fold_regions( + tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(), + |region, _| { + // If `region` is a `ReFree` that is captured by the + // opaque, remap it to its corresponding the early- + // bound region. + if let Some(remapped_region) = mapping.get(®ion) { + *remapped_region + } else { + region + } + }, + ); + tcx.arena.alloc_from_iter(remapped_wf_tys) + } + // Assumed wf types for RPITITs in an impl just inherit (and instantiate) + // the assumed wf types of the trait's RPITIT GAT. + ty::ImplTraitInTraitData::Impl { .. } => { + let impl_def_id = tcx.local_parent(def_id); + let rpitit_def_id = tcx.associated_item(def_id).trait_item_def_id.unwrap(); + let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto( + tcx, + impl_def_id.to_def_id(), + tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args, + ); + tcx.arena.alloc_from_iter( + ty::EarlyBinder::bind(tcx.assumed_wf_types_for_rpitit(rpitit_def_id)) + .iter_instantiated_copied(tcx, args) + .chain(tcx.assumed_wf_types(impl_def_id).into_iter().copied()), + ) + } + }, DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) { - DefKind::TyAlias => ty::List::empty(), + DefKind::TyAlias { .. } => ty::List::empty(), DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), // Nested opaque types only occur in associated types: // ` type Opaque = impl Trait<&'static T, AssocTy = impl Nested>; ` // assumed_wf_types should include those of `Opaque`, `Opaque` itself // and `&'static T`. DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"), - def_kind @ _ => { + def_kind => { bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}") } }, @@ -61,7 +136,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias + | DefKind::TyAlias { .. } | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::TyParam @@ -75,7 +150,6 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' | DefKind::ForeignMod | DefKind::AnonConst | DefKind::InlineConst - | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 1d93a79e5..e1a15b5cf 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -1,69 +1,64 @@ use rustc_errors::ErrorGuaranteed; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; -use rustc_middle::traits::CodegenObligationError; -use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError}; +use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt}; use rustc_span::sym; use rustc_trait_selection::traits; -use traits::{translate_substs, Reveal}; +use traits::{translate_args, Reveal}; use crate::errors::UnexpectedFnPtrAssociatedItem; fn resolve_instance<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>, + key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>, ) -> Result>, ErrorGuaranteed> { - let (param_env, (def, substs)) = key.into_parts(); + let (param_env, (def_id, args)) = key.into_parts(); - let result = if let Some(trait_def_id) = tcx.trait_of_item(def) { + let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) { debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env); resolve_associated_item( tcx, - def, + def_id, param_env, trait_def_id, - tcx.normalize_erasing_regions(param_env, substs), + tcx.normalize_erasing_regions(param_env, args), ) } else { - let ty = tcx.type_of(def); - let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty); + let def = if matches!(tcx.def_kind(def_id), DefKind::Fn) && tcx.is_intrinsic(def_id) { + debug!(" => intrinsic"); + ty::InstanceDef::Intrinsic(def_id) + } else if Some(def_id) == tcx.lang_items().drop_in_place_fn() { + let ty = args.type_at(0); - let def = match *item_type.kind() { - ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => { - debug!(" => intrinsic"); - ty::InstanceDef::Intrinsic(def) - } - ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => { - let ty = substs.type_at(0); - - if ty.needs_drop(tcx, param_env) { - debug!(" => nontrivial drop glue"); - match *ty.kind() { - ty::Closure(..) - | ty::Generator(..) - | ty::Tuple(..) - | ty::Adt(..) - | ty::Dynamic(..) - | ty::Array(..) - | ty::Slice(..) => {} - // Drop shims can only be built from ADTs. - _ => return Ok(None), - } - - ty::InstanceDef::DropGlue(def_id, Some(ty)) - } else { - debug!(" => trivial drop glue"); - ty::InstanceDef::DropGlue(def_id, None) + if ty.needs_drop(tcx, param_env) { + debug!(" => nontrivial drop glue"); + match *ty.kind() { + ty::Closure(..) + | ty::Generator(..) + | ty::Tuple(..) + | ty::Adt(..) + | ty::Dynamic(..) + | ty::Array(..) + | ty::Slice(..) => {} + // Drop shims can only be built from ADTs. + _ => return Ok(None), } + + ty::InstanceDef::DropGlue(def_id, Some(ty)) + } else { + debug!(" => trivial drop glue"); + ty::InstanceDef::DropGlue(def_id, None) } - _ => { - debug!(" => free item"); - ty::InstanceDef::Item(def) - } + } else { + debug!(" => free item"); + ty::InstanceDef::Item(def_id) }; - Ok(Some(Instance { def, substs })) + + Ok(Some(Instance { def, args })) }; debug!("inner_resolve_instance: result={:?}", result); result @@ -74,11 +69,11 @@ fn resolve_associated_item<'tcx>( trait_item_id: DefId, param_env: ty::ParamEnv<'tcx>, trait_id: DefId, - rcvr_substs: SubstsRef<'tcx>, + rcvr_args: GenericArgsRef<'tcx>, ) -> Result>, ErrorGuaranteed> { - debug!(?trait_item_id, ?param_env, ?trait_id, ?rcvr_substs, "resolve_associated_item"); + debug!(?trait_item_id, ?param_env, ?trait_id, ?rcvr_args, "resolve_associated_item"); - let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); + let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_args); let vtbl = match tcx.codegen_select_candidate((param_env, trait_ref)) { Ok(vtbl) => vtbl, @@ -102,9 +97,9 @@ fn resolve_associated_item<'tcx>( traits::ImplSource::UserDefined(impl_data) => { debug!( "resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}", - param_env, trait_item_id, rcvr_substs, impl_data + param_env, trait_item_id, rcvr_args, impl_data ); - assert!(!rcvr_substs.has_infer()); + assert!(!rcvr_args.has_infer()); assert!(!trait_ref.has_infer()); let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap(); @@ -117,15 +112,15 @@ fn resolve_associated_item<'tcx>( }); let infcx = tcx.infer_ctxt().build(); let param_env = param_env.with_reveal_all_normalized(tcx); - let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs); - let substs = translate_substs( + let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args); + let args = translate_args( &infcx, param_env, impl_data.impl_def_id, - substs, + args, leaf_def.defining_node, ); - let substs = infcx.tcx.erase_regions(substs); + let args = infcx.tcx.erase_regions(args); // Since this is a trait item, we need to see if the item is either a trait default item // or a specialization because we can't resolve those unless we can `Reveal::All`. @@ -159,7 +154,7 @@ fn resolve_associated_item<'tcx>( return Err(guard); } - let substs = tcx.erase_regions(substs); + let args = tcx.erase_regions(args); // Check if we just resolved an associated `const` declaration from // a `trait` to an associated `const` definition in an `impl`, where @@ -175,17 +170,17 @@ fn resolve_associated_item<'tcx>( ))?; } - Some(ty::Instance::new(leaf_def.item.def_id, substs)) + Some(ty::Instance::new(leaf_def.item.def_id, args)) } - traits::ImplSource::Object(ref data) => { - traits::get_vtable_index_of_object_method(tcx, data, trait_item_id).map(|index| { - Instance { + traits::ImplSource::Builtin(BuiltinImplSource::Object { vtable_base }, _) => { + traits::get_vtable_index_of_object_method(tcx, *vtable_base, trait_item_id).map( + |index| Instance { def: ty::InstanceDef::Virtual(trait_item_id, index), - substs: rcvr_substs, - } - }) + args: rcvr_args, + }, + ) } - traits::ImplSource::Builtin(..) => { + traits::ImplSource::Builtin(BuiltinImplSource::Misc, _) => { let lang_items = tcx.lang_items(); if Some(trait_ref.def_id) == lang_items.clone_trait() { // FIXME(eddyb) use lang items for methods instead of names. @@ -205,14 +200,14 @@ fn resolve_associated_item<'tcx>( Some(Instance { def: ty::InstanceDef::CloneShim(trait_item_id, self_ty), - substs: rcvr_substs, + args: rcvr_args, }) } else { assert_eq!(name, sym::clone_from); // Use the default `fn clone_from` from `trait Clone`. - let substs = tcx.erase_regions(rcvr_substs); - Some(ty::Instance::new(trait_item_id, substs)) + let args = tcx.erase_regions(rcvr_args); + Some(ty::Instance::new(trait_item_id, args)) } } else if Some(trait_ref.def_id) == lang_items.fn_ptr_trait() { if lang_items.fn_ptr_addr() == Some(trait_item_id) { @@ -222,7 +217,7 @@ fn resolve_associated_item<'tcx>( } Some(Instance { def: ty::InstanceDef::FnPtrAddrShim(trait_item_id, self_ty), - substs: rcvr_substs, + args: rcvr_args, }) } else { tcx.sess.emit_fatal(UnexpectedFnPtrAssociatedItem { @@ -230,20 +225,20 @@ fn resolve_associated_item<'tcx>( }) } } else if Some(trait_ref.def_id) == lang_items.future_trait() { - let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else { + let ty::Generator(generator_def_id, args, _) = *rcvr_args.type_at(0).kind() else { bug!() }; if Some(trait_item_id) == tcx.lang_items().future_poll_fn() { // `Future::poll` is generated by the compiler. - Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs: substs }) + Some(Instance { def: ty::InstanceDef::Item(generator_def_id), args: args }) } else { // All other methods are default methods of the `Future` trait. // (this assumes that `ImplSource::Builtin` is only used for methods on `Future`) debug_assert!(tcx.defaultness(trait_item_id).has_value()); - Some(Instance::new(trait_item_id, rcvr_substs)) + Some(Instance::new(trait_item_id, rcvr_args)) } } else if Some(trait_ref.def_id) == lang_items.gen_trait() { - let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else { + let ty::Generator(generator_def_id, args, _) = *rcvr_args.type_at(0).kind() else { bug!() }; if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume { @@ -257,7 +252,7 @@ fn resolve_associated_item<'tcx>( tcx.item_name(trait_item_id) ) } - Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs }) + Some(Instance { def: ty::InstanceDef::Item(generator_def_id), args }) } else if tcx.fn_trait_kind_from_def_id(trait_ref.def_id).is_some() { // FIXME: This doesn't check for malformed libcore that defines, e.g., // `trait Fn { fn call_once(&self) { .. } }`. This is mostly for extension @@ -275,14 +270,14 @@ fn resolve_associated_item<'tcx>( tcx.item_name(trait_item_id) ) } - match *rcvr_substs.type_at(0).kind() { - ty::Closure(closure_def_id, substs) => { + match *rcvr_args.type_at(0).kind() { + ty::Closure(closure_def_id, args) => { let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap(); - Instance::resolve_closure(tcx, closure_def_id, substs, trait_closure_kind) + Instance::resolve_closure(tcx, closure_def_id, args, trait_closure_kind) } ty::FnDef(..) | ty::FnPtr(..) => Some(Instance { - def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_substs.type_at(0)), - substs: rcvr_substs, + def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_args.type_at(0)), + args: rcvr_args, }), _ => bug!( "no built-in definition for `{trait_ref}::{}` for non-fn type", @@ -293,7 +288,9 @@ fn resolve_associated_item<'tcx>( None } } - traits::ImplSource::Param(..) | traits::ImplSource::TraitUpcasting(_) => None, + traits::ImplSource::Param(..) + | traits::ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) + | traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => None, }) } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index b67cd96a7..6b4273c03 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -8,7 +8,7 @@ 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, TypeVisitableExt, + self, AdtDef, EarlyBinder, GenericArgsRef, ReprOptions, Ty, TyCtxt, TypeVisitableExt, }; use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::symbol::Symbol; @@ -96,6 +96,13 @@ fn layout_of_uncached<'tcx>( cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, ty: Ty<'tcx>, ) -> Result, &'tcx LayoutError<'tcx>> { + // Types that reference `ty::Error` pessimistically don't have a meaningful layout. + // The only side-effect of this is possibly worse diagnostics in case the layout + // was actually computable (like if the `ty::Error` showed up only in a `PhantomData`). + if let Err(guar) = ty.error_reported() { + return Err(error(cx, LayoutError::ReferencesError(guar))); + } + let tcx = cx.tcx; let param_env = cx.param_env; let dl = cx.data_layout(); @@ -258,6 +265,8 @@ fn layout_of_uncached<'tcx>( largest_niche, align: element.align, size, + max_repr_align: None, + unadjusted_abi_align: element.align.abi, }) } ty::Slice(element) => { @@ -269,6 +278,8 @@ fn layout_of_uncached<'tcx>( largest_niche: None, align: element.align, size: Size::ZERO, + max_repr_align: None, + unadjusted_abi_align: element.align.abi, }) } ty::Str => tcx.mk_layout(LayoutS { @@ -278,6 +289,8 @@ fn layout_of_uncached<'tcx>( largest_niche: None, align: dl.i8_align, size: Size::ZERO, + max_repr_align: None, + unadjusted_abi_align: dl.i8_align.abi, }), // Odd unit types. @@ -299,12 +312,14 @@ fn layout_of_uncached<'tcx>( tcx.mk_layout(unit) } - ty::Generator(def_id, substs, _) => generator_layout(cx, ty, def_id, substs)?, + ty::Generator(def_id, args, _) => generator_layout(cx, ty, def_id, args)?, - ty::Closure(_, ref substs) => { - let tys = substs.as_closure().upvar_tys(); + ty::Closure(_, ref args) => { + let tys = args.as_closure().upvar_tys(); univariant( - &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).try_collect::>()?, + &tys.iter() + .map(|ty| Ok(cx.layout_of(ty)?.layout)) + .try_collect::>()?, &ReprOptions::default(), StructKind::AlwaysSized, )? @@ -322,7 +337,7 @@ fn layout_of_uncached<'tcx>( } // SIMD vector types. - ty::Adt(def, substs) if def.repr().simd() => { + ty::Adt(def, args) if def.repr().simd() => { if !def.is_struct() { // Should have yielded E0517 by now. tcx.sess.delay_span_bug( @@ -349,12 +364,12 @@ fn layout_of_uncached<'tcx>( } // Type of the first ADT field: - let f0_ty = fields[FieldIdx::from_u32(0)].ty(tcx, substs); + let f0_ty = fields[FieldIdx::from_u32(0)].ty(tcx, args); // Heterogeneous SIMD vectors are not supported: // (should be caught by typeck) for fi in fields { - if fi.ty(tcx, substs) != f0_ty { + if fi.ty(tcx, args) != f0_ty { tcx.sess.delay_span_bug( DUMMY_SP, "#[repr(simd)] was applied to an ADT with heterogeneous field type", @@ -431,11 +446,13 @@ fn layout_of_uncached<'tcx>( largest_niche: e_ly.largest_niche, size, align, + max_repr_align: None, + unadjusted_abi_align: align.abi, }) } // ADTs. - ty::Adt(def, substs) => { + ty::Adt(def, args) => { // Cache the field layouts. let variants = def .variants() @@ -443,7 +460,7 @@ fn layout_of_uncached<'tcx>( .map(|v| { v.fields .iter() - .map(|field| Ok(cx.layout_of(field.ty(tcx, substs))?.layout)) + .map(|field| Ok(cx.layout_of(field.ty(tcx, args))?.layout)) .try_collect::>() }) .try_collect::>()?; @@ -482,7 +499,7 @@ fn layout_of_uncached<'tcx>( let maybe_unsized = def.is_struct() && def.non_enum_variant().tail_opt().is_some_and(|last_field| { let param_env = tcx.param_env(def.did()); - !tcx.type_of(last_field.did).subst_identity().is_sized(tcx, param_env) + !tcx.type_of(last_field.did).instantiate_identity().is_sized(tcx, param_env) }); let Some(layout) = cx.layout_of_struct_or_enum( @@ -502,7 +519,7 @@ fn layout_of_uncached<'tcx>( // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around. if cfg!(debug_assertions) && maybe_unsized - && def.non_enum_variant().tail().ty(tcx, substs).is_sized(tcx, cx.param_env) + && def.non_enum_variant().tail().ty(tcx, args).is_sized(tcx, cx.param_env) { let mut variants = variants; let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap(); @@ -525,8 +542,13 @@ fn layout_of_uncached<'tcx>( let FieldsShape::Arbitrary { offsets: sized_offsets, .. } = &layout.fields else { bug!("unexpected FieldsShape for sized layout of {ty:?}: {:?}", layout.fields); }; - let FieldsShape::Arbitrary { offsets: unsized_offsets, .. } = &unsized_layout.fields else { - bug!("unexpected FieldsShape for unsized layout of {ty:?}: {:?}", unsized_layout.fields); + let FieldsShape::Arbitrary { offsets: unsized_offsets, .. } = + &unsized_layout.fields + else { + bug!( + "unexpected FieldsShape for unsized layout of {ty:?}: {:?}", + unsized_layout.fields + ); }; let (sized_tail, sized_fields) = sized_offsets.raw.split_last().unwrap(); @@ -551,11 +573,15 @@ fn layout_of_uncached<'tcx>( return Err(error(cx, LayoutError::Unknown(ty))); } - ty::Bound(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Infer(_) => { + ty::Bound(..) + | ty::GeneratorWitness(..) + | ty::GeneratorWitnessMIR(..) + | ty::Infer(_) + | ty::Error(_) => { bug!("Layout::compute: unexpected type `{}`", ty) } - ty::Placeholder(..) | ty::Param(_) | ty::Error(_) => { + ty::Placeholder(..) | ty::Param(_) => { return Err(error(cx, LayoutError::Unknown(ty))); } }) @@ -691,11 +717,11 @@ fn generator_layout<'tcx>( cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, ty: Ty<'tcx>, def_id: hir::def_id::DefId, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, ) -> Result, &'tcx LayoutError<'tcx>> { use SavedLocalEligibility::*; let tcx = cx.tcx; - let subst_field = |ty: Ty<'tcx>| EarlyBinder::bind(ty).subst(tcx, substs); + let subst_field = |ty: Ty<'tcx>| EarlyBinder::bind(ty).instantiate(tcx, args); let Some(info) = tcx.generator_layout(def_id) else { return Err(error(cx, LayoutError::Unknown(ty))); @@ -705,7 +731,7 @@ fn generator_layout<'tcx>( // Build a prefix layout, including "promoting" all ineligible // locals as part of the prefix. We compute the layout of all of // these fields at once to get optimal packing. - let tag_index = substs.as_generator().prefix_tys().count(); + let tag_index = args.as_generator().prefix_tys().len(); // `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; @@ -721,9 +747,10 @@ fn generator_layout<'tcx>( .map(|local| subst_field(info.field_tys[local].ty)) .map(|ty| Ty::new_maybe_uninit(tcx, ty)) .map(|ty| Ok(cx.layout_of(ty)?.layout)); - let prefix_layouts = substs + let prefix_layouts = args .as_generator() .prefix_tys() + .iter() .map(|ty| Ok(cx.layout_of(ty)?.layout)) .chain(iter::once(Ok(tag_layout))) .chain(promoted_layouts) @@ -879,6 +906,8 @@ fn generator_layout<'tcx>( largest_niche: prefix.largest_niche, size, align, + max_repr_align: None, + unadjusted_abi_align: align.abi, }); debug!("generator layout ({:?}): {:#?}", ty, layout); Ok(layout) @@ -929,11 +958,11 @@ fn record_layout_for_printing_outlined<'tcx>( record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos); } - ty::Generator(def_id, substs, _) => { + ty::Generator(def_id, args, _) => { 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); + variant_info_for_generator(cx, layout, def_id, args); record(DataTypeKind::Generator, false, opt_discr_size, variant_infos); } @@ -1023,7 +1052,7 @@ fn variant_info_for_generator<'tcx>( cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: TyAndLayout<'tcx>, def_id: DefId, - substs: ty::SubstsRef<'tcx>, + args: ty::GenericArgsRef<'tcx>, ) -> (Vec, Option) { let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else { return (vec![], None); @@ -1033,9 +1062,10 @@ fn variant_info_for_generator<'tcx>( let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id); let mut upvars_size = Size::ZERO; - let upvar_fields: Vec<_> = substs + let upvar_fields: Vec<_> = args .as_generator() .upvar_tys() + .iter() .zip(upvar_names) .enumerate() .map(|(field_idx, (_, name))| { @@ -1108,7 +1138,7 @@ fn variant_info_for_generator<'tcx>( } VariantInfo { - name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(variant_idx))), + name: Some(Symbol::intern(&ty::GeneratorArgs::variant_name(variant_idx))), kind: SizeKind::Exact, size: variant_size.bytes(), align: variant_layout.align.abi.bytes(), diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs index c4a4cda68..863333438 100644 --- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs +++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs @@ -52,7 +52,7 @@ pub(super) fn sanity_check_layout<'tcx>( let mut fields = non_zst_fields(cx, layout); let Some(first) = fields.next() else { // No fields here, so this could be a primitive or enum -- either way it's not a newtype around a thing - return *layout + return *layout; }; if fields.next().is_none() { let (offset, first) = first; @@ -77,7 +77,7 @@ pub(super) fn sanity_check_layout<'tcx>( Abi::Uninhabited | Abi::Aggregate { .. }, "ABI unexpectedly missing alignment and/or size in {layout:#?}" ); - return + return; }; assert_eq!( layout.layout.align().abi, diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 55b8857ed..147b600f7 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -8,6 +8,7 @@ #![feature(assert_matches)] #![feature(iterator_try_collect)] #![feature(let_chains)] +#![feature(if_let_guard)] #![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 9d593dc5e..1fc5d9359 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -3,8 +3,8 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_middle::query::Providers; -use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop}; +use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt}; use rustc_session::Limit; use rustc_span::{sym, DUMMY_SP}; @@ -19,13 +19,32 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> // needs drop. let adt_has_dtor = |adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant); - let res = - drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false).next().is_some(); + let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false) + .filter(filter_array_elements(tcx, query.param_env)) + .next() + .is_some(); debug!("needs_drop_raw({:?}) = {:?}", query, res); res } +/// HACK: in order to not mistakenly assume that `[PhantomData; N]` requires drop glue +/// we check the element type for drop glue. The correct fix would be looking at the +/// entirety of the code around `needs_drop_components` and this file and come up with +/// logic that is easier to follow while not repeating any checks that may thus diverge. +fn filter_array_elements<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, +) -> impl Fn(&Result, AlwaysRequiresDrop>) -> bool { + move |ty| match ty { + Ok(ty) => match *ty.kind() { + ty::Array(elem, _) => tcx.needs_drop_raw(param_env.and(elem)), + _ => true, + }, + Err(AlwaysRequiresDrop) => true, + } +} + fn has_significant_drop_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, @@ -37,6 +56,7 @@ fn has_significant_drop_raw<'tcx>( adt_consider_insignificant_dtor(tcx), true, ) + .filter(filter_array_elements(tcx, query.param_env)) .next() .is_some(); debug!("has_significant_drop_raw({:?}) = {:?}", query, res); @@ -80,7 +100,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> { impl<'tcx, F, I> Iterator for NeedsDropTypes<'tcx, F> where - F: Fn(ty::AdtDef<'tcx>, SubstsRef<'tcx>) -> NeedsDropResult, + F: Fn(ty::AdtDef<'tcx>, GenericArgsRef<'tcx>) -> NeedsDropResult, I: Iterator>, { type Item = NeedsDropResult>; @@ -96,7 +116,7 @@ where return Some(Err(AlwaysRequiresDrop)); } - let components = match needs_drop_components(ty, &tcx.data_layout) { + let components = match needs_drop_components(tcx, ty) { Err(e) => return Some(Err(e)), Ok(components) => components, }; @@ -119,21 +139,25 @@ where _ if component.is_copy_modulo_regions(tcx, self.param_env) => (), - ty::Closure(_, substs) => { - queue_type(self, substs.as_closure().tupled_upvars_ty()); + ty::Closure(_, args) => { + for upvar in args.as_closure().upvar_tys() { + queue_type(self, upvar); + } } - ty::Generator(def_id, substs, _) => { - let substs = substs.as_generator(); - queue_type(self, substs.tupled_upvars_ty()); + ty::Generator(def_id, args, _) => { + let args = args.as_generator(); + for upvar in args.upvar_tys() { + queue_type(self, upvar); + } - let witness = substs.witness(); + let witness = args.witness(); let interior_tys = match witness.kind() { &ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys), _ => { tcx.sess.delay_span_bug( tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP), - format!("unexpected generator witness type {:?}", witness), + format!("unexpected generator witness type {witness:?}"), ); return Some(Err(AlwaysRequiresDrop)); } @@ -147,8 +171,8 @@ where // Check for a `Drop` impl and whether this is a union or // `ManuallyDrop`. If it's a struct or enum without a `Drop` // impl then check whether the field types need `Drop`. - ty::Adt(adt_def, substs) => { - let tys = match (self.adt_components)(adt_def, substs) { + ty::Adt(adt_def, args) => { + let tys = match (self.adt_components)(adt_def, args) { Err(e) => return Some(Err(e)), Ok(tys) => tys, }; @@ -160,7 +184,7 @@ where queue_type(self, required); } } - ty::Array(..) | ty::Alias(..) | ty::Param(_) => { + ty::Alias(..) | ty::Array(..) | ty::Placeholder(_) | ty::Param(_) => { if ty == component { // Return the type to the caller: they may be able // to normalize further than we can. @@ -172,7 +196,31 @@ where queue_type(self, component); } } - _ => return Some(Err(AlwaysRequiresDrop)), + + ty::Foreign(_) | ty::Dynamic(..) => { + return Some(Err(AlwaysRequiresDrop)); + } + + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Str + | ty::Slice(_) + | ty::Ref(..) + | ty::RawPtr(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Tuple(_) + | ty::Bound(..) + | ty::GeneratorWitness(..) + | ty::GeneratorWitnessMIR(..) + | ty::Never + | ty::Infer(_) + | ty::Error(_) => { + bug!("unexpected type returned by `needs_drop_components`: {component}") + } } } } @@ -210,7 +258,7 @@ fn drop_tys_helper<'tcx>( match subty.kind() { ty::Adt(adt_id, subst) => { for subty in tcx.adt_drop_tys(adt_id.did())? { - vec.push(EarlyBinder::bind(subty).subst(tcx, subst)); + vec.push(EarlyBinder::bind(subty).instantiate(tcx, subst)); } } _ => vec.push(subty), @@ -219,7 +267,7 @@ fn drop_tys_helper<'tcx>( }) } - let adt_components = move |adt_def: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>| { + let adt_components = move |adt_def: ty::AdtDef<'tcx>, args: GenericArgsRef<'tcx>| { if adt_def.is_manually_drop() { debug!("drop_tys_helper: `{:?}` is manually drop", adt_def); Ok(Vec::new()) @@ -235,7 +283,7 @@ fn drop_tys_helper<'tcx>( // Since the destructor is insignificant, we just want to make sure all of // the passed in type parameters are also insignificant. // Eg: Vec dtor is insignificant when T=i32 but significant when T=Mutex. - Ok(substs.types().collect()) + Ok(args.types().collect()) } } } else if adt_def.is_union() { @@ -243,8 +291,8 @@ fn drop_tys_helper<'tcx>( Ok(Vec::new()) } else { let field_tys = adt_def.all_fields().map(|field| { - let r = tcx.type_of(field.did).subst(tcx, substs); - debug!("drop_tys_helper: Subst into {:?} with {:?} getting {:?}", field, substs, r); + let r = tcx.type_of(field.did).instantiate(tcx, args); + debug!("drop_tys_helper: Subst into {:?} with {:?} getting {:?}", field, args, r); r }); if only_significant { @@ -295,10 +343,10 @@ fn adt_drop_tys<'tcx>( // significant. 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)` + // `tcx.type_of(def_id)` identical to `tcx.make_adt(def, identity_args)` drop_tys_helper( tcx, - tcx.type_of(def_id).subst_identity(), + tcx.type_of(def_id).instantiate_identity(), tcx.param_env(def_id), adt_has_dtor, false, @@ -307,7 +355,7 @@ fn adt_drop_tys<'tcx>( .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 +// a `tcx.make_ty(def, identity_args)` and as such it is legal to substitute the generic parameters // of the ADT into the outputted `ty`s. fn adt_significant_drop_tys( tcx: TyCtxt<'_>, @@ -315,7 +363,7 @@ fn adt_significant_drop_tys( ) -> Result<&ty::List>, AlwaysRequiresDrop> { drop_tys_helper( tcx, - tcx.type_of(def_id).subst_identity(), // identical to `tcx.make_adt(def, identity_substs)` + tcx.type_of(def_id).instantiate_identity(), // identical to `tcx.make_adt(def, identity_args)` tcx.param_env(def_id), adt_consider_insignificant_dtor(tcx), true, diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 570c3b245..38768f0a0 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::util::{CheckRegions, NotUniqueParam}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_span::Span; -use rustc_trait_selection::traits::check_substs_compatible; +use rustc_trait_selection::traits::check_args_compatible; use std::ops::ControlFlow; use crate::errors::{DuplicateArg, NotParam}; @@ -45,7 +45,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { fn parent_trait_ref(&self) -> Option> { let parent = self.parent()?; if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) { - Some(self.tcx.impl_trait_ref(parent)?.subst_identity()) + Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity()) } else { None } @@ -53,7 +53,9 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { fn parent(&self) -> Option { match self.tcx.def_kind(self.item) { - DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias => None, + DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias { .. } => { + None + } DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => { Some(self.tcx.local_parent(self.item)) } @@ -116,7 +118,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { #[instrument(level = "trace", skip(self))] fn visit_nested_item(&mut self, id: rustc_hir::ItemId) { let id = id.owner_id.def_id; - if let DefKind::TyAlias = self.collector.tcx.def_kind(id) { + if let DefKind::TyAlias { .. } = self.collector.tcx.def_kind(id) { let items = self.collector.tcx.opaque_types_defined_by(id); self.collector.opaques.extend(items); } @@ -159,19 +161,19 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { self.opaques.push(alias_ty.def_id.expect_local()); - match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) { + match self.tcx.uses_unique_generic_params(alias_ty.args, CheckRegions::Bound) { Ok(()) => { // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not // supported at all, so this is sound to do, but once we want to support them, you'll // start seeing the error below. // Collect opaque types nested within the associated type bounds of this opaque type. - // We use identity substs here, because we already know that the opaque type uses + // We use identity args here, because we already know that the opaque type uses // only generic parameters, and thus substituting would not give us more information. for (pred, span) in self .tcx .explicit_item_bounds(alias_ty.def_id) - .subst_identity_iter_copied() + .instantiate_identity_iter_copied() { trace!(?pred); self.visit_spanned(span, pred); @@ -196,7 +198,7 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => { self.tcx .type_of(alias_ty.def_id) - .subst(self.tcx, alias_ty.substs) + .instantiate(self.tcx, alias_ty.args) .visit_with(self)?; } ty::Alias(ty::Projection, alias_ty) => { @@ -222,22 +224,22 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { continue; } - let impl_substs = alias_ty.substs.rebase_onto( + let impl_args = alias_ty.args.rebase_onto( self.tcx, parent_trait_ref.def_id, - ty::InternalSubsts::identity_for_item(self.tcx, parent), + ty::GenericArgs::identity_for_item(self.tcx, parent), ); - if check_substs_compatible(self.tcx, assoc, impl_substs) { + if check_args_compatible(self.tcx, assoc, impl_args) { return self .tcx .type_of(assoc.def_id) - .subst(self.tcx, impl_substs) + .instantiate(self.tcx, impl_args) .visit_with(self); } else { self.tcx.sess.delay_span_bug( self.tcx.def_span(assoc.def_id), - "item had incorrect substs", + "item had incorrect args", ); } } @@ -250,15 +252,15 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { } for variant in def.variants().iter() { for field in variant.fields.iter() { - // Don't use the `ty::Adt` substs, we either - // * found the opaque in the substs + // Don't use the `ty::Adt` args, we either + // * found the opaque in the args // * will find the opaque in the unsubstituted fields // The only other situation that can occur is that after substituting, // some projection resolves to an opaque that we would have otherwise // not found. While we could substitute and walk those, that would mean we // would have to walk all substitutions of an Adt, which can quickly // degenerate into looking at an exponential number of types. - let ty = self.tcx.type_of(field.did).subst_identity(); + let ty = self.tcx.type_of(field.did).instantiate_identity(); self.visit_spanned(self.tcx.def_span(field.did), ty); } } @@ -276,7 +278,7 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ match kind { // Walk over the signature of the function-like to find the opaques. DefKind::AssocFn | DefKind::Fn => { - let ty_sig = tcx.fn_sig(item).subst_identity(); + let ty_sig = tcx.fn_sig(item).instantiate_identity(); let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap(); // Walk over the inputs and outputs manually in order to get good spans for them. collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output()); @@ -291,15 +293,15 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ Some(ty) => ty.span, _ => tcx.def_span(item), }; - collector.visit_spanned(span, tcx.type_of(item).subst_identity()); + collector.visit_spanned(span, tcx.type_of(item).instantiate_identity()); collector.collect_body_and_predicate_taits(); } // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds` - DefKind::TyAlias | DefKind::AssocTy => { - tcx.type_of(item).subst_identity().visit_with(&mut collector); + DefKind::TyAlias { .. } | DefKind::AssocTy => { + tcx.type_of(item).instantiate_identity().visit_with(&mut collector); } DefKind::OpaqueTy => { - for (pred, span) in tcx.explicit_item_bounds(item).subst_identity_iter_copied() { + for (pred, span) in tcx.explicit_item_bounds(item).instantiate_identity_iter_copied() { collector.visit_spanned(span, pred); } } @@ -318,7 +320,6 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ | DefKind::ExternCrate | DefKind::Use | DefKind::ForeignMod - | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index 0b5e27c2c..f34e0df2c 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).subst_identity()), + DefKind::Field => representability_ty(tcx, tcx.type_of(def_id).instantiate_identity()), def_kind => bug!("unexpected {def_kind:?}"), } } @@ -68,14 +68,14 @@ representability_adt_ty(Bar<..>) is in the cycle and representability(Bar) is *not* in the cycle. */ fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability { - let ty::Adt(adt, substs) = ty.kind() else { bug!("expected adt") }; + let ty::Adt(adt, args) = ty.kind() else { bug!("expected adt") }; if let Some(def_id) = adt.did().as_local() { rtry!(tcx.representability(def_id)); } // At this point, we know that the item of the ADT type is representable; // but the type parameters may cause a cycle with an upstream type let params_in_repr = tcx.params_in_repr(adt.did()); - for (i, subst) in substs.iter().enumerate() { + for (i, subst) in args.iter().enumerate() { if let ty::GenericArgKind::Type(ty) = subst.unpack() { if params_in_repr.contains(i as u32) { rtry!(representability_ty(tcx, ty)); @@ -91,7 +91,11 @@ fn params_in_repr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> 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).subst_identity(), &mut params_in_repr); + params_in_repr_ty( + tcx, + tcx.type_of(field.did).instantiate_identity(), + &mut params_in_repr, + ); } } params_in_repr @@ -99,9 +103,9 @@ fn params_in_repr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> BitSet { fn params_in_repr_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, params_in_repr: &mut BitSet) { match *ty.kind() { - ty::Adt(adt, substs) => { + ty::Adt(adt, args) => { let inner_params_in_repr = tcx.params_in_repr(adt.did()); - for (i, subst) in substs.iter().enumerate() { + for (i, subst) in args.iter().enumerate() { if let ty::GenericArgKind::Type(ty) = subst.unpack() { if inner_params_in_repr.contains(i as u32) { params_in_repr_ty(tcx, ty, params_in_repr); diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 6e5c50492..ba0258b63 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -37,12 +37,12 @@ fn sized_constraint_for_ty<'tcx>( Some(&ty) => sized_constraint_for_ty(tcx, adtdef, ty), }, - Adt(adt, substs) => { + Adt(adt, args) => { // recursive case let adt_tys = adt.sized_constraint(tcx); debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys); adt_tys - .subst_iter_copied(tcx, substs) + .iter_instantiated(tcx, args) .flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty)) .collect() } @@ -58,11 +58,18 @@ fn sized_constraint_for_ty<'tcx>( // we know that `T` is Sized and do not need to check // it on the impl. - let Some(sized_trait) = tcx.lang_items().sized_trait() else { return vec![ty] }; - let sized_predicate = - ty::TraitRef::new(tcx, sized_trait, [ty]).without_const().to_predicate(tcx); + let Some(sized_trait_def_id) = tcx.lang_items().sized_trait() else { return vec![ty] }; let predicates = tcx.predicates_of(adtdef.did()).predicates; - if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] } + if predicates.iter().any(|(p, _)| { + p.as_trait_clause().is_some_and(|trait_pred| { + trait_pred.def_id() == sized_trait_def_id + && trait_pred.self_ty().skip_binder() == ty + }) + }) { + vec![] + } else { + vec![ty] + } } Placeholder(..) | Bound(..) | Infer(..) => { @@ -92,24 +99,25 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness { /// - a tuple of type parameters or projections, if there are multiple /// such. /// - an Error, if a type is infinitely sized -fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] { +fn adt_sized_constraint<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, +) -> ty::EarlyBinder<&'tcx ty::List>> { if let Some(def_id) = def_id.as_local() { if matches!(tcx.representability(def_id), ty::Representability::Infinite) { - return tcx.mk_type_list(&[Ty::new_misc_error(tcx)]); + return ty::EarlyBinder::bind(tcx.mk_type_list(&[Ty::new_misc_error(tcx)])); } } let def = tcx.adt_def(def_id); - let result = tcx.mk_type_list_from_iter( - def.variants() - .iter() - .filter_map(|v| v.tail_opt()) - .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).subst_identity())), - ); + let result = + tcx.mk_type_list_from_iter(def.variants().iter().filter_map(|v| v.tail_opt()).flat_map( + |f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).instantiate_identity()), + )); debug!("adt_sized_constraint: {:?} => {:?}", def, result); - result + ty::EarlyBinder::bind(result) } /// See `ParamEnv` struct definition for details. @@ -131,9 +139,11 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // sure that this will succeed without errors anyway. if tcx.def_kind(def_id) == DefKind::AssocFn - && tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer + && let assoc_item = tcx.associated_item(def_id) + && assoc_item.container == ty::AssocItemContainer::TraitContainer + && assoc_item.defaultness(tcx).has_value() { - let sig = tcx.fn_sig(def_id).subst_identity(); + let sig = tcx.fn_sig(def_id).instantiate_identity(); // We accounted for the binder of the fn sig, so skip the binder. sig.skip_binder().visit_with(&mut ImplTraitInTraitFinder { tcx, @@ -146,85 +156,9 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { } let local_did = def_id.as_local(); - // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This isn't correct for - // RPITITs in const trait fn. - let hir_id = local_did.and_then(|def_id| tcx.opt_local_def_id_to_hir_id(def_id)); - - // FIXME(consts): This is not exactly in line with the constness query. - let constness = match hir_id { - Some(hir_id) => match tcx.hir().get(hir_id) { - hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) - if tcx.is_const_default_method(def_id) => - { - hir::Constness::Const - } - - hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) - | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) - | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(..), .. - }) - | hir::Node::AnonConst(_) - | hir::Node::ConstBlock(_) - | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) - | hir::Node::ImplItem(hir::ImplItem { - kind: - hir::ImplItemKind::Fn( - hir::FnSig { - header: hir::FnHeader { constness: hir::Constness::Const, .. }, - .. - }, - .., - ), - .. - }) => hir::Constness::Const, - - hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..), - .. - }) => { - 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, .. }), - .. - }) => *constness, - _ => span_bug!( - tcx.def_span(parent_hir_id.owner), - "impl item's parent node is not an impl", - ), - } - } - - hir::Node::Item(hir::Item { - kind: - hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), - .. - }) - | hir::Node::TraitItem(hir::TraitItem { - kind: - hir::TraitItemKind::Fn( - hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, - .., - ), - .. - }) - | hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), - .. - }) => *constness, - - _ => hir::Constness::NotConst, - }, - // FIXME(consts): It's suspicious that a param-env for a foreign item - // will always have NotConst param-env, though we don't typically use - // that param-env for anything meaningful right now, so it's likely - // not an issue. - None => hir::Constness::NotConst, - }; let unnormalized_env = - ty::ParamEnv::new(tcx.mk_clauses(&predicates), traits::Reveal::UserFacing, constness); + ty::ParamEnv::new(tcx.mk_clauses(&predicates), traits::Reveal::UserFacing); let body_id = local_did.unwrap_or(CRATE_DEF_ID); let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); @@ -257,8 +191,10 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { if let ty::Alias(ty::Projection, unshifted_alias_ty) = *ty.kind() - && self.tcx.is_impl_trait_in_trait(unshifted_alias_ty.def_id) - && self.tcx.impl_trait_in_trait_parent_fn(unshifted_alias_ty.def_id) == self.fn_def_id + && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. } + | ty::ImplTraitInTraitData::Impl { fn_def_id, .. }) + = self.tcx.opt_rpitit_info(unshifted_alias_ty.def_id) + && fn_def_id == self.fn_def_id && self.seen.insert(unshifted_alias_ty.def_id) { // We have entered some binders as we've walked into the @@ -282,11 +218,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { // If we're lowering to associated item, install the opaque type which is just // the `type_of` of the trait's associated item. If we're using the old lowering // strategy, then just reinterpret the associated type like an opaque :^) - let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() { - self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs) - } else { - Ty::new_alias(self.tcx,ty::Opaque, shifted_alias_ty) - }; + let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).instantiate(self.tcx, shifted_alias_ty.args); self.predicates.push( ty::Binder::bind_with_vars( @@ -303,7 +235,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { for bound in self .tcx .item_bounds(unshifted_alias_ty.def_id) - .subst_iter(self.tcx, unshifted_alias_ty.substs) + .iter_instantiated(self.tcx, unshifted_alias_ty.args) { bound.visit_with(self); } @@ -317,22 +249,6 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE tcx.param_env(def_id).with_reveal_all_normalized(tcx) } -fn instance_def_size_estimate<'tcx>( - tcx: TyCtxt<'tcx>, - instance_def: ty::InstanceDef<'tcx>, -) -> usize { - use ty::InstanceDef; - - match instance_def { - InstanceDef::Item(..) | InstanceDef::DropGlue(..) => { - let mir = tcx.instance_mir(instance_def); - mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum() - } - // Estimate the size of other compiler-generated shims to be 1. - _ => 1, - } -} - /// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`. /// /// See [`ty::ImplOverlapKind::Issue33140`] for more details. @@ -356,8 +272,8 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet