Skip to content

Commit 83055d7

Browse files
committed
Auto merge of rust-lang#120835 - oli-obk:no_hir_coherence, r=<try>
Avoid accessing the HIR in the happy path of `coherent_trait` based on rust-lang#120834 This may resolve part of the performance issue of rust-lang#120558
2 parents 98aa362 + d8fa0d5 commit 83055d7

File tree

3 files changed

+33
-27
lines changed

3 files changed

+33
-27
lines changed

compiler/rustc_hir_analysis/src/coherence/builtin.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,13 @@ use rustc_trait_selection::traits::ObligationCtxt;
2525
use rustc_trait_selection::traits::{self, ObligationCause};
2626
use std::collections::BTreeMap;
2727

28-
pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Result<(), ErrorGuaranteed> {
28+
pub fn check_trait(
29+
tcx: TyCtxt<'_>,
30+
trait_def_id: DefId,
31+
impl_def_id: LocalDefId,
32+
) -> Result<(), ErrorGuaranteed> {
2933
let lang_items = tcx.lang_items();
30-
let checker = Checker { tcx, trait_def_id };
34+
let checker = Checker { tcx, trait_def_id, impl_def_id };
3135
let mut res = checker.check(lang_items.drop_trait(), visit_implementation_of_drop);
3236
res = res.and(checker.check(lang_items.copy_trait(), visit_implementation_of_copy));
3337
res = res.and(
@@ -45,6 +49,7 @@ pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Result<(), ErrorGuar
4549
struct Checker<'tcx> {
4650
tcx: TyCtxt<'tcx>,
4751
trait_def_id: DefId,
52+
impl_def_id: LocalDefId,
4853
}
4954

5055
impl<'tcx> Checker<'tcx> {
@@ -54,9 +59,7 @@ impl<'tcx> Checker<'tcx> {
5459
{
5560
let mut res = Ok(());
5661
if Some(self.trait_def_id) == trait_def_id {
57-
for &impl_def_id in self.tcx.hir().trait_impls(self.trait_def_id) {
58-
res = res.and(f(self.tcx, impl_def_id));
59-
}
62+
res = res.and(f(self.tcx, self.impl_def_id));
6063
}
6164
res
6265
}
@@ -92,10 +95,10 @@ fn visit_implementation_of_copy(
9295

9396
debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
9497

95-
let span = match tcx.hir().expect_item(impl_did).expect_impl() {
96-
hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return Ok(()),
97-
hir::Impl { self_ty, .. } => self_ty.span,
98-
};
98+
if let ty::ImplPolarity::Negative = tcx.impl_polarity(impl_did) {
99+
return Ok(());
100+
}
101+
let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
99102

100103
let cause = traits::ObligationCause::misc(span, impl_did);
101104
match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) {
@@ -121,10 +124,10 @@ fn visit_implementation_of_const_param_ty(
121124

122125
let param_env = tcx.param_env(impl_did);
123126

124-
let span = match tcx.hir().expect_item(impl_did).expect_impl() {
125-
hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return Ok(()),
126-
impl_ => impl_.self_ty.span,
127-
};
127+
if let ty::ImplPolarity::Negative = tcx.impl_polarity(impl_did) {
128+
return Ok(());
129+
}
130+
let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
128131

129132
let cause = traits::ObligationCause::misc(span, impl_did);
130133
match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {

compiler/rustc_hir_analysis/src/coherence/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,13 @@ pub fn provide(providers: &mut Providers) {
120120
}
121121

122122
fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> {
123+
// If there are no impls for the trait, then "all impls" are trivially coherent and we won't check anything
124+
// anyway. Thus we bail out even before the specialization graph, avoiding the dep_graph edge.
125+
let Some(impls) = tcx.all_local_trait_impls(()).get(&def_id) else { return Ok(()) };
123126
// Trigger building the specialization graph for the trait. This will detect and report any
124127
// overlap errors.
125128
let mut res = tcx.ensure().specialization_graph_of(def_id);
126129

127-
let impls = tcx.hir().trait_impls(def_id);
128130
for &impl_def_id in impls {
129131
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
130132

@@ -133,9 +135,10 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed>
133135

134136
res = res.and(unsafety::check_item(tcx, impl_def_id));
135137
res = res.and(tcx.ensure().orphan_check_impl(impl_def_id));
138+
res = res.and(builtin::check_trait(tcx, def_id, impl_def_id));
136139
}
137140

138-
res.and(builtin::check_trait(tcx, def_id))
141+
res
139142
}
140143

141144
/// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`.

tests/ui/coherence/coherence-impls-copy.stderr

+12-12
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ LL | impl Copy for &'static [NotSync] {}
3030
|
3131
= note: define and implement a trait or new type instead
3232

33+
error[E0206]: the trait `Copy` cannot be implemented for this type
34+
--> $DIR/coherence-impls-copy.rs:21:15
35+
|
36+
LL | impl Copy for &'static mut MyType {}
37+
| ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
38+
3339
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
3440
--> $DIR/coherence-impls-copy.rs:25:1
3541
|
@@ -41,6 +47,12 @@ LL | impl Copy for (MyType, MyType) {}
4147
|
4248
= note: define and implement a trait or new type instead
4349

50+
error[E0206]: the trait `Copy` cannot be implemented for this type
51+
--> $DIR/coherence-impls-copy.rs:25:15
52+
|
53+
LL | impl Copy for (MyType, MyType) {}
54+
| ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
55+
4456
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
4557
--> $DIR/coherence-impls-copy.rs:30:1
4658
|
@@ -52,18 +64,6 @@ LL | impl Copy for [MyType] {}
5264
|
5365
= note: define and implement a trait or new type instead
5466

55-
error[E0206]: the trait `Copy` cannot be implemented for this type
56-
--> $DIR/coherence-impls-copy.rs:21:15
57-
|
58-
LL | impl Copy for &'static mut MyType {}
59-
| ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
60-
61-
error[E0206]: the trait `Copy` cannot be implemented for this type
62-
--> $DIR/coherence-impls-copy.rs:25:15
63-
|
64-
LL | impl Copy for (MyType, MyType) {}
65-
| ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
66-
6767
error[E0206]: the trait `Copy` cannot be implemented for this type
6868
--> $DIR/coherence-impls-copy.rs:30:15
6969
|

0 commit comments

Comments
 (0)