diff options
Diffstat (limited to 'compiler/rustc_ty_utils')
| -rw-r--r-- | compiler/rustc_ty_utils/src/assoc.rs | 308 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/layout.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/opaque_types.rs | 11 | 
3 files changed, 139 insertions, 184 deletions
| diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 2fb3c5ff945..37cb64511c7 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -1,18 +1,20 @@ -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::definitions::{DefPathData, DisambiguatorState}; use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::{self as hir, ItemKind}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt}; use rustc_middle::{bug, span_bug}; +use rustc_span::Ident; +use rustc_span::symbol::kw; pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { associated_item, associated_item_def_ids, associated_items, - associated_types_for_impl_traits_in_associated_fn, + associated_types_for_impl_traits_in_trait_or_impl, impl_item_implementor_ids, ..*providers }; @@ -22,54 +24,28 @@ 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(.., trait_item_refs) => { - // We collect RPITITs for each trait method's return type and create a - // corresponding associated item using associated_types_for_impl_traits_in_associated_fn + // We collect RPITITs for each trait method's return type and create a corresponding + // associated item using the associated_types_for_impl_traits_in_trait_or_impl // query. - tcx.arena.alloc_from_iter( - trait_item_refs - .iter() - .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()) - .chain( - trait_item_refs - .iter() - .filter(|trait_item_ref| { - matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. }) - }) - .flat_map(|trait_item_ref| { - let trait_fn_def_id = trait_item_ref.id.owner_id.def_id.to_def_id(); - tcx.associated_types_for_impl_traits_in_associated_fn( - trait_fn_def_id, - ) - }) - .copied(), - ), - ) + let rpitit_items = tcx.associated_types_for_impl_traits_in_trait_or_impl(def_id); + tcx.arena.alloc_from_iter(trait_item_refs.iter().flat_map(|trait_item_ref| { + let item_def_id = trait_item_ref.owner_id.to_def_id(); + [item_def_id] + .into_iter() + .chain(rpitit_items.get(&item_def_id).into_iter().flatten().copied()) + })) } hir::ItemKind::Impl(impl_) => { // We collect RPITITs for each trait method's return type, on the impl side too and // create a corresponding associated item using - // associated_types_for_impl_traits_in_associated_fn query. - tcx.arena.alloc_from_iter( - impl_ - .items - .iter() - .map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()) - .chain(impl_.of_trait.iter().flat_map(|_| { - impl_ - .items - .iter() - .filter(|impl_item_ref| { - matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. }) - }) - .flat_map(|impl_item_ref| { - let impl_fn_def_id = impl_item_ref.id.owner_id.def_id.to_def_id(); - tcx.associated_types_for_impl_traits_in_associated_fn( - impl_fn_def_id, - ) - }) - .copied() - })), - ) + // associated_types_for_impl_traits_in_trait_or_impl query. + let rpitit_items = tcx.associated_types_for_impl_traits_in_trait_or_impl(def_id); + tcx.arena.alloc_from_iter(impl_.items.iter().flat_map(|impl_item_ref| { + let item_def_id = impl_item_ref.owner_id.to_def_id(); + [item_def_id] + .into_iter() + .chain(rpitit_items.get(&item_def_id).into_iter().flatten().copied()) + })) } _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), } @@ -92,46 +68,33 @@ fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap<DefId> } fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem { - let id = tcx.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(impl_) => { - 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.expect_local(), def_id); - return assoc_item; - } - } - - hir::ItemKind::Trait(.., trait_item_refs) => { - if let Some(trait_item_ref) = - 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.expect_local(), def_id); - return assoc_item; - } - } - - _ => {} - } + let assoc_item = match tcx.hir_node_by_def_id(def_id) { + hir::Node::TraitItem(ti) => associated_item_from_trait_item(tcx, ti), + hir::Node::ImplItem(ii) => associated_item_from_impl_item(tcx, ii), + node => span_bug!(tcx.def_span(def_id), "impl item or item not found: {:?}", node,), + }; + debug_assert_eq!(assoc_item.def_id.expect_local(), def_id); + assoc_item +} - span_bug!( - parent_item.span, - "unexpected parent of trait or impl item or item not found: {:?}", - parent_item.kind - ) +fn fn_has_self_parameter(tcx: TyCtxt<'_>, owner_id: hir::OwnerId) -> bool { + matches!(tcx.fn_arg_idents(owner_id.def_id), [Some(Ident { name: kw::SelfLower, .. }), ..]) } -fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem { - let owner_id = trait_item_ref.id.owner_id; - let name = trait_item_ref.ident.name; - let kind = match trait_item_ref.kind { - hir::AssocItemKind::Const => ty::AssocKind::Const { name }, - hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { name, has_self }, - hir::AssocItemKind::Type => ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) }, +fn associated_item_from_trait_item( + tcx: TyCtxt<'_>, + trait_item: &hir::TraitItem<'_>, +) -> ty::AssocItem { + let owner_id = trait_item.owner_id; + let name = trait_item.ident.name; + let kind = match trait_item.kind { + hir::TraitItemKind::Const { .. } => ty::AssocKind::Const { name }, + hir::TraitItemKind::Fn { .. } => { + ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id) } + } + hir::TraitItemKind::Type { .. } => { + ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) } + } }; ty::AssocItem { @@ -142,30 +105,34 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty } } -fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem { - let def_id = impl_item_ref.id.owner_id; - let name = impl_item_ref.ident.name; - let kind = match impl_item_ref.kind { - hir::AssocItemKind::Const => ty::AssocKind::Const { name }, - hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { name, has_self }, - hir::AssocItemKind::Type => ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) }, +fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) -> ty::AssocItem { + let owner_id = impl_item.owner_id; + let name = impl_item.ident.name; + let kind = match impl_item.kind { + hir::ImplItemKind::Const { .. } => ty::AssocKind::Const { name }, + hir::ImplItemKind::Fn { .. } => { + ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id) } + } + hir::ImplItemKind::Type { .. } => { + ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) } + } }; ty::AssocItem { kind, - def_id: def_id.to_def_id(), - trait_item_def_id: impl_item_ref.trait_item_def_id, + def_id: owner_id.to_def_id(), + trait_item_def_id: impl_item.trait_item_def_id, container: ty::AssocItemContainer::Impl, } } -struct RPITVisitor<'tcx> { +struct RPITVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, synthetics: Vec<LocalDefId>, data: DefPathData, - disambiguator: DisambiguatorState, + disambiguator: &'a mut DisambiguatorState, } -impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for RPITVisitor<'_, 'tcx> { fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) -> Self::Result { self.synthetics.push(associated_type_for_impl_trait_in_trait( self.tcx, @@ -177,86 +144,70 @@ impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> { } } -/// 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 => { - if let Some(output) = tcx.hir_get_fn_output(fn_def_id) { - let def_path_id = |def_id: LocalDefId| tcx.item_name(def_id.to_def_id()); - let def_path_data = def_path_id(fn_def_id); - - let (.., trait_item_refs) = tcx.hir_expect_item(parent_def_id).expect_trait(); - // The purpose of `disambiguator_idx` is to ensure there are - // no duplicate `def_id` in certain cases, such as: - // ``` - // trait Foo { - // fn bar() -> impl Trait; - // fn bar() -> impl Trait; - // // ~~~~~~~~~~ It will generate the same ID if we don’t disambiguate it. - // } - // ``` - let disambiguator_idx = trait_item_refs - .iter() - .take_while(|item| item.id.owner_id.def_id != fn_def_id) - .fold(0, |acc, item| { - if !matches!(item.kind, hir::AssocItemKind::Fn { .. }) { - acc - } else if def_path_id(item.id.owner_id.def_id) == def_path_data { - tcx.def_key(item.id.owner_id.def_id).disambiguated_data.disambiguator - + 1 - } else { - acc - } - }); - - let data = DefPathData::AnonAssocTy(def_path_data); - let mut visitor = RPITVisitor { - tcx, - synthetics: vec![], - data, - disambiguator: DisambiguatorState::with(parent_def_id, data, disambiguator_idx), +fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, +) -> DefIdMap<Vec<DefId>> { + let item = tcx.hir_expect_item(def_id); + let disambiguator = &mut DisambiguatorState::new(); + match item.kind { + ItemKind::Trait(.., trait_item_refs) => trait_item_refs + .iter() + .filter_map(move |item| { + if !matches!(tcx.def_kind(item.owner_id), DefKind::AssocFn) { + return None; + } + let fn_def_id = item.owner_id.def_id; + let Some(output) = tcx.hir_get_fn_output(fn_def_id) else { + return Some((fn_def_id.to_def_id(), vec![])); }; + let def_name = tcx.item_name(fn_def_id.to_def_id()); + let data = DefPathData::AnonAssocTy(def_name); + let mut visitor = RPITVisitor { tcx, synthetics: vec![], data, disambiguator }; visitor.visit_fn_ret_ty(output); - tcx.arena.alloc_from_iter( - visitor.synthetics.into_iter().map(|def_id| def_id.to_def_id()), - ) - } else { - &[] - } - } - - DefKind::Impl { .. } => { - let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else { - return &[]; + let defs = visitor + .synthetics + .into_iter() + .map(|def_id| def_id.to_def_id()) + .collect::<Vec<_>>(); + Some((fn_def_id.to_def_id(), defs)) + }) + .collect(), + ItemKind::Impl(impl_) => { + let Some(trait_ref) = impl_.of_trait else { + return Default::default(); + }; + let Some(trait_def_id) = trait_ref.trait_def_id() else { + return Default::default(); }; - tcx.arena.alloc_from_iter( - 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) + let in_trait_def = tcx.associated_types_for_impl_traits_in_trait_or_impl(trait_def_id); + impl_ + .items + .iter() + .filter_map(|item| { + if !matches!(tcx.def_kind(item.owner_id), DefKind::AssocFn) { + return None; + } + let did = item.owner_id.def_id.to_def_id(); + let item = tcx.hir_impl_item(*item); + let Some(trait_item_def_id) = item.trait_item_def_id else { + return Some((did, vec![])); + }; + let iter = in_trait_def[&trait_item_def_id].iter().map(|&id| { + associated_type_for_impl_trait_in_impl(tcx, id, item, disambiguator) .to_def_id() - }, - ), + }); + Some((did, iter.collect())) + }) + .collect() + } + _ => { + bug!( + "associated_types_for_impl_traits_in_trait_or_impl: {:?} should be Trait or Impl but is {:?}", + def_id, + tcx.def_kind(def_id) ) } - - def_kind => bug!( - "associated_types_for_impl_traits_in_associated_fn: {:?} should be Trait or Impl but is {:?}", - parent_def_id, - def_kind - ), } } @@ -323,19 +274,20 @@ fn associated_type_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 +/// `impl_fn` 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: DefId, - impl_fn_def_id: LocalDefId, + impl_fn: &hir::ImplItem<'_>, + disambiguator: &mut DisambiguatorState, ) -> LocalDefId { - let impl_local_def_id = tcx.local_parent(impl_fn_def_id); + let impl_local_def_id = tcx.local_parent(impl_fn.owner_id.def_id); - let decl = tcx.hir_node_by_def_id(impl_fn_def_id).fn_decl().expect("expected decl"); - let span = match decl.output { - hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id), + let hir::ImplItemKind::Fn(fn_sig, _) = impl_fn.kind else { bug!("expected decl") }; + let span = match fn_sig.decl.output { + hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn.owner_id), hir::FnRetTy::Return(ty) => ty.span, }; @@ -352,7 +304,7 @@ fn associated_type_for_impl_trait_in_impl( None, DefKind::AssocTy, Some(data), - &mut DisambiguatorState::with(impl_local_def_id, data, disambiguated_data.disambiguator), + disambiguator, ); let local_def_id = impl_assoc_ty.def_id(); @@ -366,7 +318,7 @@ fn associated_type_for_impl_trait_in_impl( impl_assoc_ty.associated_item(ty::AssocItem { kind: ty::AssocKind::Type { data: ty::AssocTypeData::Rpitit(ImplTraitInTraitData::Impl { - fn_def_id: impl_fn_def_id.to_def_id(), + fn_def_id: impl_fn.owner_id.to_def_id(), }), }, def_id, @@ -375,10 +327,10 @@ fn associated_type_for_impl_trait_in_impl( }); // Copy visility of the containing function. - impl_assoc_ty.visibility(tcx.visibility(impl_fn_def_id)); + impl_assoc_ty.visibility(tcx.visibility(impl_fn.owner_id)); // Copy defaultness of the containing function. - impl_assoc_ty.defaultness(tcx.defaultness(impl_fn_def_id)); + impl_assoc_ty.defaultness(tcx.defaultness(impl_fn.owner_id)); // Copy generics_of the trait's associated item but the impl as the parent. // FIXME: This may be detrimental to diagnostics, as we resolve the early-bound vars diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index a225b712d4b..163e2b30883 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -379,7 +379,7 @@ fn layout_of_uncached<'tcx>( // Potentially-wide pointers. ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => { - let mut data_ptr = scalar_unit(Pointer(AddressSpace::DATA)); + let mut data_ptr = scalar_unit(Pointer(AddressSpace::ZERO)); if !ty.is_raw_ptr() { data_ptr.valid_range_mut().start = 1; } @@ -435,7 +435,7 @@ fn layout_of_uncached<'tcx>( } ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), ty::Dynamic(..) => { - let mut vtable = scalar_unit(Pointer(AddressSpace::DATA)); + let mut vtable = scalar_unit(Pointer(AddressSpace::ZERO)); vtable.valid_range_mut().start = 1; vtable } diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 3b313edea6f..4a7263d0ccd 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -223,7 +223,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { } // Skips type aliases, as they are meant to be transparent. // FIXME(type_alias_impl_trait): can we require mentioning nested type aliases explicitly? - ty::Alias(ty::Free, alias_ty) if alias_ty.def_id.is_local() => { + ty::Alias(ty::Free, alias_ty) if let Some(def_id) = alias_ty.def_id.as_local() => { + if !self.seen.insert(def_id) { + return; + } self.tcx .type_of(alias_ty.def_id) .instantiate(self.tcx, alias_ty.args) @@ -256,16 +259,16 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { return; } - let impl_args = alias_ty.args.rebase_onto( + let alias_args = alias_ty.args.rebase_onto( self.tcx, impl_trait_ref.def_id, ty::GenericArgs::identity_for_item(self.tcx, parent), ); - if self.tcx.check_args_compatible(assoc.def_id, impl_args) { + if self.tcx.check_args_compatible(assoc.def_id, alias_args) { self.tcx .type_of(assoc.def_id) - .instantiate(self.tcx, impl_args) + .instantiate(self.tcx, alias_args) .visit_with(self); return; } else { | 
