Skip to content

Commit 63514ce

Browse files
authored
Merge pull request #96 from auto-impl-rs/feat/associated-lifetimes
Associated type generics and syn::Error
2 parents a0f053c + 2b1f9f7 commit 63514ce

25 files changed

+384
-405
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ proc-macro = true
2828
proc-macro2 = "1.0"
2929
quote = "1.0"
3030
syn = { version = "2.0", features = ["full", "visit", "visit-mut"] }
31-
proc-macro-error = "1.0.0"
3231

3332
[dev-dependencies]
3433
trybuild = "1"

src/attr.rs

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,18 @@
22
//! attached to trait items.
33
44
use proc_macro2::{Delimiter, TokenTree};
5-
use proc_macro_error::{abort, emit_error};
65
use syn::{
76
spanned::Spanned,
87
visit_mut::{visit_item_trait_mut, VisitMut},
9-
Attribute, Meta, TraitItem,
8+
Attribute, Error, Meta, TraitItem,
109
};
1110

1211
use crate::proxy::{parse_types, ProxyType};
1312

1413
/// Removes all `#[auto_impl]` attributes that are attached to methods of the
1514
/// given trait.
16-
pub(crate) fn remove_our_attrs(trait_def: &mut syn::ItemTrait) {
17-
struct AttrRemover;
15+
pub(crate) fn remove_our_attrs(trait_def: &mut syn::ItemTrait) -> syn::Result<()> {
16+
struct AttrRemover(syn::Result<()>);
1817
impl VisitMut for AttrRemover {
1918
fn visit_trait_item_mut(&mut self, item: &mut TraitItem) {
2019
let item_span = item.span();
@@ -23,26 +22,46 @@ pub(crate) fn remove_our_attrs(trait_def: &mut syn::ItemTrait) {
2322
TraitItem::Const(c) => (&mut c.attrs, false),
2423
TraitItem::Type(t) => (&mut t.attrs, false),
2524
TraitItem::Macro(m) => (&mut m.attrs, false),
26-
_ => abort!(
27-
item.span(),
28-
"encountered unexpected `TraitItem`, cannot handle that, sorry!";
29-
note = "auto-impl supports only methods, consts, types and macros currently";
30-
),
25+
_ => {
26+
let err = syn::Error::new(
27+
item.span(),
28+
"encountered unexpected `TraitItem`, cannot handle that, sorry!",
29+
);
30+
31+
if let Err(ref mut current_err) = self.0 {
32+
current_err.combine(err);
33+
} else {
34+
self.0 = Err(err);
35+
};
36+
37+
return;
38+
}
3139
};
3240

3341
// Make sure non-methods do not have our attributes.
3442
if !is_method && attrs.iter().any(is_our_attr) {
35-
emit_error!(
43+
let err = syn::Error::new(
3644
item_span,
3745
"`#[auto_impl]` attributes are only allowed on methods",
3846
);
47+
48+
if let Err(ref mut current_err) = self.0 {
49+
current_err.combine(err);
50+
} else {
51+
self.0 = Err(err);
52+
};
53+
54+
return;
3955
}
4056

4157
attrs.retain(|a| !is_our_attr(a));
4258
}
4359
}
4460

45-
visit_item_trait_mut(&mut AttrRemover, trait_def);
61+
let mut visitor = AttrRemover(Ok(()));
62+
visit_item_trait_mut(&mut visitor, trait_def);
63+
64+
visitor.0
4665
}
4766

4867
/// Checks if the given attribute is "our" attribute. That means that it's path
@@ -55,7 +74,7 @@ pub(crate) fn is_our_attr(attr: &Attribute) -> bool {
5574
/// attributes. If it's invalid, an error is emitted and `Err(())` is returned.
5675
/// You have to make sure that `attr` is one of our attrs with `is_our_attr`
5776
/// before calling this function!
58-
pub(crate) fn parse_our_attr(attr: &Attribute) -> Result<OurAttr, ()> {
77+
pub(crate) fn parse_our_attr(attr: &Attribute) -> syn::Result<OurAttr> {
5978
assert!(is_our_attr(attr));
6079

6180
// Get the body of the attribute (which has to be a ground, because we
@@ -64,8 +83,10 @@ pub(crate) fn parse_our_attr(attr: &Attribute) -> Result<OurAttr, ()> {
6483
let body = match &attr.meta {
6584
Meta::List(list) => list.tokens.clone(),
6685
_ => {
67-
emit_error!(attr.span(), "expected single group delimited by `()`");
68-
return Err(());
86+
return Err(Error::new(
87+
attr.span(),
88+
"expected single group delimited by `()`",
89+
));
6990
}
7091
};
7192

@@ -75,12 +96,13 @@ pub(crate) fn parse_our_attr(attr: &Attribute) -> Result<OurAttr, ()> {
7596
let name = match it.next() {
7697
Some(TokenTree::Ident(x)) => x,
7798
Some(other) => {
78-
emit_error!(other.span(), "expected ident, found '{}'", other);
79-
return Err(());
99+
return Err(Error::new(
100+
other.span(),
101+
format_args!("expected ident, found '{}'", other),
102+
));
80103
}
81104
None => {
82-
emit_error!(attr.span(), "expected ident, found nothing");
83-
return Err(());
105+
return Err(Error::new(attr.span(), "expected ident, found nothing"));
84106
}
85107
};
86108

@@ -89,21 +111,22 @@ pub(crate) fn parse_our_attr(attr: &Attribute) -> Result<OurAttr, ()> {
89111
let params = match it.next() {
90112
Some(TokenTree::Group(ref g)) if g.delimiter() == Delimiter::Parenthesis => g.stream(),
91113
Some(other) => {
92-
emit_error!(
114+
return Err(Error::new(
93115
other.span(),
94-
"expected arguments for '{}' in parenthesis `()`, found `{}`",
95-
name,
96-
other,
97-
);
98-
return Err(());
116+
format_args!(
117+
"expected arguments for '{}' in parenthesis `()`, found `{}`",
118+
name, other
119+
),
120+
));
99121
}
100122
None => {
101-
emit_error!(
123+
return Err(Error::new(
102124
body.span(),
103-
"expected arguments for '{}' in parenthesis `()`, found nothing",
104-
name,
105-
);
106-
return Err(());
125+
format_args!(
126+
"expected arguments for '{}' in parenthesis `()`, found nothing",
127+
name,
128+
),
129+
));
107130
}
108131
};
109132

@@ -112,11 +135,13 @@ pub(crate) fn parse_our_attr(attr: &Attribute) -> Result<OurAttr, ()> {
112135
let proxy_types = parse_types(params.into());
113136
OurAttr::KeepDefaultFor(proxy_types)
114137
} else {
115-
emit_error!(
116-
name.span(), "invalid attribute '{}'", name;
117-
note = "only `keep_default_for` is supported";
118-
);
119-
return Err(());
138+
return Err(Error::new(
139+
name.span(),
140+
format_args!(
141+
"invalid attribute '{}'; only `keep_default_for` is supported",
142+
name
143+
),
144+
));
120145
};
121146

122147
Ok(out)

0 commit comments

Comments
 (0)