Skip to content

Commit

Permalink
Merge pull request #59 from auto-impl-rs/use-trybuild
Browse files Browse the repository at this point in the history
Use `trybuild` to do compile-fail/pass tests (and fix some minor bugs)
  • Loading branch information
LukasKalbertodt authored Nov 28, 2019
2 parents f5d3f9b + 43ad0ed commit 7976a40
Show file tree
Hide file tree
Showing 74 changed files with 347 additions and 243 deletions.
19 changes: 8 additions & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
language: rust
rust:
- nightly
- beta
- stable

script:
- cargo build --verbose || travis_terminate 1
- cargo test --verbose || travis_terminate 1

matrix:
include:
Expand All @@ -7,17 +15,6 @@ matrix:
script:
- cargo build --verbose --features=nightly || travis_terminate 1
- cargo test --verbose --features=nightly || travis_terminate 1
- name: "Build & test on nightly WITHOUT nightly feature"
rust: nightly
script:
- cargo build --verbose || travis_terminate 1
- cargo test --verbose || travis_terminate 1
- name: "Build on beta"
rust: beta
script: cargo build --verbose
- name: "Build on stable"
rust: stable
script: cargo build --verbose

env:
global:
Expand Down
14 changes: 2 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,5 @@ quote = "1.0"
syn = { version = "1.0", features = ["full", "visit", "visit-mut"] }

[dev-dependencies]
build-plan = "0.1.1"
libtest-mimic = "0.2.0"

[[test]]
name = "compile-fail"
path = "tests/compile-fail.rs"
harness = false

[[test]]
name = "compile-pass"
path = "tests/compile-pass.rs"
harness = false
trybuild = "1"
rustversion = "1"
22 changes: 19 additions & 3 deletions src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use proc_macro2::{Delimiter, TokenTree};
use syn::{
Attribute, TraitItemMethod,
Attribute, TraitItem,
visit_mut::{VisitMut, visit_item_trait_mut},
};

