1//! Error type.
2
3use proc_macro2::Span;
4
5/// Easy API to create all [`syn::Error`] messages in this crate.
6pub struct Error;
7
8impl 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