Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
est31 committed Dec 7, 2020
1 parent 7208a01 commit 73a7d93
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
// Perform a O(n^2) algorithm for small n,
// otherwise switch to an allocating algorithm with
// faster asymptotic runtime.
if impls.len() < 30 {
const ALLOCATING_ALGO_THRESHOLD: usize = 500;
if impls.len() < ALLOCATING_ALGO_THRESHOLD {
for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() {
for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
if self.impls_have_common_items(impl_items1, impl_items2) {
Expand Down
54 changes: 54 additions & 0 deletions src/test/ui/inherent-impls-overlap-check/auxiliary/repeat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// force-host
// no-prefer-dynamic

#![crate_type = "proc-macro"]

extern crate proc_macro;
use proc_macro::{Ident, Group, TokenStream, TokenTree as Tt};

// This constant has to be above the ALLOCATING_ALGO_THRESHOLD
// constant in inherent_impls_overlap.rs
const REPEAT_COUNT: u32 = 501;

#[proc_macro]
/// Repeats the input many times, while replacing idents
/// named "IDENT" with "id_$v", where v is a counter.
pub fn repeat_with_idents(input: TokenStream) -> TokenStream {
let mut res = Vec::new();
fn visit_stream(res: &mut Vec<Tt>, stream :TokenStream, v: u32) {
let mut stream_iter = stream.into_iter();
while let Some(tt) = stream_iter.next() {
match tt {
Tt::Group(group) => {
let tt = Tt::Group(visit_group(group, v));
res.push(tt);
},
Tt::Ident(id) => {
let id = if &id.to_string() == "IDENT" {
Ident::new(&format!("id_{}", v), id.span())
} else {
id
};
res.push(Tt::Ident(id));
},
Tt::Punct(p) => {
res.push(Tt::Punct(p));
},
Tt::Literal(lit) => {
res.push(Tt::Literal(lit));
},
}
}
}
fn visit_group(group :Group, v: u32) -> Group {
let mut res = Vec::new();
visit_stream(&mut res, group.stream(), v);
let stream = res.into_iter().collect();
let delim = group.delimiter();
Group::new(delim, stream)
}
for v in 0 .. REPEAT_COUNT {
visit_stream(&mut res, input.clone(), v)
}
res.into_iter().collect()
}
34 changes: 34 additions & 0 deletions src/test/ui/inherent-impls-overlap-check/no-overlap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// run-pass
// aux-build:repeat.rs

// This tests the allocating algo branch of the
// inherent impls overlap checker.
// This branch was added by PR:
// https://github.com/rust-lang/rust/pull/78317
// In this test, we repeat many impl blocks
// to trigger the allocating branch.

#![allow(unused)]

extern crate repeat;

// Simple case where each impl block is distinct

struct Foo {}

repeat::repeat_with_idents!(impl Foo { fn IDENT() {} });

// There are overlapping impl blocks but due to generics,
// they may overlap.

struct Bar<T>(T);

struct A;
struct B;

repeat::repeat_with_idents!(impl Bar<A> { fn IDENT() {} });

impl Bar<A> { fn foo() {} }
impl Bar<B> { fn foo() {} }

fn main() {}
71 changes: 71 additions & 0 deletions src/test/ui/inherent-impls-overlap-check/overlap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// aux-build:repeat.rs

#![allow(unused)]

// This tests the allocating algo branch of the
// inherent impls overlap checker.
// This branch was added by PR:
// https://github.com/rust-lang/rust/pull/78317
// In this test, we repeat many impl blocks
// to trigger the allocating branch.

// Simple overlap

extern crate repeat;

struct Foo {}

repeat::repeat_with_idents!(impl Foo { fn IDENT() {} });

impl Foo { fn hello() {} } //~ERROR duplicate definitions with name `hello`
impl Foo { fn hello() {} }

// Transitive overlap

struct Foo2 {}

repeat::repeat_with_idents!(impl Foo2 { fn IDENT() {} });

impl Foo2 {
fn bar() {}
fn hello2() {} //~ERROR duplicate definitions with name `hello2`
}

impl Foo2 {
fn baz() {}
fn hello2() {}
}

// Slightly stronger transitive overlap

struct Foo3 {}

repeat::repeat_with_idents!(impl Foo3 { fn IDENT() {} });

impl Foo3 {
fn bar() {} //~ERROR duplicate definitions with name `bar`
fn hello3() {} //~ERROR duplicate definitions with name `hello3`
}

impl Foo3 {
fn bar() {}
fn hello3() {}
}

// Generic overlap

struct Bar<T>(T);

struct A;
struct B;

repeat::repeat_with_idents!(impl Bar<A> { fn IDENT() {} });

impl Bar<A> { fn foo() {} fn bar2() {} }
impl Bar<B> {
fn foo() {}
fn bar2() {} //~ERROR duplicate definitions with name `bar2`
}
impl Bar<B> { fn bar2() {} }

fn main() {}
47 changes: 47 additions & 0 deletions src/test/ui/inherent-impls-overlap-check/overlap.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
error[E0592]: duplicate definitions with name `hello`
--> $DIR/overlap.rs:20:12
|
LL | impl Foo { fn hello() {} }
| ^^^^^^^^^^ duplicate definitions for `hello`
LL | impl Foo { fn hello() {} }
| ---------- other definition for `hello`

error[E0592]: duplicate definitions with name `hello2`
--> $DIR/overlap.rs:31:5
|
LL | fn hello2() {}
| ^^^^^^^^^^^ duplicate definitions for `hello2`
...
LL | fn hello2() {}
| ----------- other definition for `hello2`

error[E0592]: duplicate definitions with name `bar`
--> $DIR/overlap.rs:46:5
|
LL | fn bar() {}
| ^^^^^^^^ duplicate definitions for `bar`
...
LL | fn bar() {}
| -------- other definition for `bar`

error[E0592]: duplicate definitions with name `hello3`
--> $DIR/overlap.rs:47:5
|
LL | fn hello3() {}
| ^^^^^^^^^^^ duplicate definitions for `hello3`
...
LL | fn hello3() {}
| ----------- other definition for `hello3`

error[E0592]: duplicate definitions with name `bar2`
--> $DIR/overlap.rs:67:5
|
LL | fn bar2() {}
| ^^^^^^^^^ duplicate definitions for `bar2`
LL | }
LL | impl Bar<B> { fn bar2() {} }
| --------- other definition for `bar2`

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0592`.

0 comments on commit 73a7d93

Please sign in to comment.