Expand All @@ -19,8 +19,24 @@ use crate::{
pub(crate) fn remove_our_attrs(trait_def: &mut syn::ItemTrait) {
struct AttrRemover;
impl VisitMut for AttrRemover {
fn visit_trait_item_method_mut(&mut self, m: &mut TraitItemMethod) {
m.attrs.retain(|a| !is_our_attr(a));
fn visit_trait_item_mut(&mut self, item: &mut TraitItem) {
let item_span = item.span();
let (attrs, is_method) = match item {
TraitItem::Method(m) => (&mut m.attrs, true),
TraitItem::Const(c) => (&mut c.attrs, false),
TraitItem::Type(t) => (&mut t.attrs, false),
TraitItem::Macro(m) => (&mut m.attrs, false),
_ => panic!("encountered unexpected `TraitItem`, cannot handle that, sorry!"),
};

// Make sure non-methods do not have our attributes.
if !is_method && attrs.iter().any(|a| is_our_attr(a)) {
item_span
.err("`auto_impl` attributes are only allowed on methods")
.emit();
}

attrs.retain(|a| !is_our_attr(a));
}
}

Expand Down
9 changes: 8 additions & 1 deletion src/diag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,14 @@ thread_local! {
/// On stable, we just copy the error token streams from the global variable.
#[cfg(not(feature = "nightly"))]
pub(crate) fn error_tokens() -> TokenStream {
ERROR_TOKENS.with(|toks| toks.borrow().iter().cloned().collect())
ERROR_TOKENS.with(|toks| {
// We are clearing the vector here (and dropping all its elements) so
// that it does not need to do that ... at some other point. It's
// unclear when exactly the thread local variable is dropped. But
// currently, if the vector still has elements when our macro is done,
// we cause a fatal runtime error inside `rustc`. That's bad.
toks.borrow_mut().drain(..).collect()
})
}

/// On nightly, we don't use and don't have a strange global variable. Instead,
Expand Down
12 changes: 8 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,16 +273,20 @@ pub fn auto_impl(args: TokenStream, input: TokenStream) -> TokenStream {
// `#[auto_impl(...)]` attributes on all methods.
attr::remove_our_attrs(&mut trait_def);

match generated {
let error_tokens = diag::error_tokens();

match &generated {
// No errors at all => output the trait and our generated impls
Ok(generated) => quote! { #trait_def #generated }.into(),
Err(_) => {
Ok(generated) if error_tokens.is_empty() => {
(quote! { #trait_def #generated }).into()
}
_ => {
// We combine the token stream of the modified trait
// definition with the generated errors (which are tokens
// on stable due to the `compile_error!` hack).
vec![
TokenStream::from(trait_def.into_token_stream()),
diag::error_tokens()
error_tokens,
].into_iter().collect()
}
}
Expand Down
34 changes: 0 additions & 34 deletions tests/compile-fail.rs

This file was deleted.

2 changes: 2 additions & 0 deletions tests/compile-fail/attr_on_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ enum Foo {
Name(String),
Rgb(u8, u8, u8),
}

fn main() {}
9 changes: 9 additions & 0 deletions tests/compile-fail/attr_on_enum.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error: couldn't parse trait item

note: expected `trait`

note: the #[auto_impl] attribute can only be applied to traits!
--> $DIR/attr_on_enum.rs:5:1
|
5 | enum Foo {
| ^^^^
2 changes: 2 additions & 0 deletions tests/compile-fail/attr_on_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ use auto_impl::auto_impl;
fn foo(s: String) -> u32 {
3
}

fn main() {}
9 changes: 9 additions & 0 deletions tests/compile-fail/attr_on_fn.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error: couldn't parse trait item

note: expected `trait`

note: the #[auto_impl] attribute can only be applied to traits!
--> $DIR/attr_on_fn.rs:5:1
|
5 | fn foo(s: String) -> u32 {
| ^^
2 changes: 2 additions & 0 deletions tests/compile-fail/attr_on_impl_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ trait Foo {}

#[auto_impl(&, &mut)]
impl Foo for usize {}

fn main() {}
9 changes: 9 additions & 0 deletions tests/compile-fail/attr_on_impl_block.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error: couldn't parse trait item

note: expected `trait`

note: the #[auto_impl] attribute can only be applied to traits!
--> $DIR/attr_on_impl_block.rs:7:1
|
7 | impl Foo for usize {}
| ^^^^
3 changes: 3 additions & 0 deletions tests/compile-fail/attr_on_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ struct Foo {
x: usize,
bar: String,
}


fn main() {}
9 changes: 9 additions & 0 deletions tests/compile-fail/attr_on_struct.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error: couldn't parse trait item

note: expected `trait`

note: the #[auto_impl] attribute can only be applied to traits!
--> $DIR/attr_on_struct.rs:5:1
|
5 | struct Foo {
| ^^^^^^
3 changes: 3 additions & 0 deletions tests/compile-fail/attr_on_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ use auto_impl::auto_impl;

#[auto_impl(&, &mut)]
type Baz = String;


fn main() {}
9 changes: 9 additions & 0 deletions tests/compile-fail/attr_on_type.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error: couldn't parse trait item

note: expected `trait`

note: the #[auto_impl] attribute can only be applied to traits!
--> $DIR/attr_on_type.rs:5:1
|
5 | type Baz = String;
| ^^^^
3 changes: 3 additions & 0 deletions tests/compile-fail/attr_on_unit_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ use auto_impl::auto_impl;

#[auto_impl(&, &mut)]
struct Foo(usize, String);


fn main() {}
9 changes: 9 additions & 0 deletions tests/compile-fail/attr_on_unit_struct.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error: couldn't parse trait item

note: expected `trait`

note: the #[auto_impl] attribute can only be applied to traits!
--> $DIR/attr_on_unit_struct.rs:5:1
|
5 | struct Foo(usize, String);
| ^^^^^^
3 changes: 3 additions & 0 deletions tests/compile-fail/fn_associated_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ trait Foo {

fn a(&self);
}


fn main() {}
7 changes: 7 additions & 0 deletions tests/compile-fail/fn_associated_const.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: this trait cannot be auto-implemented for Fn-traits (only traits with exactly one method and no other items are allowed)

note: auto-impl requested here
--> $DIR/fn_associated_const.rs:5:1
|
5 | trait Foo {
| ^^^^^
3 changes: 3 additions & 0 deletions tests/compile-fail/fn_associated_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ trait Foo {

fn a(&self);
}


fn main() {}
7 changes: 7 additions & 0 deletions tests/compile-fail/fn_associated_type.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: this trait cannot be auto-implemented for Fn-traits (only traits with exactly one method and no other items are allowed)

note: auto-impl requested here
--> $DIR/fn_associated_type.rs:5:1
|
5 | trait Foo {
| ^^^^^
3 changes: 3 additions & 0 deletions tests/compile-fail/fn_multiple_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ trait Foo {
fn a(&self);
fn b(&self);
}


fn main() {}
7 changes: 7 additions & 0 deletions tests/compile-fail/fn_multiple_methods.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: this trait cannot be auto-implemented for Fn-traits (only traits with exactly one method and no other items are allowed)

note: auto-impl requested here
--> $DIR/fn_multiple_methods.rs:5:1
|
5 | trait Foo {
| ^^^^^
3 changes: 3 additions & 0 deletions tests/compile-fail/fn_unsafe_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ use auto_impl::auto_impl;
trait Foo {
unsafe fn a(&self);
}


fn main() {}
7 changes: 7 additions & 0 deletions tests/compile-fail/fn_unsafe_method.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: the trait 'Foo' cannot be auto-implemented for Fn-traits: unsafe methods are not allowed

note: auto-impl requested here
--> $DIR/fn_unsafe_method.rs:6:5
|
6 | unsafe fn a(&self);
| ^^^^^^
3 changes: 3 additions & 0 deletions tests/compile-fail/keep_default_for_on_assoc_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ trait Foo {
#[auto_impl(keep_default_for(&))]
type Foo;
}


fn main() {}
5 changes: 5 additions & 0 deletions tests/compile-fail/keep_default_for_on_assoc_type.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: `auto_impl` attributes are only allowed on methods
--> $DIR/keep_default_for_on_assoc_type.rs:6:5
|
6 | #[auto_impl(keep_default_for(&))]
| ^
3 changes: 3 additions & 0 deletions tests/compile-fail/keep_default_for_on_required_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ trait Foo {
#[auto_impl(keep_default_for(&))]
fn required(&self);
}


fn main() {}
7 changes: 7 additions & 0 deletions tests/compile-fail/keep_default_for_on_required_method.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: the method `required` has the attribute `keep_default_for` but is not a default method (no body is provided)

note: auto-impl requested here
--> $DIR/keep_default_for_on_required_method.rs:7:5
|
7 | fn required(&self);
| ^^
3 changes: 3 additions & 0 deletions tests/compile-fail/method_attr_invalid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ trait Foo {
#[auto_impl(ferris_for_life)]
fn a(&self);
}


fn main() {}
7 changes: 7 additions & 0 deletions tests/compile-fail/method_attr_invalid.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: expected arguments for 'ferris_for_life' in parenthesis `()`, found nothing

note: auto-impl requested here
--> $DIR/method_attr_invalid.rs:6:17
|
6 | #[auto_impl(ferris_for_life)]
| ^^^^^^^^^^^^^^^
3 changes: 3 additions & 0 deletions tests/compile-fail/mut_self_for_arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ use auto_impl::auto_impl;
trait Foo {
fn foo(&mut self);
}


fn main() {}
7 changes: 7 additions & 0 deletions tests/compile-fail/mut_self_for_arc.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: the trait `Foo` cannot be auto-implemented for Arc-smartpointer, because this method has a `&mut self` receiver (only `&self` and no receiver are allowed)

note: auto-impl requested here
--> $DIR/mut_self_for_arc.rs:6:5
|
6 | fn foo(&mut self);
| ^^
3 changes: 3 additions & 0 deletions tests/compile-fail/mut_self_for_immutable_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ use auto_impl::auto_impl;
trait Foo {
fn foo(&mut self);
}


fn main() {}
7 changes: 7 additions & 0 deletions tests/compile-fail/mut_self_for_immutable_ref.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: the trait `Foo` cannot be auto-implemented for immutable references, because this method has a `&mut self` receiver (only `&self` and no receiver are allowed)

note: auto-impl requested here
--> $DIR/mut_self_for_immutable_ref.rs:6:5
|
6 | fn foo(&mut self);
| ^^
3 changes: 3 additions & 0 deletions tests/compile-fail/mut_self_for_rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ use auto_impl::auto_impl;
trait Foo {
fn foo(&mut self);
}


fn main() {}
Loading

0 comments on commit 7976a40

Please sign in to comment.