| 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 | |