diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 10dc407c060..9fb4e08e284 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -78,7 +78,8 @@ /// Trait impl data. /// FIXME: Used only from queries and can use query cache, /// so pre-decoding can probably be avoided. - trait_impls: FxHashMap<(u32, DefIndex), Lazy<[DefIndex]>>, + trait_impls: + FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option)]>>, /// Proc macro descriptions for this crate, if it's a proc macro crate. raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. @@ -1289,7 +1290,7 @@ fn get_implementations_for_trait( &self, tcx: TyCtxt<'tcx>, filter: Option, - ) -> &'tcx [DefId] { + ) -> &'tcx [(DefId, Option)] { if self.root.is_proc_macro_crate() { // proc-macro crates export no trait impls. return &[]; @@ -1305,16 +1306,20 @@ fn get_implementations_for_trait( if let Some(filter) = filter { if let Some(impls) = self.trait_impls.get(&filter) { - tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx))) + tcx.arena.alloc_from_iter( + impls.decode(self).map(|(idx, simplified_self_ty)| { + (self.local_def_id(idx), simplified_self_ty) + }), + ) } else { &[] } } else { - tcx.arena.alloc_from_iter( - self.trait_impls - .values() - .flat_map(|impls| impls.decode(self).map(|idx| self.local_def_id(idx))), - ) + tcx.arena.alloc_from_iter(self.trait_impls.values().flat_map(|impls| { + impls + .decode(self) + .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)) + })) } } diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index aec9e8daa0f..acae44e6bf7 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1610,7 +1610,7 @@ fn encode_impls(&mut self) -> Lazy<[TraitImpls]> { .into_iter() .map(|(trait_def_id, mut impls)| { // Bring everything into deterministic order for hashing - impls.sort_by_cached_key(|&index| { + impls.sort_by_cached_key(|&(index, _)| { tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index }) }); @@ -1852,7 +1852,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item<'_>) { struct ImplVisitor<'tcx> { tcx: TyCtxt<'tcx>, - impls: FxHashMap>, + impls: FxHashMap)>>, } impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { @@ -1860,7 +1860,13 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { if let hir::ItemKind::Impl { .. } = item.kind { let impl_id = self.tcx.hir().local_def_id(item.hir_id); if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id.to_def_id()) { - self.impls.entry(trait_ref.def_id).or_default().push(impl_id.local_def_index); + let simplified_self_ty = + ty::fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), false); + + self.impls + .entry(trait_ref.def_id) + .or_default() + .push((impl_id.local_def_index, simplified_self_ty)); } } } diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 465461ebf97..1c287be9f6b 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -233,7 +233,7 @@ macro_rules! Lazy { #[derive(RustcEncodable, RustcDecodable)] crate struct TraitImpls { trait_id: (u32, DefIndex), - impls: Lazy<[DefIndex]>, + impls: Lazy<[(DefIndex, Option)]>, } /// Define `LazyTables` and `TableBuilders` at the same time. diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index 7e9226f83c3..a8f6723a356 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -1125,11 +1125,11 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String { TypeChecking { query implementations_of_trait(_: (CrateNum, DefId)) - -> &'tcx [DefId] { + -> &'tcx [(DefId, Option)] { desc { "looking up implementations of a trait in a crate" } } query all_trait_implementations(_: CrateNum) - -> &'tcx [DefId] { + -> &'tcx [(DefId, Option)] { desc { "looking up all (?) trait implementations" } } } diff --git a/src/librustc_middle/ty/trait_def.rs b/src/librustc_middle/ty/trait_def.rs index 8f125098ee6..f93cce3f4da 100644 --- a/src/librustc_middle/ty/trait_def.rs +++ b/src/librustc_middle/ty/trait_def.rs @@ -187,32 +187,38 @@ pub(super) fn all_local_trait_impls<'tcx>( pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> TraitImpls { let mut impls = TraitImpls::default(); - { - let mut add_impl = |impl_def_id: DefId| { - let impl_self_ty = tcx.type_of(impl_def_id); - if impl_def_id.is_local() && impl_self_ty.references_error() { - return; - } - - if let Some(simplified_self_ty) = fast_reject::simplify_type(tcx, impl_self_ty, false) { - impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); - } else { - impls.blanket_impls.push(impl_def_id); - } - }; - - // Traits defined in the current crate can't have impls in upstream - // crates, so we don't bother querying the cstore. - if !trait_id.is_local() { - for &cnum in tcx.crates().iter() { - for &def_id in tcx.implementations_of_trait((cnum, trait_id)).iter() { - add_impl(def_id); + // Traits defined in the current crate can't have impls in upstream + // crates, so we don't bother querying the cstore. + if !trait_id.is_local() { + for &cnum in tcx.crates().iter() { + for &(impl_def_id, simplified_self_ty) in + tcx.implementations_of_trait((cnum, trait_id)).iter() + { + if let Some(simplified_self_ty) = simplified_self_ty { + impls + .non_blanket_impls + .entry(simplified_self_ty) + .or_default() + .push(impl_def_id); + } else { + impls.blanket_impls.push(impl_def_id); } } } + } - for &hir_id in tcx.hir().trait_impls(trait_id) { - add_impl(tcx.hir().local_def_id(hir_id).to_def_id()); + for &hir_id in tcx.hir().trait_impls(trait_id) { + let impl_def_id = tcx.hir().local_def_id(hir_id).to_def_id(); + + let impl_self_ty = tcx.type_of(impl_def_id); + if impl_self_ty.references_error() { + continue; + } + + if let Some(simplified_self_ty) = fast_reject::simplify_type(tcx, impl_self_ty, false) { + impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); + } else { + impls.blanket_impls.push(impl_def_id); } } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 0fdeefd79e9..3000afde0c2 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -28,7 +28,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { let mut new_items = Vec::new(); for &cnum in cx.tcx.crates().iter() { - for &did in cx.tcx.all_trait_implementations(cnum).iter() { + for &(did, _) in cx.tcx.all_trait_implementations(cnum).iter() { inline::build_impl(cx, did, None, &mut new_items); } }