Skip to content

Commit 000243c

Browse files
Add a fast path to inherent impl overlap check
Quickly skip impls that do not define any items with the same name
1 parent 7d1ac19 commit 000243c

File tree

1 file changed

+46
-20
lines changed

1 file changed

+46
-20
lines changed

src/librustc_typeck/coherence/inherent_impls_overlap.rs

+46-20
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,30 @@ struct InherentOverlapChecker<'tcx> {
1717
}
1818

1919
impl InherentOverlapChecker<'tcx> {
20+
/// Checks whether any associated items in impls 1 and 2 share the same identifier and
21+
/// namespace.
22+
fn impls_have_common_items(&self, impl1: DefId, impl2: DefId) -> bool {
23+
let impl_items1 = self.tcx.associated_items(impl1);
24+
let impl_items2 = self.tcx.associated_items(impl2);
25+
26+
for item1 in &impl_items1[..] {
27+
for item2 in &impl_items2[..] {
28+
// Avoid costly `.modern()` calls as much as possible by doing them as late as we
29+
// can. Compare raw symbols first.
30+
if item1.ident.name == item2.ident.name
31+
&& Namespace::from(item1.kind) == Namespace::from(item2.kind)
32+
{
33+
// Symbols and namespace match, compare hygienically.
34+
if item1.ident.modern() == item2.ident.modern() {
35+
return true;
36+
}
37+
}
38+
}
39+
}
40+
41+
false
42+
}
43+
2044
fn check_for_common_items_in_impls(
2145
&self,
2246
impl1: DefId,
@@ -64,24 +88,18 @@ impl InherentOverlapChecker<'tcx> {
6488
}
6589
}
6690

67-
fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
68-
let impls = self.tcx.inherent_impls(ty_def_id);
69-
70-
for (i, &impl1_def_id) in impls.iter().enumerate() {
71-
for &impl2_def_id in &impls[(i + 1)..] {
72-
traits::overlapping_impls(
73-
self.tcx,
74-
impl1_def_id,
75-
impl2_def_id,
76-
IntercrateMode::Issue43355,
77-
|overlap| {
78-
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
79-
false
80-
},
81-
|| true,
82-
);
83-
}
84-
}
91+
fn check_for_overlapping_inherent_impls(&self, impl1_def_id: DefId, impl2_def_id: DefId) {
92+
traits::overlapping_impls(
93+
self.tcx,
94+
impl1_def_id,
95+
impl2_def_id,
96+
IntercrateMode::Issue43355,
97+
|overlap| {
98+
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
99+
false
100+
},
101+
|| true,
102+
);
85103
}
86104
}
87105

@@ -92,8 +110,16 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
92110
| hir::ItemKind::Struct(..)
93111
| hir::ItemKind::Trait(..)
94112
| hir::ItemKind::Union(..) => {
95-
let type_def_id = self.tcx.hir().local_def_id(item.hir_id);
96-
self.check_for_overlapping_inherent_impls(type_def_id);
113+
let ty_def_id = self.tcx.hir().local_def_id(item.hir_id);
114+
let impls = self.tcx.inherent_impls(ty_def_id);
115+
116+
for (i, &impl1_def_id) in impls.iter().enumerate() {
117+
for &impl2_def_id in &impls[(i + 1)..] {
118+
if self.impls_have_common_items(impl1_def_id, impl2_def_id) {
119+
self.check_for_overlapping_inherent_impls(impl1_def_id, impl2_def_id);
120+
}
121+
}
122+
}
97123
}
98124
_ => {}
99125
}

0 commit comments

Comments
 (0)