1 | //! Error type. |
2 | |
3 | use proc_macro2::Span; |
4 | |
5 | /// Easy API to create all [`syn::Error`] messages in this crate. |
6 | pub struct Error; |
7 | |
8 | impl Error { |
9 | /// `derive_where` was already applied on this item before. |
10 | pub fn visited(span: Span) -> syn::Error { |
11 | syn::Error::new( |
12 | span, |
13 | "`#[derive_where(..)` was already applied to this item before, this occurs when using \ |
14 | a qualified path for any `#[derive_where(..)`s except the first" , |
15 | ) |
16 | } |
17 | |
18 | /// Unnecessary `crate` option because it is equal to the default. |
19 | pub fn path_unnecessary(span: Span, default: &str) -> syn::Error { |
20 | syn::Error::new( |
21 | span, |
22 | format!( |
23 | "unnecessary path qualification, ` {}` is used by default" , |
24 | default |
25 | ), |
26 | ) |
27 | } |
28 | |
29 | /// The `crate` option was defined together with traits. |
30 | pub fn crate_(span: Span) -> syn::Error { |
31 | syn::Error::new( |
32 | span, |
33 | "the `crate` option has to be defined in it's own `#[derive_where(..)` attribute" , |
34 | ) |
35 | } |
36 | |
37 | /// No `derive_where` with [`Trait`](crate::Trait) found. |
38 | pub fn none(span: Span) -> syn::Error { |
39 | syn::Error::new( |
40 | span, |
41 | "no traits found to implement, use `#[derive_where(..)` to specify some" , |
42 | ) |
43 | } |
44 | |
45 | /// Unsupported empty `derive_where` on item. |
46 | pub fn empty(span: Span) -> syn::Error { |
47 | syn::Error::new(span, "empty `derive_where` found" ) |
48 | } |
49 | |
50 | /// Item has no use-case because it's covered by standard `#[derive(..)]`. |
51 | pub fn use_case(span: Span) -> syn::Error { |
52 | syn::Error::new( |
53 | span, |
54 | "this can be handled by standard `#[derive(..)]`, use a `skip` or `incomparable` \ |
55 | attribute, implement `Default` on an enum, or different generic type parameters" , |
56 | ) |
57 | } |
58 | |
59 | /// Unsupported empty item. |
60 | pub fn item_empty(span: Span) -> syn::Error { |
61 | syn::Error::new( |
62 | span, |
63 | "derive-where doesn't support empty items, as this can already be handled by standard \ |
64 | `#[derive(..)]`" , |
65 | ) |
66 | } |
67 | |
68 | /// Unsupported trait for union. |
69 | pub fn union(span: Span) -> syn::Error { |
70 | syn::Error::new( |
71 | span, |
72 | "traits other then `Clone` and `Copy` aren't supported by unions" , |
73 | ) |
74 | } |
75 | |
76 | /// Unsupported option in attribute. |
77 | #[cfg (feature = "zeroize" )] |
78 | pub fn option_trait(span: Span, attribute: &str) -> syn::Error { |
79 | syn::Error::new(span, format!("`{}` doesn't support this option" , attribute)) |
80 | } |
81 | |
82 | /// Unsupported option in attribute. |
83 | pub fn option(span: Span) -> syn::Error { |
84 | syn::Error::new(span, "unknown option" ) |
85 | } |
86 | |
87 | /// Unsupported options in attribute. |
88 | pub fn options(span: Span, trait_: &str) -> syn::Error { |
89 | syn::Error::new(span, format!("` {}` doesn't support any options" , trait_)) |
90 | } |
91 | |
92 | /// Invalid syntax for an option in attribute. |
93 | pub fn option_syntax(span: Span) -> syn::Error { |
94 | syn::Error::new(span, "unexpected option syntax" ) |
95 | } |
96 | |
97 | /// Unsupported empty attribute option. |
98 | pub fn option_empty(span: Span) -> syn::Error { |
99 | syn::Error::new(span, "empty attribute option found" ) |
100 | } |
101 | |
102 | /// Missing sub-option for an option. |
103 | #[cfg (feature = "zeroize" )] |
104 | pub fn option_required(span: Span, option: &str) -> syn::Error { |
105 | syn::Error::new(span, format!("`{}` requires an option" , option)) |
106 | } |
107 | |
108 | /// Duplicate option in attribute. |
109 | pub fn option_duplicate(span: Span, option: &str) -> syn::Error { |
110 | syn::Error::new(span, format!("duplicate ` {}` option" , option)) |
111 | } |
112 | |
113 | /// Unsupported `skip_inner` on an enum. |
114 | pub fn option_enum_skip_inner(span: Span) -> syn::Error { |
115 | syn::Error::new( |
116 | span, |
117 | "enums don't support `skip_inner`, use it on a variant instead" , |
118 | ) |
119 | } |
120 | |
121 | /// Unexpected `skip` on a field when `skip_inner` is already used on the |
122 | /// item or variant with this [`Trait`](crate::Trait). |
123 | pub fn option_skip_inner(span: Span) -> syn::Error { |
124 | syn::Error::new( |
125 | span, |
126 | "unexpected `skip` on a field when parent already uses `skip_inner` with this trait" , |
127 | ) |
128 | } |
129 | |
130 | /// Unsupported `skip_inner` on empty variant. |
131 | pub fn option_skip_empty(span: Span) -> syn::Error { |
132 | syn::Error::new(span, "no fields to skip" ) |
133 | } |
134 | |
135 | /// Unexpected constrained field skipping when configured to skip all traits |
136 | /// anyway. |
137 | pub fn option_skip_all(span: Span) -> syn::Error { |
138 | syn::Error::new( |
139 | span, |
140 | "unexpected constraint on `skip` when unconstrained `skip` already used" , |
141 | ) |
142 | } |
143 | |
144 | /// Duplicate trait constraint on `skip`. |
145 | pub fn option_skip_duplicate(span: Span, trait_: &str) -> syn::Error { |
146 | syn::Error::new(span, format!("duplicate ` {}` constraint on `skip`" , trait_)) |
147 | } |
148 | |
149 | /// No trait that can be skipped is being implemented. |
150 | pub fn option_skip_no_trait(span: Span) -> syn::Error { |
151 | syn::Error::new(span, "no trait that can be skipped is being implemented" ) |
152 | } |
153 | |
154 | /// Trait to be skipped isn't being implemented |
155 | pub fn option_skip_trait(span: Span) -> syn::Error { |
156 | syn::Error::new(span, "trait to be skipped isn't being implemented" ) |
157 | } |
158 | |
159 | /// Unsupported [`SkipGroup`](crate::SkipGroup). |
160 | pub fn skip_group(span: Span) -> syn::Error { |
161 | syn::Error::new( |
162 | span, |
163 | format!( |
164 | "unsupported skip group, expected one of {}" , |
165 | Self::skip_group_list() |
166 | ), |
167 | ) |
168 | } |
169 | |
170 | /// Invalid value for the `derive_where` or `Zeroize` `crate` option. |
171 | pub fn path(span: Span, parse_error: syn::Error) -> syn::Error { |
172 | syn::Error::new(span, format!("expected path, {}" , parse_error)) |
173 | } |
174 | |
175 | /// Unsupported [`Trait`](crate::Trait). |
176 | pub fn trait_(span: Span) -> syn::Error { |
177 | syn::Error::new( |
178 | span, |
179 | format!("unsupported trait, expected one of {}" , Self::trait_list()), |
180 | ) |
181 | } |
182 | |
183 | /// Invalid syntax for a [`Trait`](crate::Trait). |
184 | pub fn trait_syntax(span: Span) -> syn::Error { |
185 | syn::Error::new( |
186 | span, |
187 | format!( |
188 | "unsupported trait syntax, expected one of {}" , |
189 | Self::trait_list() |
190 | ), |
191 | ) |
192 | } |
193 | |
194 | /// Invalid delimiter in `derive_where` attribute for |
195 | /// [`Trait`](crate::Trait)s. |
196 | pub fn derive_where_delimiter(span: Span) -> syn::Error { |
197 | syn::Error::new(span, "expected `;` or `," ) |
198 | } |
199 | |
200 | /// Unsupported predicate type in `derive_where` attribute for where clause. |
201 | pub fn generic(span: Span) -> syn::Error { |
202 | syn::Error::new(span, "only type predicates are supported" ) |
203 | } |
204 | |
205 | /// Invalid syntax in `derive_where` attribute for generics. |
206 | pub fn generic_syntax(span: Span, parse_error: syn::Error) -> syn::Error { |
207 | syn::Error::new(span, format!("expected type to bind to, {}" , parse_error)) |
208 | } |
209 | |
210 | /// Duplicate trait with the same bound. |
211 | pub fn trait_duplicate(span: Span) -> syn::Error { |
212 | syn::Error::new(span, "duplicate trait with the same bound" ) |
213 | } |
214 | |
215 | /// Unknown `repr`. |
216 | pub fn repr_unknown(span: Span) -> syn::Error { |
217 | syn::Error::new(span, "found unknown representation" ) |
218 | } |
219 | |
220 | /// Invalid enum with non-empty variants and custom discriminants without an |
221 | /// integer representation. |
222 | pub fn repr_discriminant_invalid(span: Span) -> syn::Error { |
223 | syn::Error::new( |
224 | span, |
225 | "enums with non-empty variants and custom discriminants require a integer \ |
226 | representation" , |
227 | ) |
228 | } |
229 | |
230 | /// Unsupported default option if [`Default`] isn't implemented. |
231 | pub fn default(span: Span) -> syn::Error { |
232 | syn::Error::new( |
233 | span, |
234 | "`default` is only supported if `Default` is being implemented" , |
235 | ) |
236 | } |
237 | |
238 | /// Missing `default` option on a variant when [`Default`] is implemented |
239 | /// for an enum. |
240 | pub fn default_missing(span: Span) -> syn::Error { |
241 | syn::Error::new( |
242 | span, |
243 | "required `default` option on a variant if `Default` is being implemented" , |
244 | ) |
245 | } |
246 | |
247 | /// Duplicate `default` option on a variant. |
248 | pub fn default_duplicate(span: Span) -> syn::Error { |
249 | syn::Error::new(span, "multiple `default` options in enum" ) |
250 | } |
251 | |
252 | /// Unsupported `incomparable` option if [`PartialEq`] or [`PartialOrd`] |
253 | /// isn't implemented. |
254 | pub fn incomparable(span: Span) -> syn::Error { |
255 | syn::Error::new( |
256 | span, |
257 | "`incomparable` is only supported if `PartialEq` or `PartialOrd` is being implemented" , |
258 | ) |
259 | } |
260 | |
261 | /// Unsupported `incomparable` option if [`Eq`] or [`Ord`] is implemented. |
262 | pub fn non_partial_incomparable(span: Span) -> syn::Error { |
263 | syn::Error::new( |
264 | span, |
265 | "`incomparable` is not supported if `Eq` or `Ord` is being implemented" , |
266 | ) |
267 | } |
268 | |
269 | /// Unsupported `incomparable` option on both enum and variant. |
270 | pub fn incomparable_on_item_and_variant(item: Span, variant: Span) -> syn::Error { |
271 | syn::Error::new( |
272 | // This will only produce joint spans on nightly. |
273 | item.join(variant).unwrap_or(item), |
274 | "`incomparable` cannot be specified on both item and variant" , |
275 | ) |
276 | } |
277 | |
278 | /// List of available [`Trait`](crate::Trait)s. |
279 | fn trait_list() -> String { |
280 | [ |
281 | "Clone" , |
282 | "Copy" , |
283 | "Debug" , |
284 | "Default" , |
285 | "Eq" , |
286 | "Hash" , |
287 | "Ord" , |
288 | "PartialEq" , |
289 | "PartialOrd" , |
290 | #[cfg (feature = "zeroize" )] |
291 | "Zeroize" , |
292 | #[cfg (feature = "zeroize" )] |
293 | "ZeroizeOnDrop" , |
294 | ] |
295 | .join(", " ) |
296 | } |
297 | |
298 | /// List of available [`SkipGroup`](crate::SkipGroup)s. |
299 | fn skip_group_list() -> String { |
300 | [ |
301 | "Debug" , |
302 | "EqHashOrd" , |
303 | "Hash" , |
304 | #[cfg (feature = "zeroize" )] |
305 | "Zeroize" , |
306 | ] |
307 | .join(", " ) |
308 | } |
309 | |
310 | /// Unsupported `Zeroize` option if [`Zeroize`](https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html) isn't implemented. |
311 | #[cfg (feature = "zeroize" )] |
312 | pub fn zeroize(span: Span) -> syn::Error { |
313 | syn::Error::new( |
314 | span, |
315 | "`Zeroize` option is only supported if `Zeroize` is being implemented" , |
316 | ) |
317 | } |
318 | |
319 | /// Deprecated use of `Zeroize(drop)`. |
320 | #[cfg (feature = "zeroize" )] |
321 | pub fn deprecated_zeroize_drop(span: Span) -> syn::Error { |
322 | syn::Error::new( |
323 | span, |
324 | "`Zeroize(drop)` is deprecated, use `ZeroizeOnDrop` instead" , |
325 | ) |
326 | } |
327 | } |
328 | |