summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ty_utils
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /compiler/rustc_ty_utils
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_ty_utils')
-rw-r--r--compiler/rustc_ty_utils/messages.ftl (renamed from compiler/rustc_ty_utils/locales/en-US.ftl)12
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs14
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs245
-rw-r--r--compiler/rustc_ty_utils/src/common_traits.rs3
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs5
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs33
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs1
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs20
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs143
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs5
-rw-r--r--compiler/rustc_ty_utils/src/representability.rs4
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs100
12 files changed, 396 insertions, 189 deletions
diff --git a/compiler/rustc_ty_utils/locales/en-US.ftl b/compiler/rustc_ty_utils/messages.ftl
index abe65a0e3..15a14112f 100644
--- a/compiler/rustc_ty_utils/locales/en-US.ftl
+++ b/compiler/rustc_ty_utils/messages.ftl
@@ -12,7 +12,7 @@ ty_utils_array_not_supported = array construction is not supported in generic co
ty_utils_block_not_supported = blocks are not supported in generic constants
-ty_utils_never_to_any_not_supported = converting nevers to any is not supported in generic constants
+ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
ty_utils_tuple_not_supported = tuple construction is not supported in generic constants
@@ -45,3 +45,13 @@ ty_utils_control_flow_not_supported = control flow is not supported in generic c
ty_utils_inline_asm_not_supported = assembly is not supported in generic constants
ty_utils_operation_not_supported = unsupported operation in generic constants
+
+ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item
+
+ty_utils_zero_length_simd_type = monomorphising SIMD type `{$ty}` of zero length
+
+ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field
+
+ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
+
+ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 35c9f95eb..271284b2d 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -3,7 +3,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_middle::ty::layout::{
fn_can_unwind, FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout,
};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt};
use rustc_session::config::OptLevel;
use rustc_span::def_id::DefId;
use rustc_target::abi::call::{
@@ -29,6 +29,16 @@ fn fn_sig_for_fn_abi<'tcx>(
instance: ty::Instance<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> ty::PolyFnSig<'tcx> {
+ if let InstanceDef::ThreadLocalShim(..) = instance.def {
+ return ty::Binder::dummy(tcx.mk_fn_sig(
+ [],
+ tcx.thread_local_ptr_ty(instance.def_id()),
+ false,
+ hir::Unsafety::Normal,
+ rustc_target::spec::abi::Abi::Unadjusted,
+ ));
+ }
+
let ty = instance.ty(tcx, param_env);
match *ty.kind() {
ty::FnDef(..) => {
@@ -539,7 +549,7 @@ fn make_thin_self_ptr<'tcx>(
// get a built-in pointer type
let mut fat_pointer_layout = layout;
'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr()
- && !fat_pointer_layout.ty.is_region_ptr()
+ && !fat_pointer_layout.ty.is_ref()
{
for i in 0..fat_pointer_layout.fields.count() {
let field_layout = fat_pointer_layout.field(cx, i);
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 0648784b2..de1e1a527 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -1,10 +1,10 @@
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::definitions::DefPathData;
use rustc_hir::intravisit::{self, Visitor};
-use rustc_middle::ty::{self, DefIdTree, ImplTraitInTraitData, InternalSubsts, TyCtxt};
+use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, TyCtxt};
use rustc_span::symbol::kw;
pub fn provide(providers: &mut ty::query::Providers) {
@@ -12,20 +12,20 @@ pub fn provide(providers: &mut 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,
+ associated_types_for_impl_traits_in_associated_fn,
+ associated_type_for_impl_trait_in_trait,
impl_item_implementor_ids,
..*providers
};
}
-fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
- let item = tcx.hir().expect_item(def_id.expect_local());
+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.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty {
+ 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_items_for_impl_trait_in_trait
+ // corresponding associated item using associated_types_for_impl_traits_in_associated_fn
// query.
tcx.arena.alloc_from_iter(
trait_item_refs
@@ -40,7 +40,9 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
.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)
+ tcx.associated_types_for_impl_traits_in_associated_fn(
+ trait_fn_def_id,
+ )
})
.map(|def_id| *def_id),
),
@@ -54,10 +56,10 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
}
}
hir::ItemKind::Impl(ref impl_) => {
- if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty {
+ 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_items_for_impl_trait_in_trait query.
+ // associated_types_for_impl_traits_in_associated_fn query.
tcx.arena.alloc_from_iter(
impl_
.items
@@ -73,7 +75,9 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
.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)
+ tcx.associated_types_for_impl_traits_in_associated_fn(
+ impl_fn_def_id,
+ )
})
.map(|def_id| *def_id)
})),
@@ -97,34 +101,33 @@ fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems {
}
}
-fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId, DefId> {
+fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap<DefId> {
tcx.associated_items(impl_id)
.in_definition_order()
.filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id)))
.collect()
}
-fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
- let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem {
+ let id = tcx.hir().local_def_id_to_hir_id(def_id);
let parent_def_id = tcx.hir().get_parent_item(id);
let parent_item = tcx.hir().expect_item(parent_def_id.def_id);
match parent_item.kind {
hir::ItemKind::Impl(ref impl_) => {
- if let Some(impl_item_ref) =
- impl_.items.iter().find(|i| i.id.owner_id.to_def_id() == def_id)
+ if let Some(impl_item_ref) = impl_.items.iter().find(|i| i.id.owner_id.def_id == def_id)
{
let assoc_item = associated_item_from_impl_item_ref(impl_item_ref);
- debug_assert_eq!(assoc_item.def_id, def_id);
+ debug_assert_eq!(assoc_item.def_id.expect_local(), def_id);
return assoc_item;
}
}
hir::ItemKind::Trait(.., ref trait_item_refs) => {
if let Some(trait_item_ref) =
- trait_item_refs.iter().find(|i| i.id.owner_id.to_def_id() == def_id)
+ trait_item_refs.iter().find(|i| i.id.owner_id.def_id == def_id)
{
let assoc_item = associated_item_from_trait_item_ref(trait_item_ref);
- debug_assert_eq!(assoc_item.def_id, def_id);
+ debug_assert_eq!(assoc_item.def_id.expect_local(), def_id);
return assoc_item;
}
}
@@ -154,6 +157,7 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty
trait_item_def_id: Some(owner_id.to_def_id()),
container: ty::TraitContainer,
fn_has_self_parameter: has_self,
+ opt_rpitit_info: None,
}
}
@@ -172,40 +176,53 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
trait_item_def_id: impl_item_ref.trait_item_def_id,
container: ty::ImplContainer,
fn_has_self_parameter: has_self,
+ opt_rpitit_info: None,
}
}
-/// 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);
+/// Given an `fn_def_id` of a trait or a trait implementation:
+///
+/// if `fn_def_id` is a function defined inside a trait, then it synthesizes
+/// a new def id corresponding to a new associated type for each return-
+/// position `impl Trait` in the signature.
+///
+/// if `fn_def_id` is a function inside of an impl, then for each synthetic
+/// associated type generated for the corresponding trait function described
+/// above, synthesize a corresponding associated type in the impl.
+fn associated_types_for_impl_traits_in_associated_fn(
+ tcx: TyCtxt<'_>,
+ fn_def_id: LocalDefId,
+) -> &'_ [DefId] {
+ let parent_def_id = tcx.local_parent(fn_def_id);
match tcx.def_kind(parent_def_id) {
DefKind::Trait => {
- struct RPITVisitor {
- rpits: Vec<LocalDefId>,
+ struct RPITVisitor<'tcx> {
+ rpits: FxIndexSet<LocalDefId>,
+ tcx: TyCtxt<'tcx>,
}
- 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)
+ impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> {
+ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
+ if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind
+ && self.rpits.insert(item_id.owner_id.def_id)
+ {
+ let opaque_item = self.tcx.hir().expect_item(item_id.owner_id.def_id).expect_opaque_ty();
+ for bound in opaque_item.bounds {
+ intravisit::walk_param_bound(self, bound);
+ }
}
intravisit::walk_ty(self, ty)
}
}
- let mut visitor = RPITVisitor { rpits: Vec::new() };
+ let mut visitor = RPITVisitor { tcx, rpits: FxIndexSet::default() };
- if let Some(output) = tcx.hir().get_fn_output(fn_def_id.expect_local()) {
+ if let Some(output) = tcx.hir().get_fn_output(fn_def_id) {
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()
+ tcx.associated_type_for_impl_trait_in_trait(opaque_ty_def_id).to_def_id()
}))
} else {
&[]
@@ -216,40 +233,40 @@ fn associated_items_for_impl_trait_in_trait(tcx: TyCtxt<'_>, fn_def_id: DefId) -
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()
+ tcx.associated_types_for_impl_traits_in_associated_fn(trait_fn_def_id).iter().map(
+ move |&trait_assoc_def_id| {
+ associated_type_for_impl_trait_in_impl(tcx, trait_assoc_def_id, fn_def_id)
+ .to_def_id()
},
),
)
}
def_kind => bug!(
- "associated_items_for_impl_trait_in_trait: {:?} should be Trait or Impl but is {:?}",
+ "associated_types_for_impl_traits_in_associated_fn: {:?} 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(
+/// Given an `opaque_ty_def_id` corresponding to an `impl Trait` in an associated
+/// function from a trait, synthesize an associated type for that `impl Trait`
+/// that inherits properties that we infer from the method and the opaque type.
+fn associated_type_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);
+ let (hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) =
+ tcx.hir().expect_item(opaque_ty_def_id).expect_opaque_ty().origin
+ else {
+ bug!("expected opaque for {opaque_ty_def_id:?}");
+ };
+ let trait_def_id = tcx.local_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 trait_assoc_ty = tcx.at(span).create_def(trait_def_id, DefPathData::ImplTraitAssocTy);
let local_def_id = trait_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();
@@ -263,12 +280,6 @@ fn associated_item_for_impl_trait_in_trait(
// 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,
@@ -276,6 +287,10 @@ fn associated_item_for_impl_trait_in_trait(
trait_item_def_id: None,
container: ty::TraitContainer,
fn_has_self_parameter: false,
+ opt_rpitit_info: Some(ImplTraitInTraitData::Trait {
+ fn_def_id: fn_def_id.to_def_id(),
+ opaque_def_id: opaque_ty_def_id.to_def_id(),
+ }),
});
// Copy visility of the containing function.
@@ -287,40 +302,70 @@ fn associated_item_for_impl_trait_in_trait(
// 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()),
+ InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
)));
- // Copy generics_of of the opaque.
- trait_assoc_ty.generics_of(tcx.generics_of(opaque_ty_def_id).clone());
+ trait_assoc_ty.is_type_alias_impl_trait(false);
+
+ // Copy generics_of of the opaque type item but the trait is the parent.
+ trait_assoc_ty.generics_of({
+ let opaque_ty_generics = tcx.generics_of(opaque_ty_def_id);
+ let opaque_ty_parent_count = opaque_ty_generics.parent_count;
+ let mut params = opaque_ty_generics.params.clone();
+
+ let parent_generics = tcx.generics_of(trait_def_id);
+ let parent_count = parent_generics.parent_count + parent_generics.params.len();
+
+ let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone();
+
+ for param in &mut params {
+ param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32
+ - opaque_ty_parent_count as u32;
+ }
+
+ trait_fn_params.extend(params);
+ params = trait_fn_params;
+
+ let param_def_id_to_index =
+ params.iter().map(|param| (param.def_id, param.index)).collect();
+
+ ty::Generics {
+ parent: Some(trait_def_id.to_def_id()),
+ parent_count,
+ params,
+ param_def_id_to_index,
+ has_self: false,
+ has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
+ }
+ });
// There are no predicates for the synthesized associated type.
trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
- parent: Some(trait_def_id),
+ parent: Some(trait_def_id.to_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(
+/// Given an `trait_assoc_def_id` corresponding to an associated item synthesized
+/// from an `impl Trait` in an associated function from a trait, and an
+/// `impl_fn_def_id` that represents an implementation of the associated function
+/// that the `impl Trait` comes from, synthesize an associated type for that `impl Trait`
+/// that inherits properties that we infer from the method and the associated type.
+fn associated_type_for_impl_trait_in_impl(
tcx: TyCtxt<'_>,
- trait_assoc_def_id: LocalDefId,
+ trait_assoc_def_id: DefId,
impl_fn_def_id: LocalDefId,
) -> LocalDefId {
- let impl_def_id = tcx.local_parent(impl_fn_def_id);
+ 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 impl_assoc_ty = tcx.at(span).create_def(impl_def_id, DefPathData::ImplTraitAssocTy);
+ let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, DefPathData::ImplTraitAssocTy);
let local_def_id = impl_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();
@@ -331,27 +376,61 @@ fn impl_associated_item_for_impl_trait_in_trait(
// `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(),
- }));
+ // Copy span of the opaque.
+ impl_assoc_ty.def_ident_span(Some(span));
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()),
+ trait_item_def_id: Some(trait_assoc_def_id),
container: ty::ImplContainer,
fn_has_self_parameter: false,
+ opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),
});
+ // Copy visility of the containing function.
+ impl_assoc_ty.visibility(tcx.visibility(impl_fn_def_id));
+
// 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());
+ // Copy generics_of the trait's associated item but the impl as the parent.
+ // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) resolves to the trait instead of the impl
+ // generics.
+ impl_assoc_ty.generics_of({
+ let trait_assoc_generics = tcx.generics_of(trait_assoc_def_id);
+ let trait_assoc_parent_count = trait_assoc_generics.parent_count;
+ let mut params = trait_assoc_generics.params.clone();
+
+ let parent_generics = tcx.generics_of(impl_local_def_id.to_def_id());
+ let parent_count = parent_generics.parent_count + parent_generics.params.len();
+
+ for param in &mut params {
+ param.index = param.index + parent_count as u32 - trait_assoc_parent_count as u32;
+ }
+
+ let param_def_id_to_index =
+ params.iter().map(|param| (param.def_id, param.index)).collect();
+
+ ty::Generics {
+ parent: Some(impl_local_def_id.to_def_id()),
+ parent_count,
+ params,
+ param_def_id_to_index,
+ has_self: false,
+ has_late_bound_regions: trait_assoc_generics.has_late_bound_regions,
+ }
+ });
+
+ // There are no predicates for the synthesized associated type.
+ impl_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
+ parent: Some(impl_local_def_id.to_def_id()),
+ predicates: &[],
+ });
+
+ // There are no inferred outlives for the synthesized associated type.
+ impl_assoc_ty.inferred_outlives_of(&[]);
local_def_id
}
diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs
index d3169b6d9..3b1abdcb2 100644
--- a/compiler/rustc_ty_utils/src/common_traits.rs
+++ b/compiler/rustc_ty_utils/src/common_traits.rs
@@ -3,7 +3,6 @@
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits;
fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
@@ -30,7 +29,7 @@ fn is_item_raw<'tcx>(
let (param_env, ty) = query.into_parts();
let trait_def_id = tcx.require_lang_item(item, None);
let infcx = tcx.infer_ctxt().build();
- traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id, DUMMY_SP)
+ traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id)
}
pub(crate) fn provide(providers: &mut ty::query::Providers) {
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index f26352716..b67607a4d 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::abstract_const::CastKind;
use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitableExt};
use rustc_middle::{mir, thir};
use rustc_span::Span;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{VariantIdx, FIRST_VARIANT};
use std::iter;
@@ -44,7 +44,7 @@ pub(crate) fn destructure_const<'tcx>(
let (head, rest) = branches.split_first().unwrap();
(VariantIdx::from_u32(head.unwrap_leaf().try_to_u32().unwrap()), rest)
} else {
- (VariantIdx::from_u32(0), branches)
+ (FIRST_VARIANT, branches)
};
let fields = &def.variant(variant_idx).fields;
let mut field_consts = Vec::with_capacity(fields.len());
@@ -425,7 +425,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers {
destructure_const,
thir_abstract_const: |tcx, def_id| {
- let def_id = def_id.expect_local();
if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
tcx.thir_abstract_const_of_const_arg(def)
} else {
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index ab3e62f04..3d3fc50e6 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -67,3 +67,36 @@ pub enum GenericConstantTooComplexSub {
#[label(ty_utils_operation_not_supported)]
OperationNotSupported(#[primary_span] Span),
}
+
+#[derive(Diagnostic)]
+#[diag(ty_utils_unexpected_fnptr_associated_item)]
+pub struct UnexpectedFnPtrAssociatedItem {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ty_utils_zero_length_simd_type)]
+pub struct ZeroLengthSimdType<'tcx> {
+ pub ty: Ty<'tcx>,
+}
+
+#[derive(Diagnostic)]
+#[diag(ty_utils_multiple_array_fields_simd_type)]
+pub struct MultipleArrayFieldsSimdType<'tcx> {
+ pub ty: Ty<'tcx>,
+}
+
+#[derive(Diagnostic)]
+#[diag(ty_utils_oversized_simd_type)]
+pub struct OversizedSimdType<'tcx> {
+ pub ty: Ty<'tcx>,
+ pub max_lanes: u64,
+}
+
+#[derive(Diagnostic)]
+#[diag(ty_utils_non_primitive_simd_type)]
+pub struct NonPrimitiveSimdType<'tcx> {
+ pub ty: Ty<'tcx>,
+ pub e_ty: Ty<'tcx>,
+}
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 7fecee2a3..56d6cc28b 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -1,4 +1,3 @@
-use crate::rustc_middle::ty::DefIdTree;
use rustc_hir::{def::DefKind, def_id::DefId};
use rustc_middle::ty::{self, Ty, TyCtxt};
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 2eaeca73d..0a6c11809 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -8,6 +8,8 @@ use rustc_span::sym;
use rustc_trait_selection::traits;
use traits::{translate_substs, Reveal};
+use crate::errors::UnexpectedFnPtrAssociatedItem;
+
fn resolve_instance<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
@@ -243,7 +245,8 @@ fn resolve_associated_item<'tcx>(
}
}
traits::ImplSource::Builtin(..) => {
- if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() {
+ 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.
let name = tcx.item_name(trait_item_id);
if name == sym::clone {
@@ -270,6 +273,21 @@ fn resolve_associated_item<'tcx>(
let substs = tcx.erase_regions(rcvr_substs);
Some(ty::Instance::new(trait_item_id, substs))
}
+ } else if Some(trait_ref.def_id) == lang_items.fn_ptr_trait() {
+ if lang_items.fn_ptr_addr() == Some(trait_item_id) {
+ let self_ty = trait_ref.self_ty();
+ if !matches!(self_ty.kind(), ty::FnPtr(..)) {
+ return Ok(None);
+ }
+ Some(Instance {
+ def: ty::InstanceDef::FnPtrAddrShim(trait_item_id, self_ty),
+ substs: rcvr_substs,
+ })
+ } else {
+ tcx.sess.emit_fatal(UnexpectedFnPtrAssociatedItem {
+ span: tcx.def_span(trait_item_id),
+ })
+ }
} else {
None
}
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index e3132fcc4..63ef1c724 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -1,7 +1,7 @@
use hir::def_id::DefId;
use rustc_hir as hir;
use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::{IndexSlice, IndexVec};
use rustc_middle::mir::{GeneratorLayout, GeneratorSavedLocal};
use rustc_middle::ty::layout::{
IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
@@ -17,6 +17,9 @@ use rustc_target::abi::*;
use std::fmt::Debug;
use std::iter;
+use crate::errors::{
+ MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType,
+};
use crate::layout_sanity_check::sanity_check_layout;
pub fn provide(providers: &mut ty::query::Providers) {
@@ -62,23 +65,10 @@ fn layout_of<'tcx>(
Ok(layout)
}
-// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
-// This is used to go between `memory_index` (source field order to memory order)
-// and `inverse_memory_index` (memory order to source field order).
-// See also `FieldsShape::Arbitrary::memory_index` for more details.
-// FIXME(eddyb) build a better abstraction for permutations, if possible.
-fn invert_mapping(map: &[u32]) -> Vec<u32> {
- let mut inverse = vec![0; map.len()];
- for i in 0..map.len() {
- inverse[map[i] as usize] = i as u32;
- }
- inverse
-}
-
fn univariant_uninterned<'tcx>(
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
ty: Ty<'tcx>,
- fields: &[Layout<'_>],
+ fields: &IndexSlice<FieldIdx, Layout<'_>>,
repr: &ReprOptions,
kind: StructKind,
) -> Result<LayoutS, LayoutError<'tcx>> {
@@ -106,7 +96,7 @@ fn layout_of_uncached<'tcx>(
};
let scalar = |value: Primitive| tcx.mk_layout(LayoutS::scalar(cx, scalar_unit(value)));
- let univariant = |fields: &[Layout<'_>], repr: &ReprOptions, kind| {
+ let univariant = |fields: &IndexSlice<FieldIdx, Layout<'_>>, repr: &ReprOptions, kind| {
Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, repr, kind)?))
};
debug_assert!(!ty.has_non_region_infer());
@@ -156,7 +146,11 @@ fn layout_of_uncached<'tcx>(
let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
- let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
+ let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type()
+ // Projection eagerly bails out when the pointee references errors,
+ // fall back to structurally deducing metadata.
+ && !pointee.references_error()
+ {
let metadata_ty = tcx.normalize_erasing_regions(
param_env,
tcx.mk_projection(metadata_def_id, [pointee]),
@@ -223,7 +217,7 @@ fn layout_of_uncached<'tcx>(
let largest_niche = if count != 0 { element.largest_niche } else { None };
tcx.mk_layout(LayoutS {
- variants: Variants::Single { index: VariantIdx::new(0) },
+ variants: Variants::Single { index: FIRST_VARIANT },
fields: FieldsShape::Array { stride: element.size, count },
abi,
largest_niche,
@@ -234,7 +228,7 @@ fn layout_of_uncached<'tcx>(
ty::Slice(element) => {
let element = cx.layout_of(element)?;
tcx.mk_layout(LayoutS {
- variants: Variants::Single { index: VariantIdx::new(0) },
+ variants: Variants::Single { index: FIRST_VARIANT },
fields: FieldsShape::Array { stride: element.size, count: 0 },
abi: Abi::Aggregate { sized: false },
largest_niche: None,
@@ -243,7 +237,7 @@ fn layout_of_uncached<'tcx>(
})
}
ty::Str => tcx.mk_layout(LayoutS {
- variants: Variants::Single { index: VariantIdx::new(0) },
+ variants: Variants::Single { index: FIRST_VARIANT },
fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
abi: Abi::Aggregate { sized: false },
largest_niche: None,
@@ -252,12 +246,14 @@ fn layout_of_uncached<'tcx>(
}),
// Odd unit types.
- ty::FnDef(..) => univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)?,
+ ty::FnDef(..) => {
+ univariant(IndexSlice::empty(), &ReprOptions::default(), StructKind::AlwaysSized)?
+ }
ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => {
let mut unit = univariant_uninterned(
cx,
ty,
- &[],
+ IndexSlice::empty(),
&ReprOptions::default(),
StructKind::AlwaysSized,
)?;
@@ -273,7 +269,7 @@ fn layout_of_uncached<'tcx>(
ty::Closure(_, ref substs) => {
let tys = substs.as_closure().upvar_tys();
univariant(
- &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).collect::<Result<Vec<_>, _>>()?,
+ &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).try_collect::<IndexVec<_, _>>()?,
&ReprOptions::default(),
StructKind::AlwaysSized,
)?
@@ -284,7 +280,7 @@ fn layout_of_uncached<'tcx>(
if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
univariant(
- &tys.iter().map(|k| Ok(cx.layout_of(k)?.layout)).collect::<Result<Vec<_>, _>>()?,
+ &tys.iter().map(|k| Ok(cx.layout_of(k)?.layout)).try_collect::<IndexVec<_, _>>()?,
&ReprOptions::default(),
kind,
)?
@@ -301,6 +297,8 @@ fn layout_of_uncached<'tcx>(
return Err(LayoutError::Unknown(ty));
}
+ let fields = &def.non_enum_variant().fields;
+
// Supported SIMD vectors are homogeneous ADTs with at least one field:
//
// * #[repr(simd)] struct S(T, T, T, T);
@@ -311,18 +309,22 @@ fn layout_of_uncached<'tcx>(
// SIMD vectors with zero fields are not supported.
// (should be caught by typeck)
- if def.non_enum_variant().fields.is_empty() {
- tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty));
+ if fields.is_empty() {
+ tcx.sess.emit_fatal(ZeroLengthSimdType { ty })
}
// Type of the first ADT field:
- let f0_ty = def.non_enum_variant().fields[0].ty(tcx, substs);
+ let f0_ty = fields[FieldIdx::from_u32(0)].ty(tcx, substs);
// Heterogeneous SIMD vectors are not supported:
// (should be caught by typeck)
- for fi in &def.non_enum_variant().fields {
+ for fi in fields {
if fi.ty(tcx, substs) != f0_ty {
- tcx.sess.fatal(&format!("monomorphising heterogeneous SIMD type `{}`", ty));
+ tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ "#[repr(simd)] was applied to an ADT with heterogeneous field type",
+ );
+ return Err(LayoutError::Unknown(ty));
}
}
@@ -337,12 +339,9 @@ fn layout_of_uncached<'tcx>(
// First ADT field is an array:
// SIMD vectors with multiple array fields are not supported:
- // (should be caught by typeck)
+ // Can't be caught by typeck with a generic simd type.
if def.non_enum_variant().fields.len() != 1 {
- tcx.sess.fatal(&format!(
- "monomorphising SIMD type `{}` with more than one array field",
- ty
- ));
+ tcx.sess.emit_fatal(MultipleArrayFieldsSimdType { ty });
}
// Extract the number of elements from the layout of the array field:
@@ -362,12 +361,9 @@ fn layout_of_uncached<'tcx>(
//
// Can't be caught in typeck if the array length is generic.
if e_len == 0 {
- tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty));
+ tcx.sess.emit_fatal(ZeroLengthSimdType { ty });
} else if e_len > MAX_SIMD_LANES {
- tcx.sess.fatal(&format!(
- "monomorphising SIMD type `{}` of length greater than {}",
- ty, MAX_SIMD_LANES,
- ));
+ tcx.sess.emit_fatal(OversizedSimdType { ty, max_lanes: MAX_SIMD_LANES });
}
// Compute the ABI of the element type:
@@ -375,11 +371,7 @@ fn layout_of_uncached<'tcx>(
let Abi::Scalar(e_abi) = e_ly.abi else {
// This error isn't caught in typeck, e.g., if
// the element type of the vector is generic.
- tcx.sess.fatal(&format!(
- "monomorphising SIMD type `{}` with a non-primitive-scalar \
- (integer/float/pointer) element type `{}`",
- ty, e_ty
- ))
+ tcx.sess.emit_fatal(NonPrimitiveSimdType { ty, e_ty });
};
// Compute the size and alignment of the vector:
@@ -389,13 +381,13 @@ fn layout_of_uncached<'tcx>(
// Compute the placement of the vector fields:
let fields = if is_array {
- FieldsShape::Arbitrary { offsets: vec![Size::ZERO], memory_index: vec![0] }
+ FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() }
} else {
FieldsShape::Array { stride: e_ly.size, count: e_len }
};
tcx.mk_layout(LayoutS {
- variants: Variants::Single { index: VariantIdx::new(0) },
+ variants: Variants::Single { index: FIRST_VARIANT },
fields,
abi: Abi::Vector { element: e_abi, count: e_len },
largest_niche: e_ly.largest_niche,
@@ -414,9 +406,9 @@ fn layout_of_uncached<'tcx>(
v.fields
.iter()
.map(|field| Ok(cx.layout_of(field.ty(tcx, substs))?.layout))
- .collect::<Result<Vec<_>, _>>()
+ .try_collect::<IndexVec<_, _>>()
})
- .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
+ .try_collect::<IndexVec<VariantIdx, _>>()?;
if def.is_union() {
if def.repr().pack.is_some() && def.repr().align.is_some() {
@@ -452,7 +444,8 @@ 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()) {
+ && match def.variants().iter().next().and_then(|x| x.fields.raw.last())
+ {
Some(last_field) => tcx
.type_of(last_field.did)
.subst_identity()
@@ -487,8 +480,7 @@ fn layout_of_uncached<'tcx>(
enum SavedLocalEligibility {
Unassigned,
Assigned(VariantIdx),
- // FIXME: Use newtype_index so we aren't wasting bytes
- Ineligible(Option<u32>),
+ Ineligible(Option<FieldIdx>),
}
// When laying out generators, we divide our saved local fields into two
@@ -517,7 +509,7 @@ fn generator_saved_local_eligibility(
use SavedLocalEligibility::*;
let mut assignments: IndexVec<GeneratorSavedLocal, SavedLocalEligibility> =
- IndexVec::from_elem_n(Unassigned, info.field_tys.len());
+ IndexVec::from_elem(Unassigned, &info.field_tys);
// The saved locals not eligible for overlap. These will get
// "promoted" to the prefix of our generator.
@@ -600,7 +592,7 @@ fn generator_saved_local_eligibility(
// Write down the order of our locals that will be promoted to the prefix.
{
for (idx, local) in ineligible_locals.iter().enumerate() {
- assignments[local] = Ineligible(Some(idx as u32));
+ assignments[local] = Ineligible(Some(FieldIdx::from_usize(idx)));
}
}
debug!("generator saved local assignments: {:?}", assignments);
@@ -649,7 +641,7 @@ fn generator_layout<'tcx>(
.map(|ty| Ok(cx.layout_of(ty)?.layout))
.chain(iter::once(Ok(tag_layout)))
.chain(promoted_layouts)
- .collect::<Result<Vec<_>, _>>()?;
+ .try_collect::<IndexVec<_, _>>()?;
let prefix = univariant_uninterned(
cx,
ty,
@@ -667,26 +659,28 @@ fn generator_layout<'tcx>(
debug!("prefix = {:#?}", prefix);
let (outer_fields, promoted_offsets, promoted_memory_index) = match prefix.fields {
FieldsShape::Arbitrary { mut offsets, memory_index } => {
- let mut inverse_memory_index = invert_mapping(&memory_index);
+ let mut inverse_memory_index = memory_index.invert_bijective_mapping();
// "a" (`0..b_start`) and "b" (`b_start..`) correspond to
// "outer" and "promoted" fields respectively.
- let b_start = (tag_index + 1) as u32;
- let offsets_b = offsets.split_off(b_start as usize);
+ let b_start = FieldIdx::from_usize(tag_index + 1);
+ let offsets_b = IndexVec::from_raw(offsets.raw.split_off(b_start.as_usize()));
let offsets_a = offsets;
// Disentangle the "a" and "b" components of `inverse_memory_index`
// by preserving the order but keeping only one disjoint "half" each.
// FIXME(eddyb) build a better abstraction for permutations, if possible.
- let inverse_memory_index_b: Vec<_> =
- inverse_memory_index.iter().filter_map(|&i| i.checked_sub(b_start)).collect();
- inverse_memory_index.retain(|&i| i < b_start);
+ let inverse_memory_index_b: IndexVec<u32, FieldIdx> = inverse_memory_index
+ .iter()
+ .filter_map(|&i| i.as_u32().checked_sub(b_start.as_u32()).map(FieldIdx::from_u32))
+ .collect();
+ inverse_memory_index.raw.retain(|&i| i < b_start);
let inverse_memory_index_a = inverse_memory_index;
// Since `inverse_memory_index_{a,b}` each only refer to their
// respective fields, they can be safely inverted
- let memory_index_a = invert_mapping(&inverse_memory_index_a);
- let memory_index_b = invert_mapping(&inverse_memory_index_b);
+ let memory_index_a = inverse_memory_index_a.invert_bijective_mapping();
+ let memory_index_b = inverse_memory_index_b.invert_bijective_mapping();
let outer_fields =
FieldsShape::Arbitrary { offsets: offsets_a, memory_index: memory_index_a };
@@ -717,7 +711,7 @@ fn generator_layout<'tcx>(
ty,
&variant_only_tys
.map(|ty| Ok(cx.layout_of(ty)?.layout))
- .collect::<Result<Vec<_>, _>>()?,
+ .try_collect::<IndexVec<_, _>>()?,
&ReprOptions::default(),
StructKind::Prefixed(prefix_size, prefix_align.abi),
)?;
@@ -736,13 +730,16 @@ fn generator_layout<'tcx>(
// promoted fields were being used, but leave the elements not in the
// subset as `INVALID_FIELD_IDX`, which we can filter out later to
// obtain a valid (bijective) mapping.
- const INVALID_FIELD_IDX: u32 = !0;
- let mut combined_inverse_memory_index =
- vec![INVALID_FIELD_IDX; promoted_memory_index.len() + memory_index.len()];
+ const INVALID_FIELD_IDX: FieldIdx = FieldIdx::MAX;
+ debug_assert!(variant_fields.next_index() <= INVALID_FIELD_IDX);
+
+ let mut combined_inverse_memory_index = IndexVec::from_elem_n(
+ INVALID_FIELD_IDX,
+ promoted_memory_index.len() + memory_index.len(),
+ );
let mut offsets_and_memory_index = iter::zip(offsets, memory_index);
let combined_offsets = variant_fields
- .iter()
- .enumerate()
+ .iter_enumerated()
.map(|(i, local)| {
let (offset, memory_index) = match assignments[*local] {
Unassigned => bug!(),
@@ -751,19 +748,19 @@ fn generator_layout<'tcx>(
(offset, promoted_memory_index.len() as u32 + memory_index)
}
Ineligible(field_idx) => {
- let field_idx = field_idx.unwrap() as usize;
+ let field_idx = field_idx.unwrap();
(promoted_offsets[field_idx], promoted_memory_index[field_idx])
}
};
- combined_inverse_memory_index[memory_index as usize] = i as u32;
+ combined_inverse_memory_index[memory_index] = i;
offset
})
.collect();
// Remove the unused slots and invert the mapping to obtain the
// combined `memory_index` (also see previous comment).
- combined_inverse_memory_index.retain(|&i| i != INVALID_FIELD_IDX);
- let combined_memory_index = invert_mapping(&combined_inverse_memory_index);
+ combined_inverse_memory_index.raw.retain(|&i| i != INVALID_FIELD_IDX);
+ let combined_memory_index = combined_inverse_memory_index.invert_bijective_mapping();
variant.fields = FieldsShape::Arbitrary {
offsets: combined_offsets,
@@ -774,7 +771,7 @@ fn generator_layout<'tcx>(
align = align.max(variant.align);
Ok(variant)
})
- .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
+ .try_collect::<IndexVec<VariantIdx, _>>()?;
size = size.align_to(align.abi);
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 35f468aa9..2613445f3 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -5,10 +5,13 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(iterator_try_collect)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(box_patterns)]
#![recursion_limit = "256"]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_middle;
@@ -33,7 +36,7 @@ pub mod representability;
mod structural_match;
mod ty;
-fluent_messages! { "../locales/en-US.ftl" }
+fluent_messages! { "../messages.ftl" }
pub fn provide(providers: &mut Providers) {
abi::provide(providers);
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index 591017eec..26d6deab8 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -4,7 +4,7 @@ use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Representability, Ty, TyCtxt};
-use rustc_span::def_id::{DefId, LocalDefId};
+use rustc_span::def_id::LocalDefId;
pub fn provide(providers: &mut Providers) {
*providers =
@@ -85,7 +85,7 @@ fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representab
Representability::Representable
}
-fn params_in_repr(tcx: TyCtxt<'_>, def_id: DefId) -> BitSet<u32> {
+fn params_in_repr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> BitSet<u32> {
let adt_def = tcx.adt_def(def_id);
let generics = tcx.generics_of(def_id);
let mut params_in_repr = BitSet::new_empty(generics.params.len());
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 18159778a..cb06c7acf 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -3,11 +3,12 @@ use rustc_hir as hir;
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,
+ self, Binder, EarlyBinder, ImplTraitInTraitData, Predicate, PredicateKind, ToPredicate, Ty,
+ TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use rustc_session::config::TraitSolver;
-use rustc_span::def_id::{DefId, CRATE_DEF_ID};
+use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
+use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits;
fn sized_constraint_for_ty<'tcx>(
@@ -76,8 +77,8 @@ fn sized_constraint_for_ty<'tcx>(
result
}
-fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
- match tcx.hir().get_by_def_id(def_id.expect_local()) {
+fn impl_defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
+ match tcx.hir().get_by_def_id(def_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.defaultness,
hir::Node::ImplItem(hir::ImplItem { defaultness, .. })
| hir::Node::TraitItem(hir::TraitItem { defaultness, .. }) => *defaultness,
@@ -106,7 +107,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
let result = tcx.mk_type_list_from_iter(
def.variants()
.iter()
- .flat_map(|v| v.fields.last())
+ .filter_map(|v| v.fields.raw.last())
.flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).subst_identity())),
);
@@ -121,6 +122,20 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
let ty::InstantiatedPredicates { mut predicates, .. } =
tcx.predicates_of(def_id).instantiate_identity(tcx);
+ // When computing the param_env of an RPITIT, use predicates of the containing function,
+ // *except* for the additional assumption that the RPITIT normalizes to the trait method's
+ // default opaque type. This is needed to properly check the item bounds of the assoc
+ // type hold (`check_type_bounds`), since that method already installs a similar projection
+ // bound, so they will conflict.
+ // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): I don't like this, we should
+ // at least be making sure that the generics in RPITITs and their parent fn don't
+ // get out of alignment, or else we do actually need to substitute these predicates.
+ if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
+ | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id)
+ {
+ predicates = tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates;
+ }
+
// Finally, we have to normalize the bounds in the environment, in
// case they contain any associated type projections. This process
// can yield errors if the put in illegal associated types, like
@@ -142,17 +157,21 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
&& tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer
{
let sig = tcx.fn_sig(def_id).subst_identity();
- sig.visit_with(&mut ImplTraitInTraitFinder {
+ // We accounted for the binder of the fn sig, so skip the binder.
+ sig.skip_binder().visit_with(&mut ImplTraitInTraitFinder {
tcx,
fn_def_id: def_id,
bound_vars: sig.bound_vars(),
predicates: &mut predicates,
seen: FxHashSet::default(),
+ depth: ty::INNERMOST,
});
}
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));
+ // 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 {
@@ -244,27 +263,68 @@ struct ImplTraitInTraitFinder<'a, 'tcx> {
fn_def_id: DefId,
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
seen: FxHashSet<DefId>,
+ depth: ty::DebruijnIndex,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
+ &mut self,
+ binder: &ty::Binder<'tcx, T>,
+ ) -> std::ops::ControlFlow<Self::BreakTy> {
+ self.depth.shift_in(1);
+ let binder = binder.super_visit_with(self);
+ self.depth.shift_out(1);
+ binder
+ }
+
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)
+ 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
+ && self.seen.insert(unshifted_alias_ty.def_id)
{
+ // We have entered some binders as we've walked into the
+ // bounds of the RPITIT. Shift these binders back out when
+ // constructing the top-level projection predicate.
+ let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| {
+ if let ty::ReLateBound(index, bv) = re.kind() {
+ if depth != ty::INNERMOST {
+ return self.tcx.mk_re_error_with_message(
+ DUMMY_SP,
+ "we shouldn't walk non-predicate binders with `impl Trait`...",
+ );
+ }
+ self.tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
+ } else {
+ re
+ }
+ });
+
+ // 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 {
+ self.tcx.mk_alias(ty::Opaque, shifted_alias_ty)
+ };
+
self.predicates.push(
ty::Binder::bind_with_vars(
- ty::ProjectionPredicate {
- projection_ty: alias_ty,
- term: self.tcx.mk_alias(ty::Opaque, alias_ty).into(),
- },
+ ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_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)
+ // We walk the *un-shifted* alias ty, because we're tracking the de bruijn
+ // binder depth, and if we were to walk `shifted_alias_ty` instead, we'd
+ // have to reset `self.depth` back to `ty::INNERMOST` or something. It's
+ // easier to just do this.
+ for bound in self
+ .tcx
+ .item_bounds(unshifted_alias_ty.def_id)
+ .subst_iter(self.tcx, unshifted_alias_ty.substs)
{
bound.visit_with(self);
}
@@ -456,8 +516,8 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'
}
/// Check if a function is async.
-fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
- let node = tcx.hir().get_by_def_id(def_id.expect_local());
+fn asyncness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::IsAsync {
+ let node = tcx.hir().get_by_def_id(def_id);
node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness)
}
@@ -482,7 +542,7 @@ 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.split_last() else
+ def.non_enum_variant().fields.raw.split_last() else
{
return BitSet::new_empty(num_params);
};