Skip to content

Commit 4ea8c15

Browse files
committed
Don't wipe out items on an error in #[cast_to]
1 parent 8a5b892 commit 4ea8c15

File tree

5 files changed

+78
-9
lines changed

5 files changed

+78
-9
lines changed

macros/src/lib.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ extern crate proc_macro;
22

33
use proc_macro::TokenStream;
44

5-
use syn::parse_macro_input;
6-
use syn::{DeriveInput, ItemImpl};
5+
use syn::{parse, parse_macro_input, DeriveInput, ItemImpl};
76

87
use args::{Casts, Flag, Targets};
98
use gen_caster::generate_caster;
@@ -46,13 +45,19 @@ mod item_type;
4645
/// ```
4746
#[proc_macro_attribute]
4847
pub fn cast_to(args: TokenStream, input: TokenStream) -> TokenStream {
49-
let Targets { flags, paths } = parse_macro_input!(args as args::Targets);
50-
let expanded = if paths.is_empty() {
51-
item_impl::process(&flags, parse_macro_input!(input as ItemImpl))
52-
} else {
53-
item_type::process(&flags, paths, parse_macro_input!(input as DeriveInput))
54-
};
55-
expanded.into()
48+
match parse::<Targets>(args) {
49+
Ok(Targets { flags, paths }) => {
50+
if paths.is_empty() {
51+
item_impl::process(&flags, parse_macro_input!(input as ItemImpl))
52+
} else {
53+
item_type::process(&flags, paths, parse_macro_input!(input as DeriveInput))
54+
}
55+
}
56+
Err(err) => vec![err.to_compile_error(), input.into()]
57+
.into_iter()
58+
.collect(),
59+
}
60+
.into()
5661
}
5762

5863
/// Declare target traits for casting implemented by a type.

tests/ui/duplicate-flags.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use intertrait::cast::*;
2+
use intertrait::*;
3+
use std::sync::Arc;
4+
5+
#[cast_to([sync, sync] Greet)]
6+
struct Data;
7+
8+
trait Source: CastFromSync {}
9+
10+
trait Greet {
11+
fn greet(&self);
12+
}
13+
14+
impl Greet for Data {
15+
fn greet(&self) {
16+
println!("Hello");
17+
}
18+
}
19+
20+
impl Source for Data {}
21+
22+
fn main() {
23+
let data = Arc::new(Data);
24+
let source: Arc<dyn Source> = data;
25+
let greet = source.cast::<dyn Greet>();
26+
greet.unwrap_or_else(|_| panic!("can't happen")).greet();
27+
}

tests/ui/duplicate-flags.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
error: Duplicated flag: sync
2+
--> $DIR/duplicate-flags.rs:5:18
3+
|
4+
5 | #[cast_to([sync, sync] Greet)]
5+
| ^^^^

tests/ui/unknown-flag.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use intertrait::cast::*;
2+
use intertrait::*;
3+
use std::sync::Arc;
4+
5+
#[cast_to([sync, send] Greet)]
6+
struct Data;
7+
8+
trait Source: CastFromSync {}
9+
10+
trait Greet {
11+
fn greet(&self);
12+
}
13+
14+
impl Greet for Data {
15+
fn greet(&self) {
16+
println!("Hello");
17+
}
18+
}
19+
20+
impl Source for Data {}
21+
22+
fn main() {
23+
let data = Arc::new(Data);
24+
let source: Arc<dyn Source> = data;
25+
let greet = source.cast::<dyn Greet>();
26+
greet.unwrap_or_else(|_| panic!("can't happen")).greet();
27+
}

tests/ui/unknown-flag.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
error: Unknown flag: send
2+
--> $DIR/unknown-flag.rs:5:18
3+
|
4+
5 | #[cast_to([sync, send] Greet)]
5+
| ^^^^

0 commit comments

Comments
 (0)