1
Fork 0

Decouple trait impls of different traits wrt incremental

This commit is contained in:
Oli Scherer 2025-03-27 11:48:06 +00:00
parent 97ea17b71a
commit a7b687c26e
5 changed files with 14 additions and 6 deletions

View file

@ -153,9 +153,12 @@ pub(crate) fn provide(providers: &mut Providers) {
} }
fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> { fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> {
let impls = tcx.local_trait_impls(def_id);
// If there are no impls for the trait, then "all impls" are trivially coherent and we won't check anything // If there are no impls for the trait, then "all impls" are trivially coherent and we won't check anything
// anyway. Thus we bail out even before the specialization graph, avoiding the dep_graph edge. // anyway. Thus we bail out even before the specialization graph, avoiding the dep_graph edge.
let Some(impls) = tcx.all_local_trait_impls(()).get(&def_id) else { return Ok(()) }; if impls.is_empty() {
return Ok(());
}
// Trigger building the specialization graph for the trait. This will detect and report any // Trigger building the specialization graph for the trait. This will detect and report any
// overlap errors. // overlap errors.
let mut res = tcx.ensure_ok().specialization_graph_of(def_id); let mut res = tcx.ensure_ok().specialization_graph_of(def_id);

View file

@ -368,7 +368,7 @@ impl<'tcx> TyCtxt<'tcx> {
} }
pub fn hir_trait_impls(self, trait_did: DefId) -> &'tcx [LocalDefId] { pub fn hir_trait_impls(self, trait_did: DefId) -> &'tcx [LocalDefId] {
self.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..]) self.local_trait_impls(trait_did)
} }
/// Gets the attributes on the crate. This is preferable to /// Gets the attributes on the crate. This is preferable to

View file

@ -238,6 +238,8 @@ pub fn provide(providers: &mut Providers) {
} }
}; };
providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls; providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
providers.local_trait_impls =
|tcx, trait_id| tcx.resolutions(()).trait_impls.get(&trait_id).map_or(&[], |xs| &xs[..]);
providers.expn_that_defined = providers.expn_that_defined =
|tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root()); |tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root());
providers.in_scope_traits_map = |tcx, id| { providers.in_scope_traits_map = |tcx, id| {

View file

@ -1502,6 +1502,11 @@ rustc_queries! {
desc { "finding local trait impls" } desc { "finding local trait impls" }
} }
/// Return all `impl` blocks of the given trait in the current crate.
query local_trait_impls(trait_id: DefId) -> &'tcx [LocalDefId] {
desc { "finding local trait impls of `{}`", tcx.def_path_str(trait_id) }
}
/// Given a trait `trait_id`, return all known `impl` blocks. /// Given a trait `trait_id`, return all known `impl` blocks.
query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls { query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls {
arena_cache arena_cache

View file

@ -324,11 +324,9 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
// there's a Copy impl for any instance of the adt. // there's a Copy impl for any instance of the adt.
if !is_copy(cx, ty) { if !is_copy(cx, ty) {
if ty_subs.non_erasable_generics().next().is_some() { if ty_subs.non_erasable_generics().next().is_some() {
let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(&copy_id).is_some_and(|impls| { let has_copy_impl = cx.tcx.local_trait_impls(copy_id).iter().any(|&id| {
impls.iter().any(|&id| { matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)
matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)
if ty_adt.did() == adt.did()) if ty_adt.did() == adt.did())
})
}); });
if !has_copy_impl { if !has_copy_impl {
return; return;