summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ty_utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ty_utils/src')
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs29
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs128
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs15
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs92
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs145
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs80
-rw-r--r--compiler/rustc_ty_utils/src/layout_sanity_check.rs4
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs1
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs98
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs45
-rw-r--r--compiler/rustc_ty_utils/src/representability.rs16
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs165
12 files changed, 442 insertions, 376 deletions
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<Output>`
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<Yield, Return>`
let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
let state_adt_ref = tcx.adt_def(state_did);
- let state_substs = tcx.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(&region) {
+ *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<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
// assumed_wf_types should include those of `Opaque<T>`, `Opaque<T>` 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<Option<Instance<'tcx>>, 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<Option<Instance<'tcx>>, 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<Layout<'tcx>, &'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::<IndexVec<_, _>>()?,
+ &tys.iter()
+ .map(|ty| Ok(cx.layout_of(ty)?.layout))
+ .try_collect::<IndexVec<_, _>>()?,
&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::<IndexVec<_, _>>()
})
.try_collect::<IndexVec<VariantIdx, _>>()?;
@@ -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<Layout<'tcx>, &'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<VariantInfo>, Option<Size>) {
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<T>; 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<Ty<'tcx>, 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<I>,
+ F: Fn(ty::AdtDef<'tcx>, GenericArgsRef<'tcx>) -> NeedsDropResult<I>,
I: Iterator<Item = Ty<'tcx>>,
{
type Item = NeedsDropResult<Ty<'tcx>>;
@@ -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<T> 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<Ty<'_>>, 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<ty::TraitRef<'tcx>> {
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<LocalDefId> {
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<TyCtxt<'tcx>> 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<TyCtxt<'tcx>> 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<TyCtxt<'tcx>> 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<TyCtxt<'tcx>> 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<u32> {
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<u32> {
fn params_in_repr_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, params_in_repr: &mut BitSet<u32>) {
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<Ty<'tcx>>> {
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<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
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<TyCtxt<'tcx>> 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<TyCtxt<'tcx>> 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<EarlyBinder<Ty<'
}
// impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
- if trait_ref.substs.len() != 1 {
- debug!("issue33140_self_ty - impl has substs!");
+ if trait_ref.args.len() != 1 {
+ debug!("issue33140_self_ty - impl has args!");
return None;
}
@@ -408,14 +324,12 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32
};
// 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.raw.split_last() else
- {
+ let Some((tail_field, prefix_fields)) = def.non_enum_variant().fields.raw.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() {
+ for arg in tcx.type_of(tail_field.did).instantiate_identity().walk() {
if let Some(i) = maybe_unsizing_param_idx(arg) {
unsizing_params.insert(i);
}
@@ -424,7 +338,7 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32
// 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() {
+ for arg in tcx.type_of(field.did).instantiate_identity().walk() {
if let Some(i) = maybe_unsizing_param_idx(arg) {
unsizing_params.remove(i);
}
@@ -440,7 +354,6 @@ pub fn provide(providers: &mut Providers) {
adt_sized_constraint,
param_env,
param_env_reveal_all_normalized,
- instance_def_size_estimate,
issue33140_self_ty,
defaultness,
unsizing_params_for_adt,