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