blob: d531f0ccfcb8f73041dbe2cc8f2fef73f8834a98 [file] [log] [blame]
//! Error type.
use proc_macro2::Span;
/// Easy API to create all [`syn::Error`] messages in this crate.
pub struct Error;
impl Error {
/// `derive_where` was already applied on this item before.
pub fn visited(span: Span) -> syn::Error {
syn::Error::new(
span,
"`#[derive_where(..)` was already applied to this item before, this occurs when using \
a qualified path for any `#[derive_where(..)`s except the first",
)
}
/// Unnecessary `crate` option because it is equal to the default.
pub fn path_unnecessary(span: Span, default: &str) -> syn::Error {
syn::Error::new(
span,
format!(
"unnecessary path qualification, `{}` is used by default",
default
),
)
}
/// The `crate` option was defined together with traits.
pub fn crate_(span: Span) -> syn::Error {
syn::Error::new(
span,
"the `crate` option has to be defined in it's own `#[derive_where(..)` attribute",
)
}
/// No `derive_where` with [`Trait`](crate::Trait) found.
pub fn none(span: Span) -> syn::Error {
syn::Error::new(
span,
"no traits found to implement, use `#[derive_where(..)` to specify some",
)
}
/// Unsupported empty `derive_where` on item.
pub fn empty(span: Span) -> syn::Error {
syn::Error::new(span, "empty `derive_where` found")
}
/// Item has no use-case because it's covered by standard `#[derive(..)]`.
pub fn use_case(span: Span) -> syn::Error {
syn::Error::new(
span,
"this can be handled by standard `#[derive(..)]`, use a `skip` or `incomparable` \
attribute, implement `Default` on an enum, or different generic type parameters",
)
}
/// Unsupported empty item.
pub fn item_empty(span: Span) -> syn::Error {
syn::Error::new(
span,
"derive-where doesn't support empty items, as this can already be handled by standard \
`#[derive(..)]`",
)
}
/// Unsupported trait for union.
pub fn union(span: Span) -> syn::Error {
syn::Error::new(
span,
"traits other then `Clone` and `Copy` aren't supported by unions",
)
}
/// Unsupported option in attribute.
#[cfg(feature = "zeroize")]
pub fn option_trait(span: Span, attribute: &str) -> syn::Error {
syn::Error::new(span, format!("`{}` doesn't support this option", attribute))
}
/// Unsupported option in attribute.
pub fn option(span: Span) -> syn::Error {
syn::Error::new(span, "unknown option")
}
/// Unsupported options in attribute.
pub fn options(span: Span, trait_: &str) -> syn::Error {
syn::Error::new(span, format!("`{}` doesn't support any options", trait_))
}
/// Invalid syntax for an option in attribute.
pub fn option_syntax(span: Span) -> syn::Error {
syn::Error::new(span, "unexpected option syntax")
}
/// Unsupported empty attribute option.
pub fn option_empty(span: Span) -> syn::Error {
syn::Error::new(span, "empty attribute option found")
}
/// Missing sub-option for an option.
#[cfg(feature = "zeroize")]
pub fn option_required(span: Span, option: &str) -> syn::Error {
syn::Error::new(span, format!("`{}` requires an option", option))
}
/// Duplicate option in attribute.
pub fn option_duplicate(span: Span, option: &str) -> syn::Error {
syn::Error::new(span, format!("duplicate `{}` option", option))
}
/// Unsupported `skip_inner` on an enum.
pub fn option_enum_skip_inner(span: Span) -> syn::Error {
syn::Error::new(
span,
"enums don't support `skip_inner`, use it on a variant instead",
)
}
/// Unexpected `skip` on a field when `skip_inner` is already used on the
/// item or variant with this [`Trait`](crate::Trait).
pub fn option_skip_inner(span: Span) -> syn::Error {
syn::Error::new(
span,
"unexpected `skip` on a field when parent already uses `skip_inner` with this trait",
)
}
/// Unsupported `skip_inner` on empty variant.
pub fn option_skip_empty(span: Span) -> syn::Error {
syn::Error::new(span, "no fields to skip")
}
/// Unexpected constrained field skipping when configured to skip all traits
/// anyway.
pub fn option_skip_all(span: Span) -> syn::Error {
syn::Error::new(
span,
"unexpected constraint on `skip` when unconstrained `skip` already used",
)
}
/// Duplicate trait constraint on `skip`.
pub fn option_skip_duplicate(span: Span, trait_: &str) -> syn::Error {
syn::Error::new(span, format!("duplicate `{}` constraint on `skip`", trait_))
}
/// No trait that can be skipped is being implemented.
pub fn option_skip_no_trait(span: Span) -> syn::Error {
syn::Error::new(span, "no trait that can be skipped is being implemented")
}
/// Trait to be skipped isn't being implemented
pub fn option_skip_trait(span: Span) -> syn::Error {
syn::Error::new(span, "trait to be skipped isn't being implemented")
}
/// Unsupported [`SkipGroup`](crate::SkipGroup).
pub fn skip_group(span: Span) -> syn::Error {
syn::Error::new(
span,
format!(
"unsupported skip group, expected one of {}",
Self::skip_group_list()
),
)
}
/// Invalid value for the `derive_where`, `serde` or `Zeroize` `crate`
/// option.
pub fn path(span: Span, parse_error: syn::Error) -> syn::Error {
syn::Error::new(span, format!("expected path, {}", parse_error))
}
/// Unsupported [`Trait`](crate::Trait).
pub fn trait_(span: Span) -> syn::Error {
syn::Error::new(
span,
format!("unsupported trait, expected one of {}", Self::trait_list()),
)
}
/// Invalid syntax for a [`Trait`](crate::Trait).
pub fn trait_syntax(span: Span) -> syn::Error {
syn::Error::new(
span,
format!(
"unsupported trait syntax, expected one of {}",
Self::trait_list()
),
)
}
/// Requires crate feature `serde`.
#[cfg(not(feature = "serde"))]
pub fn serde_feature(span: Span) -> syn::Error {
syn::Error::new(span, "requires crate feature `serde`")
}
/// Requires crate feature `zeroize`.
#[cfg(not(feature = "zeroize"))]
pub fn zeroize_feature(span: Span) -> syn::Error {
syn::Error::new(span, "requires crate feature `zeroize`")
}
/// Requires crate feature `zeroize-on-drop`.
#[cfg(all(feature = "zeroize", not(feature = "zeroize-on-drop")))]
pub fn zeroize_on_drop_feature(span: Span) -> syn::Error {
syn::Error::new(span, "requires crate feature `zeroize-on-drop`")
}
/// Invalid delimiter in `derive_where` attribute for
/// [`Trait`](crate::Trait)s.
pub fn derive_where_delimiter(span: Span) -> syn::Error {
syn::Error::new(span, "expected `;` or `,")
}
/// Unsupported predicate type in `derive_where` attribute for where clause.
pub fn generic(span: Span) -> syn::Error {
syn::Error::new(span, "only type predicates are supported")
}
/// Invalid syntax in `derive_where` attribute for generics.
pub fn generic_syntax(span: Span, parse_error: syn::Error) -> syn::Error {
syn::Error::new(span, format!("expected type to bind to, {}", parse_error))
}
/// Duplicate trait with the same bound.
pub fn trait_duplicate(span: Span) -> syn::Error {
syn::Error::new(span, "duplicate trait with the same bound")
}
/// Unknown `repr`.
#[cfg(not(feature = "nightly"))]
pub fn repr_unknown(span: Span) -> syn::Error {
syn::Error::new(span, "found unknown representation")
}
/// Invalid enum with non-empty variants and custom discriminants without an
/// integer representation.
#[cfg(not(feature = "nightly"))]
pub fn repr_discriminant_invalid(span: Span) -> syn::Error {
syn::Error::new(
span,
"enums with non-empty variants and custom discriminants require a integer \
representation",
)
}
/// Unsupported default option if [`Default`] isn't implemented.
pub fn default(span: Span) -> syn::Error {
syn::Error::new(
span,
"`default` is only supported if `Default` is being implemented",
)
}
/// Missing `default` option on a variant when [`Default`] is implemented
/// for an enum.
pub fn default_missing(span: Span) -> syn::Error {
syn::Error::new(
span,
"required `default` option on a variant if `Default` is being implemented",
)
}
/// Duplicate `default` option on a variant.
pub fn default_duplicate(span: Span) -> syn::Error {
syn::Error::new(span, "multiple `default` options in enum")
}
/// Unsupported `incomparable` option if [`PartialEq`] or [`PartialOrd`]
/// isn't implemented.
pub fn incomparable(span: Span) -> syn::Error {
syn::Error::new(
span,
"`incomparable` is only supported if `PartialEq` or `PartialOrd` is being implemented",
)
}
/// Unsupported `incomparable` option if [`Eq`] or [`Ord`] is implemented.
pub fn non_partial_incomparable(span: Span) -> syn::Error {
syn::Error::new(
span,
"`incomparable` is not supported if `Eq` or `Ord` is being implemented",
)
}
/// Unsupported `incomparable` option on both enum and variant.
pub fn incomparable_on_item_and_variant(item: Span, variant: Span) -> syn::Error {
syn::Error::new(
// This will only produce joint spans on nightly.
item.join(variant).unwrap_or(item),
"`incomparable` cannot be specified on both item and variant",
)
}
/// Unsupported `skip(Clone)` while deriving copy.
pub fn unable_to_skip_clone_while_deriving_copy(skip_clone: Span) -> syn::Error {
syn::Error::new(skip_clone, "Cannot skip `Clone` while deriving `Copy`")
}
/// Unsupported `serde(...)` without deriving `De/Serialize`.
#[cfg(feature = "serde")]
pub fn serde_without_serde(serde: Span) -> syn::Error {
syn::Error::new(serde, "Found unused `#[serde(...)]`")
}
/// Conflicting `serde(bound ...)` when deriving `De/Serialize`.
#[cfg(feature = "serde")]
pub fn serde_bound(serde: Span) -> syn::Error {
syn::Error::new(serde, "Found conflicting `#[serde(bound ...)]`")
}
/// List of available [`Trait`](crate::Trait)s.
fn trait_list() -> String {
[
"Clone",
"Copy",
"Debug",
"Default",
"Deserialize",
"Eq",
"Hash",
"Ord",
"PartialEq",
"PartialOrd",
"Serialize",
"Zeroize",
"ZeroizeOnDrop",
]
.join(", ")
}
/// List of available [`SkipGroup`](crate::SkipGroup)s.
fn skip_group_list() -> String {
["Clone", "Debug", "EqHashOrd", "Hash", "Zeroize"].join(", ")
}
/// Unsupported `Zeroize` option if [`Zeroize`](https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html) isn't implemented.
#[cfg(feature = "zeroize")]
pub fn zeroize(span: Span) -> syn::Error {
syn::Error::new(
span,
"`Zeroize` option is only supported if `Zeroize` is being implemented",
)
}
/// Deprecated use of `Zeroize(drop)`.
#[cfg(feature = "zeroize")]
pub fn deprecated_zeroize_drop(span: Span) -> syn::Error {
syn::Error::new(
span,
"`Zeroize(drop)` is deprecated, use `ZeroizeOnDrop` instead",
)
}
}