From 1376c5a617be5c25655d0d7cb63e3beaa5a6e026 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:20:39 +0200 Subject: Merging upstream version 1.70.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_ty_utils/locales/en-US.ftl | 47 ----- compiler/rustc_ty_utils/messages.ftl | 57 ++++++ compiler/rustc_ty_utils/src/abi.rs | 14 +- compiler/rustc_ty_utils/src/assoc.rs | 245 ++++++++++++++++-------- compiler/rustc_ty_utils/src/common_traits.rs | 3 +- compiler/rustc_ty_utils/src/consts.rs | 5 +- compiler/rustc_ty_utils/src/errors.rs | 33 ++++ compiler/rustc_ty_utils/src/implied_bounds.rs | 1 - compiler/rustc_ty_utils/src/instance.rs | 20 +- compiler/rustc_ty_utils/src/layout.rs | 143 +++++++------- compiler/rustc_ty_utils/src/lib.rs | 5 +- compiler/rustc_ty_utils/src/representability.rs | 4 +- compiler/rustc_ty_utils/src/ty.rs | 100 ++++++++-- 13 files changed, 442 insertions(+), 235 deletions(-) delete mode 100644 compiler/rustc_ty_utils/locales/en-US.ftl create mode 100644 compiler/rustc_ty_utils/messages.ftl (limited to 'compiler/rustc_ty_utils') diff --git a/compiler/rustc_ty_utils/locales/en-US.ftl b/compiler/rustc_ty_utils/locales/en-US.ftl deleted file mode 100644 index abe65a0e3..000000000 --- a/compiler/rustc_ty_utils/locales/en-US.ftl +++ /dev/null @@ -1,47 +0,0 @@ -ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop - -ty_utils_generic_constant_too_complex = overly complex generic constant - .help = consider moving this anonymous constant into a `const` function - .maybe_supported = this operation may be supported in the future - -ty_utils_borrow_not_supported = borrowing is not supported in generic constants - -ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants - -ty_utils_array_not_supported = array construction is not supported in generic constants - -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_tuple_not_supported = tuple construction is not supported in generic constants - -ty_utils_index_not_supported = indexing is not supported in generic constants - -ty_utils_field_not_supported = field access is not supported in generic constants - -ty_utils_const_block_not_supported = const blocks are not supported in generic constants - -ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants - -ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants - -ty_utils_yield_not_supported = generator control flow is not allowed in generic constants - -ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants - -ty_utils_box_not_supported = allocations are not allowed in generic constants - -ty_utils_binary_not_supported = unsupported binary operation in generic constants - -ty_utils_logical_op_not_supported = unsupported operation in generic constants, short-circuiting operations would imply control flow - -ty_utils_assign_not_supported = assignment is not supported in generic constants - -ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants - -ty_utils_control_flow_not_supported = control flow is not supported in generic constants - -ty_utils_inline_asm_not_supported = assembly is not supported in generic constants - -ty_utils_operation_not_supported = unsupported operation in generic constants diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl new file mode 100644 index 000000000..15a14112f --- /dev/null +++ b/compiler/rustc_ty_utils/messages.ftl @@ -0,0 +1,57 @@ +ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop + +ty_utils_generic_constant_too_complex = overly complex generic constant + .help = consider moving this anonymous constant into a `const` function + .maybe_supported = this operation may be supported in the future + +ty_utils_borrow_not_supported = borrowing is not supported in generic constants + +ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants + +ty_utils_array_not_supported = array construction is not supported in generic constants + +ty_utils_block_not_supported = blocks are 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 + +ty_utils_index_not_supported = indexing is not supported in generic constants + +ty_utils_field_not_supported = field access is not supported in generic constants + +ty_utils_const_block_not_supported = const blocks are not supported in generic constants + +ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants + +ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants + +ty_utils_yield_not_supported = generator control flow is not allowed in generic constants + +ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants + +ty_utils_box_not_supported = allocations are not allowed in generic constants + +ty_utils_binary_not_supported = unsupported binary operation in generic constants + +ty_utils_logical_op_not_supported = unsupported operation in generic constants, short-circuiting operations would imply control flow + +ty_utils_assign_not_supported = assignment is not supported in generic constants + +ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants + +ty_utils_control_flow_not_supported = control flow is not supported in generic constants + +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 { +fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap { 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, + struct RPITVisitor<'tcx> { + rpits: FxIndexSet, + 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 { - 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>, repr: &ReprOptions, kind: StructKind, ) -> Result> { @@ -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>, 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::, _>>()?, + &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).try_collect::>()?, &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::, _>>()?, + &tys.iter().map(|k| Ok(cx.layout_of(k)?.layout)).try_collect::>()?, &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::, _>>() + .try_collect::>() }) - .collect::, _>>()?; + .try_collect::>()?; 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), + Ineligible(Option), } // 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 = - 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::, _>>()?; + .try_collect::>()?; 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 = 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::, _>>()?, + .try_collect::>()?, &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::, _>>()?; + .try_collect::>()?; 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 { +fn params_in_repr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> BitSet { 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, seen: FxHashSet, + depth: ty::DebruijnIndex, } impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { + fn visit_binder>>( + &mut self, + binder: &ty::Binder<'tcx, T>, + ) -> std::ops::ControlFlow { + 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 { - 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, 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