diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index dede1b2122a3c..466da175810d5 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -223,6 +223,15 @@ provide! { tcx, def_id, other, cdata, fn_arg_names => { table } generator_kind => { table } trait_def => { table } + collect_trait_impl_trait_tys => { + Ok(cdata + .root + .tables + .trait_impl_trait_tys + .get(cdata, def_id.index) + .map(|lazy| lazy.decode((cdata, tcx))) + .process_decoded(tcx, || panic!("{:?} does not have trait_impl_trait_tys", def_id))) + } visibility => { cdata.get_visibility(def_id.index) } adt_def => { cdata.get_adt_def(def_id.index, tcx) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 67c28461ce5cf..734e9a31bb90c 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1059,6 +1059,34 @@ fn should_encode_const(def_kind: DefKind) -> bool { } } +fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { + if tcx.def_kind(def_id) != DefKind::AssocFn { + return false; + } + + let Some(item) = tcx.opt_associated_item(def_id) else { return false; }; + if item.container != ty::AssocItemContainer::ImplContainer { + return false; + } + + let Some(trait_item_def_id) = item.trait_item_def_id else { return false; }; + + // FIXME(RPITIT): This does a somewhat manual walk through the signature + // of the trait fn to look for any RPITITs, but that's kinda doing a lot + // of work. We can probably remove this when we refactor RPITITs to be + // associated types. + tcx.fn_sig(trait_item_def_id).skip_binder().output().walk().any(|arg| { + if let ty::GenericArgKind::Type(ty) = arg.unpack() + && let ty::Projection(data) = ty.kind() + && tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder + { + true + } else { + false + } + }) +} + impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_attrs(&mut self, def_id: LocalDefId) { let mut attrs = self @@ -1128,6 +1156,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::Trait | DefKind::TraitAlias = def_kind { record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id)); } + if should_encode_trait_impl_trait_tys(tcx, def_id) + && let Ok(table) = self.tcx.collect_trait_impl_trait_tys(def_id) + { + record!(self.tables.trait_impl_trait_tys[def_id] <- table); + } } let inherent_impls = tcx.crate_inherent_impls(()); for (def_id, implementations) in inherent_impls.inherent_impls.iter() { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 748b3afec37c7..6d7345570af85 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -1,6 +1,7 @@ use crate::creader::CrateMetadataRef; use decoder::Metadata; use def_path_hash_map::DefPathHashMapRef; +use rustc_data_structures::fx::FxHashMap; use table::TableBuilder; use rustc_ast as ast; @@ -399,6 +400,8 @@ define_tables! { macro_definition: Table>, proc_macro: Table, module_reexports: Table>, + + trait_impl_trait_tys: Table>>>, } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 9c8dc30e2db3f..0257ca7b29c71 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -1,3 +1,4 @@ +use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{DefId, DefIndex}; use rustc_index::vec::{Idx, IndexVec}; @@ -29,6 +30,10 @@ impl ParameterizedOverTcx for IndexVe type Value<'tcx> = IndexVec>; } +impl ParameterizedOverTcx for FxHashMap { + type Value<'tcx> = FxHashMap>; +} + impl ParameterizedOverTcx for ty::Binder<'static, T> { type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>; } diff --git a/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs new file mode 100644 index 0000000000000..74df300f85a6b --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs @@ -0,0 +1,11 @@ +#![feature(return_position_impl_trait_in_trait)] + +pub trait Foo { + fn bar() -> impl Sized; +} + +pub struct Foreign; + +impl Foo for Foreign { + fn bar() {} +} diff --git a/src/test/ui/impl-trait/in-trait/foreign.rs b/src/test/ui/impl-trait/in-trait/foreign.rs new file mode 100644 index 0000000000000..6341f5b428429 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/foreign.rs @@ -0,0 +1,9 @@ +// check-pass +// aux-build: rpitit.rs + +extern crate rpitit; + +fn main() { + // Witness an RPITIT from another crate + let () = ::bar(); +}