diff options
Diffstat (limited to 'compiler/rustc_hir_analysis')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/collect/generics_of.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/collect/type_of.rs | 39 |
2 files changed, 61 insertions, 15 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 9cc6c16c126..c86788db988 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -14,6 +14,43 @@ use rustc_span::Span; pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { use rustc_hir::*; + // For an RPITIT, synthesize generics which are equal to the opaque's generics + // and parent fn's generics compressed into one list. + if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) = + tcx.opt_rpitit_info(def_id.to_def_id()) + { + let trait_def_id = tcx.parent(fn_def_id); + let opaque_ty_generics = tcx.generics_of(opaque_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(); + + return ty::Generics { + parent: Some(trait_def_id), + parent_count, + params, + param_def_id_to_index, + has_self: opaque_ty_generics.has_self, + has_late_bound_regions: opaque_ty_generics.has_late_bound_regions, + host_effect_index: parent_generics.host_effect_index, + }; + } + let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 417f0fceaa8..2217e5280a7 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -5,7 +5,7 @@ use rustc_hir::HirId; use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -350,22 +350,31 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty // If we are computing `type_of` the synthesized associated type for an RPITIT in the impl // side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the // associated type in the impl. - if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = - tcx.opt_rpitit_info(def_id.to_def_id()) - { - match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) { - Ok(map) => { - let assoc_item = tcx.associated_item(def_id); - return map[&assoc_item.trait_item_def_id.unwrap()]; - } - Err(_) => { - return ty::EarlyBinder::bind(Ty::new_error_with_message( - tcx, - DUMMY_SP, - "Could not collect return position impl trait in trait tys", - )); + match tcx.opt_rpitit_info(def_id.to_def_id()) { + Some(ty::ImplTraitInTraitData::Impl { fn_def_id }) => { + match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) { + Ok(map) => { + let assoc_item = tcx.associated_item(def_id); + return map[&assoc_item.trait_item_def_id.unwrap()]; + } + Err(_) => { + return ty::EarlyBinder::bind(Ty::new_error_with_message( + tcx, + DUMMY_SP, + "Could not collect return position impl trait in trait tys", + )); + } } } + // For an RPITIT in a trait, just return the corresponding opaque. + Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { + return ty::EarlyBinder::bind(Ty::new_opaque( + tcx, + opaque_def_id, + ty::GenericArgs::identity_for_item(tcx, opaque_def_id), + )); + } + None => {} } let hir_id = tcx.local_def_id_to_hir_id(def_id); |
