Skip to content

Commit 73a7d93

Browse files
committed
Add tests
1 parent 7208a01 commit 73a7d93

File tree

5 files changed

+208
-1
lines changed

5 files changed

+208
-1
lines changed

compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
140140
// Perform a O(n^2) algorithm for small n,
141141
// otherwise switch to an allocating algorithm with
142142
// faster asymptotic runtime.
143-
if impls.len() < 30 {
143+
const ALLOCATING_ALGO_THRESHOLD: usize = 500;
144+
if impls.len() < ALLOCATING_ALGO_THRESHOLD {
144145
for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() {
145146
for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
146147
if self.impls_have_common_items(impl_items1, impl_items2) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// force-host
2+
// no-prefer-dynamic
3+
4+
#![crate_type = "proc-macro"]
5+
6+
extern crate proc_macro;
7+
use proc_macro::{Ident, Group, TokenStream, TokenTree as Tt};
8+
9+
// This constant has to be above the ALLOCATING_ALGO_THRESHOLD
10+
// constant in inherent_impls_overlap.rs
11+
const REPEAT_COUNT: u32 = 501;
12+
13+
#[proc_macro]
14+
/// Repeats the input many times, while replacing idents
15+
/// named "IDENT" with "id_$v", where v is a counter.
16+
pub fn repeat_with_idents(input: TokenStream) -> TokenStream {
17+
let mut res = Vec::new();
18+
fn visit_stream(res: &mut Vec<Tt>, stream :TokenStream, v: u32) {
19+
let mut stream_iter = stream.into_iter();
20+
while let Some(tt) = stream_iter.next() {
21+
match tt {
22+
Tt::Group(group) => {
23+
let tt = Tt::Group(visit_group(group, v));
24+
res.push(tt);
25+
},
26+
Tt::Ident(id) => {
27+
let id = if &id.to_string() == "IDENT" {
28+
Ident::new(&format!("id_{}", v), id.span())
29+
} else {
30+
id
31+
};
32+
res.push(Tt::Ident(id));
33+
},
34+
Tt::Punct(p) => {
35+
res.push(Tt::Punct(p));
36+
},
37+
Tt::Literal(lit) => {
38+
res.push(Tt::Literal(lit));
39+
},
40+
}
41+
}
42+
}
43+
fn visit_group(group :Group, v: u32) -> Group {
44+
let mut res = Vec::new();
45+
visit_stream(&mut res, group.stream(), v);
46+
let stream = res.into_iter().collect();
47+
let delim = group.delimiter();
48+
Group::new(delim, stream)
49+
}
50+
for v in 0 .. REPEAT_COUNT {
51+
visit_stream(&mut res, input.clone(), v)
52+
}
53+
res.into_iter().collect()
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// run-pass
2+
// aux-build:repeat.rs
3+
4+
// This tests the allocating algo branch of the
5+
// inherent impls overlap checker.
6+
// This branch was added by PR:
7+
// https://github.com/rust-lang/rust/pull/78317
8+
// In this test, we repeat many impl blocks
9+
// to trigger the allocating branch.
10+
11+
#![allow(unused)]
12+
13+
extern crate repeat;
14+
15+
// Simple case where each impl block is distinct
16+
17+
struct Foo {}
18+
19+
repeat::repeat_with_idents!(impl Foo { fn IDENT() {} });
20+
21+
// There are overlapping impl blocks but due to generics,
22+
// they may overlap.
23+
24+
struct Bar<T>(T);
25+
26+
struct A;
27+
struct B;
28+
29+
repeat::repeat_with_idents!(impl Bar<A> { fn IDENT() {} });
30+
31+
impl Bar<A> { fn foo() {} }
32+
impl Bar<B> { fn foo() {} }
33+
34+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// aux-build:repeat.rs
2+
3+
#![allow(unused)]
4+
5+
// This tests the allocating algo branch of the
6+
// inherent impls overlap checker.
7+
// This branch was added by PR:
8+
// https://github.com/rust-lang/rust/pull/78317
9+
// In this test, we repeat many impl blocks
10+
// to trigger the allocating branch.
11+
12+
// Simple overlap
13+
14+
extern crate repeat;
15+
16+
struct Foo {}
17+
18+
repeat::repeat_with_idents!(impl Foo { fn IDENT() {} });
19+
20+
impl Foo { fn hello() {} } //~ERROR duplicate definitions with name `hello`
21+
impl Foo { fn hello() {} }
22+
23+
// Transitive overlap
24+
25+
struct Foo2 {}
26+
27+
repeat::repeat_with_idents!(impl Foo2 { fn IDENT() {} });
28+
29+
impl Foo2 {
30+
fn bar() {}
31+
fn hello2() {} //~ERROR duplicate definitions with name `hello2`
32+
}
33+
34+
impl Foo2 {
35+
fn baz() {}
36+
fn hello2() {}
37+
}
38+
39+
// Slightly stronger transitive overlap
40+
41+
struct Foo3 {}
42+
43+
repeat::repeat_with_idents!(impl Foo3 { fn IDENT() {} });
44+
45+
impl Foo3 {
46+
fn bar() {} //~ERROR duplicate definitions with name `bar`
47+
fn hello3() {} //~ERROR duplicate definitions with name `hello3`
48+
}
49+
50+
impl Foo3 {
51+
fn bar() {}
52+
fn hello3() {}
53+
}
54+
55+
// Generic overlap
56+
57+
struct Bar<T>(T);
58+
59+
struct A;
60+
struct B;
61+
62+
repeat::repeat_with_idents!(impl Bar<A> { fn IDENT() {} });
63+
64+
impl Bar<A> { fn foo() {} fn bar2() {} }
65+
impl Bar<B> {
66+
fn foo() {}
67+
fn bar2() {} //~ERROR duplicate definitions with name `bar2`
68+
}
69+
impl Bar<B> { fn bar2() {} }
70+
71+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
error[E0592]: duplicate definitions with name `hello`
2+
--> $DIR/overlap.rs:20:12
3+
|
4+
LL | impl Foo { fn hello() {} }
5+
| ^^^^^^^^^^ duplicate definitions for `hello`
6+
LL | impl Foo { fn hello() {} }
7+
| ---------- other definition for `hello`
8+
9+
error[E0592]: duplicate definitions with name `hello2`
10+
--> $DIR/overlap.rs:31:5
11+
|
12+
LL | fn hello2() {}
13+
| ^^^^^^^^^^^ duplicate definitions for `hello2`
14+
...
15+
LL | fn hello2() {}
16+
| ----------- other definition for `hello2`
17+
18+
error[E0592]: duplicate definitions with name `bar`
19+
--> $DIR/overlap.rs:46:5
20+
|
21+
LL | fn bar() {}
22+
| ^^^^^^^^ duplicate definitions for `bar`
23+
...
24+
LL | fn bar() {}
25+
| -------- other definition for `bar`
26+
27+
error[E0592]: duplicate definitions with name `hello3`
28+
--> $DIR/overlap.rs:47:5
29+
|
30+
LL | fn hello3() {}
31+
| ^^^^^^^^^^^ duplicate definitions for `hello3`
32+
...
33+
LL | fn hello3() {}
34+
| ----------- other definition for `hello3`
35+
36+
error[E0592]: duplicate definitions with name `bar2`
37+
--> $DIR/overlap.rs:67:5
38+
|
39+
LL | fn bar2() {}
40+
| ^^^^^^^^^ duplicate definitions for `bar2`
41+
LL | }
42+
LL | impl Bar<B> { fn bar2() {} }
43+
| --------- other definition for `bar2`
44+
45+
error: aborting due to 5 previous errors
46+
47+
For more information about this error, try `rustc --explain E0592`.

0 commit comments

Comments
 (0)