Skip to content

Commit 52f7711

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 f416573 commit 52f7711

File tree

1 file changed

+49
-23
lines changed

1 file changed

+49
-23
lines changed

src/librustc_typeck/coherence/inherent_impls_overlap.rs

+49-23
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,27 +88,21 @@ 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-
// We go ahead and just skip the leak check for
78-
// inherent impls without warning.
79-
SkipLeakCheck::Yes,
80-
|overlap| {
81-
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
82-
false
83-
},
84-
|| true,
85-
);
86-
}
87-
}
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+
// We go ahead and just skip the leak check for
98+
// inherent impls without warning.
99+
SkipLeakCheck::Yes,
100+
|overlap| {
101+
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
102+
false
103+
},
104+
|| true,
105+
);
88106
}
89107
}
90108

@@ -95,8 +113,16 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
95113
| hir::ItemKind::Struct(..)
96114
| hir::ItemKind::Trait(..)
97115
| hir::ItemKind::Union(..) => {
98-
let type_def_id = self.tcx.hir().local_def_id(item.hir_id);
99-
self.check_for_overlapping_inherent_impls(type_def_id);
116+
let ty_def_id = self.tcx.hir().local_def_id(item.hir_id);
117+
let impls = self.tcx.inherent_impls(ty_def_id);
118+
119+
for (i, &impl1_def_id) in impls.iter().enumerate() {
120+
for &impl2_def_id in &impls[(i + 1)..] {
121+
if self.impls_have_common_items(impl1_def_id, impl2_def_id) {
122+
self.check_for_overlapping_inherent_impls(impl1_def_id, impl2_def_id);
123+
}
124+
}
125+
}
100126
}
101127
_ => {}
102128
}

0 commit comments

Comments
 (0)