1diff --git a/Cargo.toml b/Cargo.toml
2index 2e33871..388f042 100644
3--- a/Cargo.toml
4+++ b/Cargo.toml
5@@ -24,8 +24,6 @@ repository = "https://git.sr.ht/~ireas/merge-rs/tree/master/merge_derive"
6
7 [lib]
8 proc-macro = true
9-[dependencies.proc-macro-error]
10-version = "1.0"
11
12 [dependencies.proc-macro2]
13 version = "1.0"
14@@ -34,4 +32,4 @@ version = "1.0"
15 version = "1.0"
16
17 [dependencies.syn]
18-version = "1.0"
19+version = "2.0"
20diff --git a/src/lib.rs b/src/lib.rs
21index 75732f9..11f5b49 100644
22--- a/src/lib.rs
23+++ b/src/lib.rs
24@@ -11,9 +11,9 @@
25 extern crate proc_macro;
26
27 use proc_macro2::TokenStream;
28-use proc_macro_error::{abort, abort_call_site, dummy::set_dummy, proc_macro_error, ResultExt};
29 use quote::{quote, quote_spanned};
30-use syn::Token;
31+use std::convert::TryFrom;
32+use syn::{Error, Result, Token};
33
34 struct Field {
35     name: syn::Member,
36@@ -33,48 +33,51 @@ enum FieldAttr {
37 }
38
39 #[proc_macro_derive(Merge, attributes(merge))]
40-#[proc_macro_error]
41 pub fn merge_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
42     let ast = syn::parse(input).unwrap();
43-    impl_merge(&ast).into()
44+    impl_merge(&ast)
45+        .unwrap_or_else(Error::into_compile_error)
46+        .into()
47 }
48
49-fn impl_merge(ast: &syn::DeriveInput) -> TokenStream {
50+fn impl_merge(ast: &syn::DeriveInput) -> Result<TokenStream> {
51     let name = &ast.ident;
52
53-    set_dummy(quote! {
54-        impl ::merge::Merge for #name {
55-            fn merge(&mut self, other: Self) {
56-                unimplemented!()
57-            }
58-        }
59-    });
60-
61     if let syn::Data::Struct(syn::DataStruct { ref fields, .. }) = ast.data {
62         impl_merge_for_struct(name, fields)
63     } else {
64-        abort_call_site!("merge::Merge can only be derived for structs")
65+        Err(Error::new_spanned(
66+            ast,
67+            "merge::Merge can only be derived for structs",
68+        ))
69     }
70 }
71
72-fn impl_merge_for_struct(name: &syn::Ident, fields: &syn::Fields) -> TokenStream {
73-    let assignments = gen_assignments(fields);
74+fn impl_merge_for_struct(name: &syn::Ident, fields: &syn::Fields) -> Result<TokenStream> {
75+    let assignments = gen_assignments(fields)?;
76
77-    quote! {
78+    Ok(quote! {
79         impl ::merge::Merge for #name {
80             fn merge(&mut self, other: Self) {
81                 #assignments
82             }
83         }
84-    }
85+    })
86 }
87
88-fn gen_assignments(fields: &syn::Fields) -> TokenStream {
89-    let fields = fields.iter().enumerate().map(Field::from);
90-    let assignments = fields.filter(|f| !f.attrs.skip).map(|f| gen_assignment(&f));
91-    quote! {
92+fn gen_assignments(fields: &syn::Fields) -> Result<TokenStream> {
93+    let fields = fields
94+        .iter()
95+        .enumerate()
96+        .map(Field::try_from)
97+        .collect::<Result<Vec<_>>>()?;
98+    let assignments = fields
99+        .iter()
100+        .filter(|f| !f.attrs.skip)
101+        .map(|f| gen_assignment(&f));
102+    Ok(quote! {
103         #( #assignments )*
104-    }
105+    })
106 }
107
108 fn gen_assignment(field: &Field) -> TokenStream {
109@@ -88,48 +91,48 @@ fn gen_assignment(field: &Field) -> TokenStream {
110     }
111 }
112
113-impl From<(usize, &syn::Field)> for Field {
114-    fn from(data: (usize, &syn::Field)) -> Self {
115+impl TryFrom<(usize, &syn::Field)> for Field {
116+    type Error = syn::Error;
117+
118+    fn try_from(data: (usize, &syn::Field)) -> std::result::Result<Self, Self::Error> {
119         use syn::spanned::Spanned;
120
121         let (index, field) = data;
122-        Field {
123+        Ok(Field {
124             name: if let Some(ident) = &field.ident {
125                 syn::Member::Named(ident.clone())
126             } else {
127                 syn::Member::Unnamed(index.into())
128             },
129             span: field.span(),
130-            attrs: field.attrs.iter().into(),
131-        }
132+            attrs: FieldAttrs::new(field.attrs.iter())?,
133+        })
134     }
135 }
136
137 impl FieldAttrs {
138-    fn apply(&mut self, attr: FieldAttr) {
139-        match attr {
140-            FieldAttr::Skip => self.skip = true,
141-            FieldAttr::Strategy(path) => self.strategy = Some(path),
142-        }
143-    }
144-}
145-
146-impl<'a, I: Iterator<Item = &'a syn::Attribute>> From<I> for FieldAttrs {
147-    fn from(iter: I) -> Self {
148+    fn new<'a, I: Iterator<Item = &'a syn::Attribute>>(iter: I) -> Result<Self> {
149         let mut field_attrs = Self::default();
150
151         for attr in iter {
152-            if !attr.path.is_ident("merge") {
153+            if !attr.path().is_ident("merge") {
154                 continue;
155             }
156
157             let parser = syn::punctuated::Punctuated::<FieldAttr, Token![,]>::parse_terminated;
158-            for attr in attr.parse_args_with(parser).unwrap_or_abort() {
159+            for attr in attr.parse_args_with(parser)? {
160                 field_attrs.apply(attr);
161             }
162         }
163
164-        field_attrs
165+        Ok(field_attrs)
166+    }
167+
168+    fn apply(&mut self, attr: FieldAttr) {
169+        match attr {
170+            FieldAttr::Skip => self.skip = true,
171+            FieldAttr::Strategy(path) => self.strategy = Some(path),
172+        }
173     }
174 }
175
176@@ -144,7 +147,10 @@ impl syn::parse::Parse for FieldAttr {
177             let path: syn::Path = input.parse()?;
178             Ok(FieldAttr::Strategy(path))
179         } else {
180-            abort!(name, "Unexpected attribute: {}", name)
181+            Err(Error::new_spanned(
182+                &name,
183+                format!("Unexpected attribute: {}", name),
184+            ))
185         }
186     }
187 }
188