summaryrefslogtreecommitdiffstats
path: root/vendor/derivative/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /vendor/derivative/src
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/derivative/src')
-rw-r--r--vendor/derivative/src/ast.rs160
-rw-r--r--vendor/derivative/src/attr.rs887
-rw-r--r--vendor/derivative/src/bound.rs175
-rw-r--r--vendor/derivative/src/clone.rs196
-rw-r--r--vendor/derivative/src/cmp.rs407
-rw-r--r--vendor/derivative/src/debug.rs225
-rw-r--r--vendor/derivative/src/default.rs120
-rw-r--r--vendor/derivative/src/hash.rs97
-rw-r--r--vendor/derivative/src/lib.rs94
-rw-r--r--vendor/derivative/src/matcher.rs336
-rw-r--r--vendor/derivative/src/paths.rs10
-rw-r--r--vendor/derivative/src/utils.rs43
12 files changed, 2750 insertions, 0 deletions
diff --git a/vendor/derivative/src/ast.rs b/vendor/derivative/src/ast.rs
new file mode 100644
index 000000000..cf06995fa
--- /dev/null
+++ b/vendor/derivative/src/ast.rs
@@ -0,0 +1,160 @@
+use attr;
+use proc_macro2;
+use syn;
+use syn::spanned::Spanned as SynSpanned;
+
+#[derive(Debug)]
+pub struct Input<'a> {
+ pub attrs: attr::Input,
+ pub body: Body<'a>,
+ pub generics: &'a syn::Generics,
+ pub ident: syn::Ident,
+ pub span: proc_macro2::Span,
+}
+
+#[derive(Debug)]
+pub enum Body<'a> {
+ Enum(Vec<Variant<'a>>),
+ Struct(Style, Vec<Field<'a>>),
+}
+
+#[derive(Debug)]
+pub struct Variant<'a> {
+ pub attrs: attr::Input,
+ pub fields: Vec<Field<'a>>,
+ pub ident: syn::Ident,
+ pub style: Style,
+}
+
+#[derive(Debug)]
+pub struct Field<'a> {
+ pub attrs: attr::Field,
+ pub ident: Option<syn::Ident>,
+ pub ty: &'a syn::Type,
+ pub span: proc_macro2::Span,
+}
+
+#[derive(Clone, Copy, Debug)]
+pub enum Style {
+ Struct,
+ Tuple,
+ Unit,
+}
+
+impl<'a> Input<'a> {
+ pub fn from_ast(
+ item: &'a syn::DeriveInput,
+ errors: &mut proc_macro2::TokenStream,
+ ) -> Result<Input<'a>, ()> {
+ let attrs = attr::Input::from_ast(&item.attrs, errors)?;
+
+ let body = match item.data {
+ syn::Data::Enum(syn::DataEnum { ref variants, .. }) => {
+ Body::Enum(enum_from_ast(variants, errors)?)
+ }
+ syn::Data::Struct(syn::DataStruct { ref fields, .. }) => {
+ let (style, fields) = struct_from_ast(fields, errors)?;
+ Body::Struct(style, fields)
+ }
+ syn::Data::Union(..) => {
+ errors.extend(
+ syn::Error::new_spanned(item, "derivative does not support unions")
+ .to_compile_error(),
+ );
+ return Err(());
+ }
+ };
+
+ Ok(Input {
+ attrs,
+ body,
+ generics: &item.generics,
+ ident: item.ident.clone(),
+ span: item.span(),
+ })
+ }
+
+ /// Checks whether this type is an enum with only unit variants.
+ pub fn is_trivial_enum(&self) -> bool {
+ match &self.body {
+ Body::Enum(e) => e.iter().all(|v| v.is_unit()),
+ Body::Struct(..) => false,
+ }
+ }
+}
+
+impl<'a> Body<'a> {
+ pub fn all_fields(&self) -> Vec<&Field> {
+ match *self {
+ Body::Enum(ref variants) => variants
+ .iter()
+ .flat_map(|variant| variant.fields.iter())
+ .collect(),
+ Body::Struct(_, ref fields) => fields.iter().collect(),
+ }
+ }
+
+ pub fn is_empty(&self) -> bool {
+ match *self {
+ Body::Enum(ref variants) => variants.is_empty(),
+ Body::Struct(_, ref fields) => fields.is_empty(),
+ }
+ }
+}
+
+impl<'a> Variant<'a> {
+ /// Checks whether this variant is a unit variant.
+ pub fn is_unit(&self) -> bool {
+ self.fields.is_empty()
+ }
+}
+
+fn enum_from_ast<'a>(
+ variants: &'a syn::punctuated::Punctuated<syn::Variant, syn::token::Comma>,
+ errors: &mut proc_macro2::TokenStream,
+) -> Result<Vec<Variant<'a>>, ()> {
+ variants
+ .iter()
+ .map(|variant| {
+ let (style, fields) = struct_from_ast(&variant.fields, errors)?;
+ Ok(Variant {
+ attrs: attr::Input::from_ast(&variant.attrs, errors)?,
+ fields,
+ ident: variant.ident.clone(),
+ style,
+ })
+ })
+ .collect()
+}
+
+fn struct_from_ast<'a>(
+ fields: &'a syn::Fields,
+ errors: &mut proc_macro2::TokenStream,
+) -> Result<(Style, Vec<Field<'a>>), ()> {
+ match *fields {
+ syn::Fields::Named(ref fields) => {
+ Ok((Style::Struct, fields_from_ast(&fields.named, errors)?))
+ }
+ syn::Fields::Unnamed(ref fields) => {
+ Ok((Style::Tuple, fields_from_ast(&fields.unnamed, errors)?))
+ }
+ syn::Fields::Unit => Ok((Style::Unit, Vec::new())),
+ }
+}
+
+fn fields_from_ast<'a>(
+ fields: &'a syn::punctuated::Punctuated<syn::Field, syn::token::Comma>,
+ errors: &mut proc_macro2::TokenStream,
+) -> Result<Vec<Field<'a>>, ()> {
+ fields
+ .iter()
+ .map(|field| {
+ Ok(Field {
+ attrs: attr::Field::from_ast(field, errors)?,
+ ident: field.ident.clone(),
+ ty: &field.ty,
+ span: field.span(),
+ })
+ })
+ .collect()
+}
diff --git a/vendor/derivative/src/attr.rs b/vendor/derivative/src/attr.rs
new file mode 100644
index 000000000..01ac740bd
--- /dev/null
+++ b/vendor/derivative/src/attr.rs
@@ -0,0 +1,887 @@
+use proc_macro2;
+use syn;
+use syn::spanned::Spanned;
+
+/// Represent the `derivative` attributes on the input type (`struct`/`enum`).
+#[derive(Debug, Default)]
+pub struct Input {
+ /// Whether `Clone` is present and its specific attributes.
+ pub clone: Option<InputClone>,
+ /// Whether `Copy` is present and its specific attributes.
+ pub copy: Option<InputCopy>,
+ /// Whether `Debug` is present and its specific attributes.
+ pub debug: Option<InputDebug>,
+ /// Whether `Default` is present and its specific attributes.
+ pub default: Option<InputDefault>,
+ /// Whether `Eq` is present and its specific attributes.
+ pub eq: Option<InputEq>,
+ /// Whether `Hash` is present and its specific attributes.
+ pub hash: Option<InputHash>,
+ /// Whether `PartialEq` is present and its specific attributes.
+ pub partial_eq: Option<InputPartialEq>,
+ /// Whether `PartialOrd` is present and its specific attributes.
+ pub partial_ord: Option<InputPartialOrd>,
+ /// Whether `Ord` is present and its specific attributes.
+ pub ord: Option<InputOrd>,
+ pub is_packed: bool,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative` attributes on a field.
+pub struct Field {
+ /// The parameters for `Clone`.
+ clone: FieldClone,
+ /// The parameters for `Copy`.
+ copy_bound: Option<Vec<syn::WherePredicate>>,
+ /// The parameters for `Debug`.
+ debug: FieldDebug,
+ /// The parameters for `Default`.
+ default: FieldDefault,
+ /// The parameters for `Eq`.
+ eq_bound: Option<Vec<syn::WherePredicate>>,
+ /// The parameters for `Hash`.
+ hash: FieldHash,
+ /// The parameters for `PartialEq`.
+ partial_eq: FieldPartialEq,
+ /// The parameters for `PartialOrd`.
+ partial_ord: FieldPartialOrd,
+ /// The parameters for `Ord`.
+ ord: FieldOrd,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(Clone(…))` attributes on an input.
+pub struct InputClone {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// Whether the implementation should have an explicit `clone_from`.
+ pub clone_from: bool,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(Clone(…))` attributes on an input.
+pub struct InputCopy {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(Debug(…))` attributes on an input.
+pub struct InputDebug {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// Whether the type is marked `transparent`.
+ pub transparent: bool,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(Default(…))` attributes on an input.
+pub struct InputDefault {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// Whether the type is marked with `new`.
+ pub new: bool,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(Eq(…))` attributes on an input.
+pub struct InputEq {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(Hash(…))` attributes on an input.
+pub struct InputHash {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(PartialEq(…))` attributes on an input.
+pub struct InputPartialEq {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(PartialOrd(…))` attributes on an input.
+pub struct InputPartialOrd {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// Allow `derivative(PartialOrd)` on enums:
+ on_enum: bool,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(Ord(…))` attributes on an input.
+pub struct InputOrd {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// Allow `derivative(Ord)` on enums:
+ on_enum: bool,
+}
+
+#[derive(Debug, Default)]
+/// Represents the `derivative(Clone(…))` attributes on a field.
+pub struct FieldClone {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// The `clone_with` attribute if present and the path to the cloning function.
+ clone_with: Option<syn::Path>,
+}
+
+#[derive(Debug, Default)]
+/// Represents the `derivative(Debug(…))` attributes on a field.
+pub struct FieldDebug {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// The `format_with` attribute if present and the path to the formatting function.
+ format_with: Option<syn::Path>,
+ /// Whether the field is to be ignored from output.
+ ignore: bool,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(Default(…))` attributes on a field.
+pub struct FieldDefault {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// The default value for the field if present.
+ pub value: Option<proc_macro2::TokenStream>,
+}
+
+#[derive(Debug, Default)]
+/// Represents the `derivative(Hash(…))` attributes on a field.
+pub struct FieldHash {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// The `hash_with` attribute if present and the path to the hashing function.
+ hash_with: Option<syn::Path>,
+ /// Whether the field is to be ignored when hashing.
+ ignore: bool,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(PartialEq(…))` attributes on a field.
+pub struct FieldPartialEq {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// The `compare_with` attribute if present and the path to the comparison function.
+ compare_with: Option<syn::Path>,
+ /// Whether the field is to be ignored when comparing.
+ ignore: bool,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(PartialOrd(…))` attributes on a field.
+pub struct FieldPartialOrd {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// The `compare_with` attribute if present and the path to the comparison function.
+ compare_with: Option<syn::Path>,
+ /// Whether the field is to be ignored when comparing.
+ ignore: bool,
+}
+
+#[derive(Debug, Default)]
+/// Represent the `derivative(Ord(…))` attributes on a field.
+pub struct FieldOrd {
+ /// The `bound` attribute if present and the corresponding bounds.
+ bounds: Option<Vec<syn::WherePredicate>>,
+ /// The `compare_with` attribute if present and the path to the comparison function.
+ compare_with: Option<syn::Path>,
+ /// Whether the field is to be ignored when comparing.
+ ignore: bool,
+}
+
+macro_rules! for_all_attr {
+ ($errors:ident; for ($name:ident, $value:ident) in $attrs:expr; $($body:tt)*) => {
+ for meta_items in $attrs.iter() {
+ let meta_items = derivative_attribute(meta_items, $errors);
+ if let Some(meta_items) = meta_items {
+ for meta_item in meta_items.iter() {
+ let meta_item = read_items(meta_item, $errors);
+ let MetaItem($name, $value) = try!(meta_item);
+ match $name.to_string().as_ref() {
+ $($body)*
+ }
+ }
+ }
+ }
+ };
+}
+
+macro_rules! match_attributes {
+ ($errors:ident for $trait:expr; let Some($name:ident) = $unwrapped:expr; for $value:ident in $values:expr; $($body:tt)* ) => {
+ let mut $name = $unwrapped.take().unwrap_or_default();
+
+ match_attributes! {
+ $errors for $trait;
+ for $value in $values;
+ $($body)*
+ }
+
+ $unwrapped = Some($name);
+ };
+
+ ($errors:ident for $trait:expr; for $value:ident in $values:expr; $($body:tt)* ) => {
+ for (name, $value) in $values {
+ match name {
+ Some(ident) => {
+ match ident.to_string().as_ref() {
+ $($body)*
+ unknown => {
+ let message = format!("Unknown attribute `{}` for trait `{}`", unknown, $trait);
+ $errors.extend(quote_spanned! {ident.span()=>
+ compile_error!(#message);
+ });
+ }
+ }
+ }
+ None => {
+ let value = $value.expect("Expected value to be passed");
+ match value.value().as_ref() {
+ $($body)*
+ unknown => {
+ let message = format!("Unknown attribute `{}` for trait `{}`", unknown, $trait);
+ let span = value.span();
+ $errors.extend(quote_spanned! {span=>
+ compile_error!(#message);
+ });
+ }
+ }
+ }
+ }
+ }
+ };
+}
+
+impl Input {
+ /// Parse the `derivative` attributes on a type.
+ #[allow(clippy::cognitive_complexity)] // mostly macros
+ pub fn from_ast(
+ attrs: &[syn::Attribute],
+ errors: &mut proc_macro2::TokenStream,
+ ) -> Result<Input, ()> {
+ let mut input = Input {
+ is_packed: attrs.iter().any(has_repr_packed_attr),
+ ..Default::default()
+ };
+
+ for_all_attr! {
+ errors;
+ for (name, values) in attrs;
+ "Clone" => {
+ match_attributes! {
+ errors for "Clone";
+ let Some(clone) = input.clone;
+ for value in values;
+ "bound" => parse_bound(&mut clone.bounds, value, errors),
+ "clone_from" => {
+ clone.clone_from = parse_boolean_meta_item(value, true, "clone_from", errors);
+ }
+ }
+ }
+ "Copy" => {
+ match_attributes! {
+ errors for "Copy";
+ let Some(copy) = input.copy;
+ for value in values;
+ "bound" => parse_bound(&mut copy.bounds, value, errors),
+ }
+ }
+ "Debug" => {
+ match_attributes! {
+ errors for "Debug";
+ let Some(debug) = input.debug;
+ for value in values;
+ "bound" => parse_bound(&mut debug.bounds, value, errors),
+ "transparent" => {
+ debug.transparent = parse_boolean_meta_item(value, true, "transparent", errors);
+ }
+ }
+ }
+ "Default" => {
+ match_attributes! {
+ errors for "Default";
+ let Some(default) = input.default;
+ for value in values;
+ "bound" => parse_bound(&mut default.bounds, value, errors),
+ "new" => {
+ default.new = parse_boolean_meta_item(value, true, "new", errors);
+ }
+ }
+ }
+ "Eq" => {
+ match_attributes! {
+ errors for "Eq";
+ let Some(eq) = input.eq;
+ for value in values;
+ "bound" => parse_bound(&mut eq.bounds, value, errors),
+ }
+ }
+ "Hash" => {
+ match_attributes! {
+ errors for "Hash";
+ let Some(hash) = input.hash;
+ for value in values;
+ "bound" => parse_bound(&mut hash.bounds, value, errors),
+ }
+ }
+ "PartialEq" => {
+ match_attributes! {
+ errors for "PartialEq";
+ let Some(partial_eq) = input.partial_eq;
+ for value in values;
+ "bound" => parse_bound(&mut partial_eq.bounds, value, errors),
+ "feature_allow_slow_enum" => (), // backward compatibility, now unnecessary
+ }
+ }
+ "PartialOrd" => {
+ match_attributes! {
+ errors for "PartialOrd";
+ let Some(partial_ord) = input.partial_ord;
+ for value in values;
+ "bound" => parse_bound(&mut partial_ord.bounds, value, errors),
+ "feature_allow_slow_enum" => {
+ partial_ord.on_enum = parse_boolean_meta_item(value, true, "feature_allow_slow_enum", errors);
+ }
+ }
+ }
+ "Ord" => {
+ match_attributes! {
+ errors for "Ord";
+ let Some(ord) = input.ord;
+ for value in values;
+ "bound" => parse_bound(&mut ord.bounds, value, errors),
+ "feature_allow_slow_enum" => {
+ ord.on_enum = parse_boolean_meta_item(value, true, "feature_allow_slow_enum", errors);
+ }
+ }
+ }
+ unknown => {
+ let message = format!("deriving `{}` is not supported by derivative", unknown);
+ errors.extend(quote_spanned! {name.span()=>
+ compile_error!(#message);
+ });
+ }
+ }
+
+ Ok(input)
+ }
+
+ pub fn clone_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.clone
+ .as_ref()
+ .and_then(|d| d.bounds.as_ref().map(Vec::as_slice))
+ }
+
+ pub fn clone_from(&self) -> bool {
+ self.clone.as_ref().map_or(false, |d| d.clone_from)
+ }
+
+ pub fn copy_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.copy
+ .as_ref()
+ .and_then(|d| d.bounds.as_ref().map(Vec::as_slice))
+ }
+
+ pub fn debug_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.debug
+ .as_ref()
+ .and_then(|d| d.bounds.as_ref().map(Vec::as_slice))
+ }
+
+ pub fn debug_transparent(&self) -> bool {
+ self.debug.as_ref().map_or(false, |d| d.transparent)
+ }
+
+ pub fn default_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.default
+ .as_ref()
+ .and_then(|d| d.bounds.as_ref().map(Vec::as_slice))
+ }
+
+ pub fn eq_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.eq
+ .as_ref()
+ .and_then(|d| d.bounds.as_ref().map(Vec::as_slice))
+ }
+
+ pub fn hash_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.hash
+ .as_ref()
+ .and_then(|d| d.bounds.as_ref().map(Vec::as_slice))
+ }
+
+ pub fn partial_eq_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.partial_eq
+ .as_ref()
+ .and_then(|d| d.bounds.as_ref().map(Vec::as_slice))
+ }
+
+ pub fn partial_ord_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.partial_ord
+ .as_ref()
+ .and_then(|d| d.bounds.as_ref().map(Vec::as_slice))
+ }
+
+ pub fn ord_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.ord
+ .as_ref()
+ .and_then(|d| d.bounds.as_ref().map(Vec::as_slice))
+ }
+
+ pub fn partial_ord_on_enum(&self) -> bool {
+ self.partial_ord.as_ref().map_or(false, |d| d.on_enum)
+ }
+
+ pub fn ord_on_enum(&self) -> bool {
+ self.ord.as_ref().map_or(false, |d| d.on_enum)
+ }
+}
+
+impl Field {
+ /// Parse the `derivative` attributes on a type.
+ #[allow(clippy::cognitive_complexity)] // mostly macros
+ pub fn from_ast(
+ field: &syn::Field,
+ errors: &mut proc_macro2::TokenStream,
+ ) -> Result<Field, ()> {
+ let mut out = Field::default();
+
+ for_all_attr! {
+ errors;
+ for (name, values) in field.attrs;
+ "Clone" => {
+ match_attributes! {
+ errors for "Clone";
+ for value in values;
+ "bound" => parse_bound(&mut out.clone.bounds, value, errors),
+ "clone_with" => {
+ let path = value.expect("`clone_with` needs a value");
+ out.clone.clone_with = parse_str_lit(&path, errors).ok();
+ }
+ }
+ }
+ "Debug" => {
+ match_attributes! {
+ errors for "Debug";
+ for value in values;
+ "bound" => parse_bound(&mut out.debug.bounds, value, errors),
+ "format_with" => {
+ let path = value.expect("`format_with` needs a value");
+ out.debug.format_with = parse_str_lit(&path, errors).ok();
+ }
+ "ignore" => {
+ out.debug.ignore = parse_boolean_meta_item(value, true, "ignore", errors);
+ }
+ }
+ }
+ "Default" => {
+ match_attributes! {
+ errors for "Default";
+ for value in values;
+ "bound" => parse_bound(&mut out.default.bounds, value, errors),
+ "value" => {
+ let value = value.expect("`value` needs a value");
+ out.default.value = parse_str_lit(&value, errors).ok();
+ }
+ }
+ }
+ "Eq" => {
+ match_attributes! {
+ errors for "Eq";
+ for value in values;
+ "bound" => parse_bound(&mut out.eq_bound, value, errors),
+ }
+ }
+ "Hash" => {
+ match_attributes! {
+ errors for "Hash";
+ for value in values;
+ "bound" => parse_bound(&mut out.hash.bounds, value, errors),
+ "hash_with" => {
+ let path = value.expect("`hash_with` needs a value");
+ out.hash.hash_with = parse_str_lit(&path, errors).ok();
+ }
+ "ignore" => {
+ out.hash.ignore = parse_boolean_meta_item(value, true, "ignore", errors);
+ }
+ }
+ }
+ "PartialEq" => {
+ match_attributes! {
+ errors for "PartialEq";
+ for value in values;
+ "bound" => parse_bound(&mut out.partial_eq.bounds, value, errors),
+ "compare_with" => {
+ let path = value.expect("`compare_with` needs a value");
+ out.partial_eq.compare_with = parse_str_lit(&path, errors).ok();
+ }
+ "ignore" => {
+ out.partial_eq.ignore = parse_boolean_meta_item(value, true, "ignore", errors);
+ }
+ }
+ }
+ "PartialOrd" => {
+ match_attributes! {
+ errors for "PartialOrd";
+ for value in values;
+ "bound" => parse_bound(&mut out.partial_ord.bounds, value, errors),
+ "compare_with" => {
+ let path = value.expect("`compare_with` needs a value");
+ out.partial_ord.compare_with = parse_str_lit(&path, errors).ok();
+ }
+ "ignore" => {
+ out.partial_ord.ignore = parse_boolean_meta_item(value, true, "ignore", errors);
+ }
+ }
+ }
+ "Ord" => {
+ match_attributes! {
+ errors for "Ord";
+ for value in values;
+ "bound" => parse_bound(&mut out.ord.bounds, value, errors),
+ "compare_with" => {
+ let path = value.expect("`compare_with` needs a value");
+ out.ord.compare_with = parse_str_lit(&path, errors).ok();
+ }
+ "ignore" => {
+ out.ord.ignore = parse_boolean_meta_item(value, true, "ignore", errors);
+ }
+ }
+ }
+ unknown => {
+ let message = format!("deriving `{}` is not supported by derivative", unknown);
+ errors.extend(quote_spanned! {name.span()=>
+ compile_error!(#message);
+ });
+ }
+ }
+
+ Ok(out)
+ }
+
+ pub fn clone_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.clone.bounds.as_ref().map(Vec::as_slice)
+ }
+
+ pub fn clone_with(&self) -> Option<&syn::Path> {
+ self.clone.clone_with.as_ref()
+ }
+
+ pub fn copy_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.copy_bound.as_ref().map(Vec::as_slice)
+ }
+
+ pub fn debug_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.debug.bounds.as_ref().map(Vec::as_slice)
+ }
+
+ pub fn debug_format_with(&self) -> Option<&syn::Path> {
+ self.debug.format_with.as_ref()
+ }
+
+ pub fn ignore_debug(&self) -> bool {
+ self.debug.ignore
+ }
+
+ pub fn ignore_hash(&self) -> bool {
+ self.hash.ignore
+ }
+
+ pub fn default_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.default.bounds.as_ref().map(Vec::as_slice)
+ }
+
+ pub fn default_value(&self) -> Option<&proc_macro2::TokenStream> {
+ self.default.value.as_ref()
+ }
+
+ pub fn eq_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.eq_bound.as_ref().map(Vec::as_slice)
+ }
+
+ pub fn hash_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.hash.bounds.as_ref().map(Vec::as_slice)
+ }
+
+ pub fn hash_with(&self) -> Option<&syn::Path> {
+ self.hash.hash_with.as_ref()
+ }
+
+ pub fn partial_eq_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.partial_eq.bounds.as_ref().map(Vec::as_slice)
+ }
+
+ pub fn partial_ord_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.partial_ord.bounds.as_ref().map(Vec::as_slice)
+ }
+
+ pub fn ord_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.ord.bounds.as_ref().map(Vec::as_slice)
+ }
+
+ pub fn partial_eq_compare_with(&self) -> Option<&syn::Path> {
+ self.partial_eq.compare_with.as_ref()
+ }
+
+ pub fn partial_ord_compare_with(&self) -> Option<&syn::Path> {
+ self.partial_ord.compare_with.as_ref()
+ }
+
+ pub fn ord_compare_with(&self) -> Option<&syn::Path> {
+ self.ord.compare_with.as_ref()
+ }
+
+ pub fn ignore_partial_eq(&self) -> bool {
+ self.partial_eq.ignore
+ }
+
+ pub fn ignore_partial_ord(&self) -> bool {
+ self.partial_ord.ignore
+ }
+
+ pub fn ignore_ord(&self) -> bool {
+ self.ord.ignore
+ }
+}
+
+/// Represent an attribute.
+///
+/// We only have a limited set of possible attributes:
+///
+/// * `#[derivative(Debug)]` is represented as `(Debug, [])`;
+/// * `#[derivative(Debug="foo")]` is represented as `(Debug, [(None, Some("foo"))])`;
+/// * `#[derivative(Debug(foo="bar")]` is represented as `(Debug, [(Some(foo), Some("bar"))])`.
+struct MetaItem<'a>(
+ &'a syn::Ident,
+ Vec<(Option<&'a syn::Ident>, Option<&'a syn::LitStr>)>,
+);
+
+/// Parse an arbitrary item for our limited `MetaItem` subset.
+fn read_items<'a>(item: &'a syn::NestedMeta, errors: &mut proc_macro2::TokenStream) -> Result<MetaItem<'a>, ()> {
+ let item = match *item {
+ syn::NestedMeta::Meta(ref item) => item,
+ syn::NestedMeta::Lit(ref lit) => {
+ errors.extend(quote_spanned! {lit.span()=>
+ compile_error!("expected meta-item but found literal");
+ });
+
+ return Err(());
+ }
+ };
+ match *item {
+ syn::Meta::Path(ref path) => match path.get_ident() {
+ Some(name) => Ok(MetaItem(name, Vec::new())),
+ None => {
+ errors.extend(quote_spanned! {path.span()=>
+ compile_error!("expected derivative attribute to be a string, but found a path");
+ });
+
+ Err(())
+ }
+ },
+ syn::Meta::List(syn::MetaList {
+ ref path,
+ nested: ref values,
+ ..
+ }) => {
+ let values = values
+ .iter()
+ .map(|value| {
+ if let syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
+ ref path,
+ lit: ref value,
+ ..
+ })) = *value
+ {
+ let (name, value) = ensure_str_lit(&path, &value, errors)?;
+
+ Ok((Some(name), Some(value)))
+ } else {
+ errors.extend(quote_spanned! {value.span()=>
+ compile_error!("expected named value");
+ });
+
+ Err(())
+ }
+ })
+ .collect::<Result<_, _>>()?;
+
+ let name = match path.get_ident() {
+ Some(name) => name,
+ None => {
+ errors.extend(quote_spanned! {path.span()=>
+ compile_error!("expected derivative attribute to be a string, but found a path");
+ });
+
+ return Err(());
+ }
+ };
+
+ Ok(MetaItem(name, values))
+ }
+ syn::Meta::NameValue(syn::MetaNameValue {
+ ref path,
+ lit: ref value,
+ ..
+ }) => {
+ let (name, value) = ensure_str_lit(&path, &value, errors)?;
+
+ Ok(MetaItem(name, vec![(None, Some(value))]))
+ }
+ }
+}
+
+/// Filter the `derivative` items from an attribute.
+fn derivative_attribute(
+ attribute: &syn::Attribute,
+ errors: &mut proc_macro2::TokenStream,
+) -> Option<syn::punctuated::Punctuated<syn::NestedMeta, syn::token::Comma>> {
+ if !attribute.path.is_ident("derivative") {
+ return None;
+ }
+ match attribute.parse_meta() {
+ Ok(syn::Meta::List(meta_list)) => Some(meta_list.nested),
+ Ok(_) => None,
+ Err(e) => {
+ let message = format!("invalid attribute: {}", e);
+ errors.extend(quote_spanned! {e.span()=>
+ compile_error!(#message);
+ });
+
+ None
+ }
+ }
+}
+
+/// Parse an item value as a boolean. Accepted values are the string literal `"true"` and
+/// `"false"`. The `default` parameter specifies what the value of the boolean is when only its
+/// name is specified (eg. `Debug="ignore"` is equivalent to `Debug(ignore="true")`). The `name`
+/// parameter is used for error reporting.
+fn parse_boolean_meta_item(
+ item: Option<&syn::LitStr>,
+ default: bool,
+ name: &str,
+ errors: &mut proc_macro2::TokenStream,
+) -> bool {
+ if let Some(item) = item.as_ref() {
+ match item.value().as_ref() {
+ "true" => true,
+ "false" => false,
+ val => {
+ if val == name {
+ true
+ } else {
+ let message = format!(
+ r#"expected `"true"` or `"false"` for `{}`, got `{}`"#,
+ name, val
+ );
+ errors.extend(quote_spanned! {item.span()=>
+ compile_error!(#message);
+ });
+
+ default
+ }
+ }
+ }
+ } else {
+ default
+ }
+}
+
+/// Parse a `bound` item.
+fn parse_bound(
+ opt_bounds: &mut Option<Vec<syn::WherePredicate>>,
+ value: Option<&syn::LitStr>,
+ errors: &mut proc_macro2::TokenStream,
+) {
+ let bound = value.expect("`bound` needs a value");
+ let bound_value = bound.value();
+
+ *opt_bounds = if !bound_value.is_empty() {
+ let where_string = syn::LitStr::new(&format!("where {}", bound_value), bound.span());
+
+ let bounds = parse_str_lit::<syn::WhereClause>(&where_string, errors)
+ .map(|wh| wh.predicates.into_iter().collect());
+
+ match bounds {
+ Ok(bounds) => Some(bounds),
+ Err(_) => {
+ errors.extend(quote_spanned! {where_string.span()=>
+ compile_error!("could not parse bound");
+ });
+
+ None
+ }
+ }
+ } else {
+ Some(vec![])
+ };
+}
+
+fn parse_str_lit<T>(value: &syn::LitStr, errors: &mut proc_macro2::TokenStream) -> Result<T, ()>
+where
+ T: syn::parse::Parse,
+{
+ match value.parse() {
+ Ok(value) => Ok(value),
+ Err(e) => {
+ let message = format!("could not parse string literal: {}", e);
+ errors.extend(quote_spanned! {value.span()=>
+ compile_error!(#message);
+ });
+ Err(())
+ }
+ }
+}
+
+fn ensure_str_lit<'a>(
+ attr_path: &'a syn::Path,
+ lit: &'a syn::Lit,
+ errors: &mut proc_macro2::TokenStream,
+) -> Result<(&'a syn::Ident, &'a syn::LitStr), ()> {
+ let attr_name = match attr_path.get_ident() {
+ Some(attr_name) => attr_name,
+ None => {
+ errors.extend(quote_spanned! {attr_path.span()=>
+ compile_error!("expected derivative attribute to be a string, but found a path");
+ });
+ return Err(());
+ }
+ };
+
+ if let syn::Lit::Str(ref lit) = *lit {
+ Ok((attr_name, lit))
+ } else {
+ let message = format!(
+ "expected derivative {} attribute to be a string: `{} = \"...\"`",
+ attr_name, attr_name
+ );
+ errors.extend(quote_spanned! {lit.span()=>
+ compile_error!(#message);
+ });
+ Err(())
+ }
+}
+
+pub fn has_repr_packed_attr(attr: &syn::Attribute) -> bool {
+ if let Ok(attr) = attr.parse_meta() {
+ if attr.path().get_ident().map(|i| i == "repr") == Some(true) {
+ if let syn::Meta::List(items) = attr {
+ for item in items.nested {
+ if let syn::NestedMeta::Meta(item) = item {
+ if item.path().get_ident().map(|i| i == "packed") == Some(true) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ false
+}
diff --git a/vendor/derivative/src/bound.rs b/vendor/derivative/src/bound.rs
new file mode 100644
index 000000000..4c1361c0a
--- /dev/null
+++ b/vendor/derivative/src/bound.rs
@@ -0,0 +1,175 @@
+/* This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright 2016 The serde Developers. See
+ * https://github.com/serde-rs/serde/blob/3f28a9324042950afa80354722aeeee1a55cbfa3/README.md#license.
+ *
+ * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+ * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+ * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+ * option. This file may not be copied, modified, or distributed
+ * except according to those terms.
+ */
+
+use ast;
+use attr;
+use std::collections::HashSet;
+use syn::{self, visit, GenericParam};
+
+// use internals::ast::Item;
+// use internals::attr;
+
+/// Remove the default from every type parameter because in the generated `impl`s
+/// they look like associated types: "error: associated type bindings are not
+/// allowed here".
+pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
+ syn::Generics {
+ params: generics
+ .params
+ .iter()
+ .map(|generic_param| match *generic_param {
+ GenericParam::Type(ref ty_param) => syn::GenericParam::Type(syn::TypeParam {
+ default: None,
+ ..ty_param.clone()
+ }),
+ ref param => param.clone(),
+ })
+ .collect(),
+ ..generics.clone()
+ }
+}
+
+pub fn with_where_predicates(
+ generics: &syn::Generics,
+ predicates: &[syn::WherePredicate],
+) -> syn::Generics {
+ let mut cloned = generics.clone();
+ cloned
+ .make_where_clause()
+ .predicates
+ .extend(predicates.iter().cloned());
+ cloned
+}
+
+pub fn with_where_predicates_from_fields<F>(
+ item: &ast::Input,
+ generics: &syn::Generics,
+ from_field: F,
+) -> syn::Generics
+where
+ F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
+{
+ let mut cloned = generics.clone();
+ {
+ let fields = item.body.all_fields();
+ let field_where_predicates = fields
+ .iter()
+ .flat_map(|field| from_field(&field.attrs))
+ .flat_map(|predicates| predicates.to_vec());
+
+ cloned
+ .make_where_clause()
+ .predicates
+ .extend(field_where_predicates);
+ }
+ cloned
+}
+
+/// Puts the given bound on any generic type parameters that are used in fields
+/// for which filter returns true.
+///
+/// For example, the following structure needs the bound `A: Debug, B: Debug`.
+///
+/// ```ignore
+/// struct S<'b, A, B: 'b, C> {
+/// a: A,
+/// b: Option<&'b B>
+/// #[derivative(Debug="ignore")]
+/// c: C,
+/// }
+/// ```
+pub fn with_bound<F>(
+ item: &ast::Input,
+ generics: &syn::Generics,
+ filter: F,
+ bound: &syn::Path,
+) -> syn::Generics
+where
+ F: Fn(&attr::Field) -> bool,
+{
+ #[derive(Debug)]
+ struct FindTyParams {
+ /// Set of all generic type parameters on the current struct (A, B, C in
+ /// the example). Initialized up front.
+ all_ty_params: HashSet<syn::Ident>,
+ /// Set of generic type parameters used in fields for which filter
+ /// returns true (A and B in the example). Filled in as the visitor sees
+ /// them.
+ relevant_ty_params: HashSet<syn::Ident>,
+ }
+ impl<'ast> visit::Visit<'ast> for FindTyParams {
+ fn visit_path(&mut self, path: &'ast syn::Path) {
+ if is_phantom_data(path) {
+ // Hardcoded exception, because `PhantomData<T>` implements
+ // most traits whether or not `T` implements it.
+ return;
+ }
+ if path.leading_colon.is_none() && path.segments.len() == 1 {
+ let id = &path.segments[0].ident;
+ if self.all_ty_params.contains(id) {
+ self.relevant_ty_params.insert(id.clone());
+ }
+ }
+ visit::visit_path(self, path);
+ }
+ }
+
+ let all_ty_params: HashSet<_> = generics
+ .type_params()
+ .map(|ty_param| ty_param.ident.clone())
+ .collect();
+
+ let relevant_tys = item
+ .body
+ .all_fields()
+ .into_iter()
+ .filter(|field| {
+ if let syn::Type::Path(syn::TypePath { ref path, .. }) = *field.ty {
+ !is_phantom_data(path)
+ } else {
+ true
+ }
+ })
+ .filter(|field| filter(&field.attrs))
+ .map(|field| &field.ty);
+
+ let mut visitor = FindTyParams {
+ all_ty_params,
+ relevant_ty_params: HashSet::new(),
+ };
+ for ty in relevant_tys {
+ visit::visit_type(&mut visitor, ty);
+ }
+
+ let mut cloned = generics.clone();
+ {
+ let relevant_where_predicates = generics
+ .type_params()
+ .map(|ty_param| &ty_param.ident)
+ .filter(|id| visitor.relevant_ty_params.contains(id))
+ .map(|id| -> syn::WherePredicate { parse_quote!( #id : #bound ) });
+
+ cloned
+ .make_where_clause()
+ .predicates
+ .extend(relevant_where_predicates);
+ }
+ cloned
+}
+
+#[allow(clippy::match_like_matches_macro)] // needs rustc 1.42
+fn is_phantom_data(path: &syn::Path) -> bool {
+ match path.segments.last() {
+ Some(path) if path.ident == "PhantomData" => true,
+ _ => false,
+ }
+}
diff --git a/vendor/derivative/src/clone.rs b/vendor/derivative/src/clone.rs
new file mode 100644
index 000000000..3594e9498
--- /dev/null
+++ b/vendor/derivative/src/clone.rs
@@ -0,0 +1,196 @@
+use proc_macro2;
+
+use ast;
+use attr;
+use matcher;
+use syn;
+use utils;
+
+/// Derive `Copy` for `input`.
+pub fn derive_copy(input: &ast::Input) -> proc_macro2::TokenStream {
+ let name = &input.ident;
+
+ let copy_trait_path = copy_trait_path();
+ let generics = utils::build_impl_generics(
+ input,
+ &copy_trait_path,
+ |attrs| attrs.copy_bound().is_none(),
+ |field| field.copy_bound(),
+ |input| input.copy_bound(),
+ );
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ quote! {
+ #[allow(unused_qualifications)]
+ impl #impl_generics #copy_trait_path for #name #ty_generics #where_clause {}
+ }
+}
+
+/// Derive `Clone` for `input`.
+pub fn derive_clone(input: &ast::Input) -> proc_macro2::TokenStream {
+ let name = &input.ident;
+
+ let clone_trait_path = clone_trait_path();
+ let generics = utils::build_impl_generics(
+ input,
+ &clone_trait_path,
+ needs_clone_bound,
+ |field| field.clone_bound(),
+ |input| input.clone_bound(),
+ );
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let is_copy = input.attrs.copy.is_some();
+ if is_copy && input.generics.type_params().count() == 0 {
+ quote! {
+ #[allow(unused_qualifications)]
+ impl #impl_generics #clone_trait_path for #name #ty_generics #where_clause {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ }
+ } else {
+ let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed).build_arms(
+ input,
+ "__arg",
+ |arm_path, _, _, style, _, bis| {
+ let field_clones = bis.iter().map(|bi| {
+ let arg = &bi.expr;
+
+ let clone = if let Some(clone_with) = bi.field.attrs.clone_with() {
+ quote!(#clone_with(&#arg))
+ } else {
+ quote!(#arg.clone())
+ };
+
+ if let Some(ref name) = bi.field.ident {
+ quote! {
+ #name: #clone
+ }
+ } else {
+ clone
+ }
+ });
+
+ match style {
+ ast::Style::Struct => {
+ quote! {
+ #arm_path {
+ #(#field_clones),*
+ }
+ }
+ }
+ ast::Style::Tuple => {
+ quote! {
+ #arm_path (#(#field_clones),*)
+ }
+ }
+ ast::Style::Unit => {
+ quote! {
+ #arm_path
+ }
+ }
+ }
+ },
+ );
+
+ let clone_from = if input.attrs.clone_from() {
+ Some(
+ matcher::Matcher::new(matcher::BindingStyle::RefMut, input.attrs.is_packed).build_arms(
+ input,
+ "__arg",
+ |outer_arm_path, _, _, _, _, outer_bis| {
+ let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed).build_arms(
+ input,
+ "__other",
+ |inner_arm_path, _, _, _, _, inner_bis| {
+ if outer_arm_path == inner_arm_path {
+ let field_clones = outer_bis.iter().zip(inner_bis).map(
+ |(outer_bi, inner_bi)| {
+ let outer = &outer_bi.expr;
+ let inner = &inner_bi.expr;
+
+ quote!(#outer.clone_from(&#inner);)
+ },
+ );
+
+ quote! {
+ #(#field_clones)*
+ return;
+ }
+ } else {
+ quote!()
+ }
+ },
+ );
+
+ quote! {
+ match *other {
+ #body
+ }
+ }
+ },
+ ),
+ )
+ } else {
+ None
+ };
+
+ let clone_from = clone_from.map(|body| {
+ // Enumerations are only cloned-from if both variants are the same.
+ // If they are different, fallback to normal cloning.
+ let fallback = if let ast::Body::Enum(_) = input.body {
+ Some(quote!(*self = other.clone();))
+ } else {
+ None
+ };
+
+ quote! {
+ #[allow(clippy::needless_return)]
+ fn clone_from(&mut self, other: &Self) {
+ match *self {
+ #body
+ }
+
+ #fallback
+ }
+ }
+ });
+
+ quote! {
+ #[allow(unused_qualifications)]
+ impl #impl_generics #clone_trait_path for #name #ty_generics #where_clause {
+ fn clone(&self) -> Self {
+ match *self {
+ #body
+ }
+ }
+
+ #clone_from
+ }
+ }
+ }
+}
+
+fn needs_clone_bound(attrs: &attr::Field) -> bool {
+ attrs.clone_bound().is_none()
+}
+
+/// Return the path of the `Clone` trait, that is `::std::clone::Clone`.
+fn clone_trait_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::clone::Clone)
+ } else {
+ parse_quote!(::std::clone::Clone)
+ }
+}
+
+/// Return the path of the `Copy` trait, that is `::std::marker::Copy`.
+fn copy_trait_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::marker::Copy)
+ } else {
+ parse_quote!(::std::marker::Copy)
+ }
+}
diff --git a/vendor/derivative/src/cmp.rs b/vendor/derivative/src/cmp.rs
new file mode 100644
index 000000000..573c5fa79
--- /dev/null
+++ b/vendor/derivative/src/cmp.rs
@@ -0,0 +1,407 @@
+// https://github.com/rust-lang/rust/issues/13101
+
+use ast;
+use attr;
+use matcher;
+use paths;
+use proc_macro2;
+use syn;
+use utils;
+
+/// Derive `Eq` for `input`.
+pub fn derive_eq(input: &ast::Input) -> proc_macro2::TokenStream {
+ let name = &input.ident;
+
+ let eq_trait_path = eq_trait_path();
+ let generics = utils::build_impl_generics(
+ input,
+ &eq_trait_path,
+ needs_eq_bound,
+ |field| field.eq_bound(),
+ |input| input.eq_bound(),
+ );
+ let new_where_clause;
+ let (impl_generics, ty_generics, mut where_clause) = generics.split_for_impl();
+
+ if let Some(new_where_clause2) =
+ maybe_add_copy(input, where_clause, |f| !f.attrs.ignore_partial_eq())
+ {
+ new_where_clause = new_where_clause2;
+ where_clause = Some(&new_where_clause);
+ }
+
+ quote! {
+ #[allow(unused_qualifications)]
+ impl #impl_generics #eq_trait_path for #name #ty_generics #where_clause {}
+ }
+}
+
+/// Derive `PartialEq` for `input`.
+pub fn derive_partial_eq(input: &ast::Input) -> proc_macro2::TokenStream {
+ let discriminant_cmp = if let ast::Body::Enum(_) = input.body {
+ let discriminant_path = paths::discriminant_path();
+
+ quote!((#discriminant_path(&*self) == #discriminant_path(&*other)))
+ } else {
+ quote!(true)
+ };
+
+ let name = &input.ident;
+
+ let partial_eq_trait_path = partial_eq_trait_path();
+ let generics = utils::build_impl_generics(
+ input,
+ &partial_eq_trait_path,
+ needs_partial_eq_bound,
+ |field| field.partial_eq_bound(),
+ |input| input.partial_eq_bound(),
+ );
+ let new_where_clause;
+ let (impl_generics, ty_generics, mut where_clause) = generics.split_for_impl();
+
+ let match_fields = if input.is_trivial_enum() {
+ quote!(true)
+ } else {
+ matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed)
+ .with_field_filter(|f: &ast::Field| !f.attrs.ignore_partial_eq())
+ .build_2_arms(
+ (quote!(*self), quote!(*other)),
+ (input, "__self"),
+ (input, "__other"),
+ |_, _, _, (left_variant, right_variant)| {
+ let cmp = left_variant.iter().zip(&right_variant).map(|(o, i)| {
+ let outer_name = &o.expr;
+ let inner_name = &i.expr;
+
+ if o.field.attrs.ignore_partial_eq() {
+ None
+ } else if let Some(compare_fn) = o.field.attrs.partial_eq_compare_with() {
+ Some(quote!(&& #compare_fn(&#outer_name, &#inner_name)))
+ } else {
+ Some(quote!(&& &#outer_name == &#inner_name))
+ }
+ });
+
+ quote!(true #(#cmp)*)
+ },
+ )
+ };
+
+ if let Some(new_where_clause2) =
+ maybe_add_copy(input, where_clause, |f| !f.attrs.ignore_partial_eq())
+ {
+ new_where_clause = new_where_clause2;
+ where_clause = Some(&new_where_clause);
+ }
+
+ quote! {
+ #[allow(unused_qualifications)]
+ #[allow(clippy::unneeded_field_pattern)]
+ impl #impl_generics #partial_eq_trait_path for #name #ty_generics #where_clause {
+ fn eq(&self, other: &Self) -> bool {
+ #discriminant_cmp && #match_fields
+ }
+ }
+ }
+}
+
+/// Derive `PartialOrd` for `input`.
+pub fn derive_partial_ord(
+ input: &ast::Input,
+ errors: &mut proc_macro2::TokenStream,
+) -> proc_macro2::TokenStream {
+ if let ast::Body::Enum(_) = input.body {
+ if !input.attrs.partial_ord_on_enum() {
+ let message = "can't use `#[derivative(PartialOrd)]` on an enumeration without \
+ `feature_allow_slow_enum`; see the documentation for more details";
+ errors.extend(syn::Error::new(input.span, message).to_compile_error());
+ }
+ }
+
+ let option_path = option_path();
+ let ordering_path = ordering_path();
+
+ let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed)
+ .with_field_filter(|f: &ast::Field| !f.attrs.ignore_partial_ord())
+ .build_arms(input, "__self", |_, n, _, _, _, outer_bis| {
+ let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed)
+ .with_field_filter(|f: &ast::Field| !f.attrs.ignore_partial_ord())
+ .build_arms(input, "__other", |_, m, _, _, _, inner_bis| {
+ match n.cmp(&m) {
+ ::std::cmp::Ordering::Less => {
+ quote!(#option_path::Some(#ordering_path::Less))
+ }
+ ::std::cmp::Ordering::Greater => {
+ quote!(#option_path::Some(#ordering_path::Greater))
+ }
+ ::std::cmp::Ordering::Equal => {
+ let equal_path = quote!(#ordering_path::Equal);
+ outer_bis
+ .iter()
+ .rev()
+ .zip(inner_bis.into_iter().rev())
+ .fold(quote!(#option_path::Some(#equal_path)), |acc, (o, i)| {
+ let outer_name = &o.expr;
+ let inner_name = &i.expr;
+
+ if o.field.attrs.ignore_partial_ord() {
+ acc
+ } else {
+ let cmp_fn = o
+ .field
+ .attrs
+ .partial_ord_compare_with()
+ .map(|f| quote!(#f))
+ .unwrap_or_else(|| {
+ let path = partial_ord_trait_path();
+ quote!(#path::partial_cmp)
+ });
+
+ quote!(match #cmp_fn(&#outer_name, &#inner_name) {
+ #option_path::Some(#equal_path) => #acc,
+ __derive_ordering_other => __derive_ordering_other,
+ })
+ }
+ })
+ }
+ }
+ });
+
+ quote! {
+ match *other {
+ #body
+ }
+
+ }
+ });
+
+ let name = &input.ident;
+
+ let partial_ord_trait_path = partial_ord_trait_path();
+ let generics = utils::build_impl_generics(
+ input,
+ &partial_ord_trait_path,
+ needs_partial_ord_bound,
+ |field| field.partial_ord_bound(),
+ |input| input.partial_ord_bound(),
+ );
+ let new_where_clause;
+ let (impl_generics, ty_generics, mut where_clause) = generics.split_for_impl();
+
+ if let Some(new_where_clause2) =
+ maybe_add_copy(input, where_clause, |f| !f.attrs.ignore_partial_ord())
+ {
+ new_where_clause = new_where_clause2;
+ where_clause = Some(&new_where_clause);
+ }
+
+ quote! {
+ #[allow(unused_qualifications)]
+ #[allow(clippy::unneeded_field_pattern)]
+ impl #impl_generics #partial_ord_trait_path for #name #ty_generics #where_clause {
+ fn partial_cmp(&self, other: &Self) -> #option_path<#ordering_path> {
+ match *self {
+ #body
+ }
+ }
+ }
+ }
+}
+
+/// Derive `Ord` for `input`.
+pub fn derive_ord(
+ input: &ast::Input,
+ errors: &mut proc_macro2::TokenStream,
+) -> proc_macro2::TokenStream {
+ if let ast::Body::Enum(_) = input.body {
+ if !input.attrs.ord_on_enum() {
+ let message = "can't use `#[derivative(Ord)]` on an enumeration without \
+ `feature_allow_slow_enum`; see the documentation for more details";
+ errors.extend(syn::Error::new(input.span, message).to_compile_error());
+ }
+ }
+
+ let ordering_path = ordering_path();
+
+ let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed)
+ .with_field_filter(|f: &ast::Field| !f.attrs.ignore_ord())
+ .build_arms(input, "__self", |_, n, _, _, _, outer_bis| {
+ let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed)
+ .with_field_filter(|f: &ast::Field| !f.attrs.ignore_ord())
+ .build_arms(input, "__other", |_, m, _, _, _, inner_bis| {
+ match n.cmp(&m) {
+ ::std::cmp::Ordering::Less => quote!(#ordering_path::Less),
+ ::std::cmp::Ordering::Greater => quote!(#ordering_path::Greater),
+ ::std::cmp::Ordering::Equal => {
+ let equal_path = quote!(#ordering_path::Equal);
+ outer_bis
+ .iter()
+ .rev()
+ .zip(inner_bis.into_iter().rev())
+ .fold(quote!(#equal_path), |acc, (o, i)| {
+ let outer_name = &o.expr;
+ let inner_name = &i.expr;
+
+ if o.field.attrs.ignore_ord() {
+ acc
+ } else {
+ let cmp_fn = o
+ .field
+ .attrs
+ .ord_compare_with()
+ .map(|f| quote!(#f))
+ .unwrap_or_else(|| {
+ let path = ord_trait_path();
+ quote!(#path::cmp)
+ });
+
+ quote!(match #cmp_fn(&#outer_name, &#inner_name) {
+ #equal_path => #acc,
+ __derive_ordering_other => __derive_ordering_other,
+ })
+ }
+ })
+ }
+ }
+ });
+
+ quote! {
+ match *other {
+ #body
+ }
+
+ }
+ });
+
+ let name = &input.ident;
+
+ let ord_trait_path = ord_trait_path();
+ let generics = utils::build_impl_generics(
+ input,
+ &ord_trait_path,
+ needs_ord_bound,
+ |field| field.ord_bound(),
+ |input| input.ord_bound(),
+ );
+ let new_where_clause;
+ let (impl_generics, ty_generics, mut where_clause) = generics.split_for_impl();
+
+ if let Some(new_where_clause2) = maybe_add_copy(input, where_clause, |f| !f.attrs.ignore_ord())
+ {
+ new_where_clause = new_where_clause2;
+ where_clause = Some(&new_where_clause);
+ }
+
+ quote! {
+ #[allow(unused_qualifications)]
+ #[allow(clippy::unneeded_field_pattern)]
+ impl #impl_generics #ord_trait_path for #name #ty_generics #where_clause {
+ fn cmp(&self, other: &Self) -> #ordering_path {
+ match *self {
+ #body
+ }
+ }
+ }
+ }
+}
+
+fn needs_partial_eq_bound(attrs: &attr::Field) -> bool {
+ !attrs.ignore_partial_eq() && attrs.partial_eq_bound().is_none()
+}
+
+fn needs_partial_ord_bound(attrs: &attr::Field) -> bool {
+ !attrs.ignore_partial_ord() && attrs.partial_ord_bound().is_none()
+}
+
+fn needs_ord_bound(attrs: &attr::Field) -> bool {
+ !attrs.ignore_ord() && attrs.ord_bound().is_none()
+}
+
+fn needs_eq_bound(attrs: &attr::Field) -> bool {
+ !attrs.ignore_partial_eq() && attrs.eq_bound().is_none()
+}
+
+/// Return the path of the `Eq` trait, that is `::std::cmp::Eq`.
+fn eq_trait_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::cmp::Eq)
+ } else {
+ parse_quote!(::std::cmp::Eq)
+ }
+}
+
+/// Return the path of the `PartialEq` trait, that is `::std::cmp::PartialEq`.
+fn partial_eq_trait_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::cmp::PartialEq)
+ } else {
+ parse_quote!(::std::cmp::PartialEq)
+ }
+}
+
+/// Return the path of the `PartialOrd` trait, that is `::std::cmp::PartialOrd`.
+fn partial_ord_trait_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::cmp::PartialOrd)
+ } else {
+ parse_quote!(::std::cmp::PartialOrd)
+ }
+}
+
+/// Return the path of the `Ord` trait, that is `::std::cmp::Ord`.
+fn ord_trait_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::cmp::Ord)
+ } else {
+ parse_quote!(::std::cmp::Ord)
+ }
+}
+
+/// Return the path of the `Option` trait, that is `::std::option::Option`.
+fn option_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::option::Option)
+ } else {
+ parse_quote!(::std::option::Option)
+ }
+}
+
+/// Return the path of the `Ordering` trait, that is `::std::cmp::Ordering`.
+fn ordering_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::cmp::Ordering)
+ } else {
+ parse_quote!(::std::cmp::Ordering)
+ }
+}
+
+fn maybe_add_copy(
+ input: &ast::Input,
+ where_clause: Option<&syn::WhereClause>,
+ field_filter: impl Fn(&ast::Field) -> bool,
+) -> Option<syn::WhereClause> {
+ if input.attrs.is_packed && !input.body.is_empty() {
+ let mut new_where_clause = where_clause.cloned().unwrap_or_else(|| syn::WhereClause {
+ where_token: parse_quote!(where),
+ predicates: Default::default(),
+ });
+
+ new_where_clause.predicates.extend(
+ input
+ .body
+ .all_fields()
+ .into_iter()
+ .filter(|f| field_filter(f))
+ .map(|f| {
+ let ty = f.ty;
+
+ let pred: syn::WherePredicate = parse_quote!(#ty: Copy);
+ pred
+ }),
+ );
+
+ Some(new_where_clause)
+ } else {
+ None
+ }
+}
diff --git a/vendor/derivative/src/debug.rs b/vendor/derivative/src/debug.rs
new file mode 100644
index 000000000..ed667c1d7
--- /dev/null
+++ b/vendor/derivative/src/debug.rs
@@ -0,0 +1,225 @@
+use proc_macro2;
+
+use ast;
+use attr;
+use matcher;
+use syn;
+use syn::spanned::Spanned;
+use utils;
+
+pub fn derive(input: &ast::Input) -> proc_macro2::TokenStream {
+ let debug_trait_path = debug_trait_path();
+ let fmt_path = fmt_path();
+
+ let formatter = quote_spanned! {input.span=> __f};
+
+ let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed)
+ .with_field_filter(|f: &ast::Field| !f.attrs.ignore_debug())
+ .build_arms(input, "__arg", |_, _, arm_name, style, attrs, bis| {
+ let field_prints = bis.iter().filter_map(|bi| {
+ if bi.field.attrs.ignore_debug() {
+ return None;
+ }
+
+ if attrs.debug_transparent() {
+ return Some(quote_spanned! {arm_name.span()=>
+ #debug_trait_path::fmt(__arg_0, #formatter)
+ });
+ }
+
+ let arg_expr = &bi.expr;
+ let arg_ident = &bi.ident;
+
+ let dummy_debug = bi.field.attrs.debug_format_with().map(|format_fn| {
+ format_with(
+ bi.field,
+ &input.attrs.debug_bound(),
+ &arg_expr,
+ &arg_ident,
+ format_fn,
+ input.generics.clone(),
+ )
+ });
+ let expr = if bi.field.attrs.debug_format_with().is_some() {
+ quote_spanned! {arm_name.span()=>
+ &#arg_ident
+ }
+ } else {
+ quote_spanned! {arm_name.span()=>
+ &&#arg_expr
+ }
+ };
+
+ let builder = if let Some(ref name) = bi.field.ident {
+ let name = name.to_string();
+ quote_spanned! {arm_name.span()=>
+ #dummy_debug
+ let _ = __debug_trait_builder.field(#name, #expr);
+ }
+ } else {
+ quote_spanned! {arm_name.span()=>
+ #dummy_debug
+ let _ = __debug_trait_builder.field(#expr);
+ }
+ };
+
+ Some(builder)
+ });
+
+ let method = match style {
+ ast::Style::Struct => "debug_struct",
+ ast::Style::Tuple | ast::Style::Unit => "debug_tuple",
+ };
+ let method = syn::Ident::new(method, proc_macro2::Span::call_site());
+
+ if attrs.debug_transparent() {
+ quote_spanned! {arm_name.span()=>
+ #(#field_prints)*
+ }
+ } else {
+ let name = arm_name.to_string();
+ quote_spanned! {arm_name.span()=>
+ let mut __debug_trait_builder = #formatter.#method(#name);
+ #(#field_prints)*
+ __debug_trait_builder.finish()
+ }
+ }
+ });
+
+ let name = &input.ident;
+
+ let generics = utils::build_impl_generics(
+ input,
+ &debug_trait_path,
+ needs_debug_bound,
+ |field| field.debug_bound(),
+ |input| input.debug_bound(),
+ );
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ // don't attach a span to prevent issue #58
+ let match_self = quote!(match *self);
+ quote_spanned! {input.span=>
+ #[allow(unused_qualifications)]
+ #[allow(clippy::unneeded_field_pattern)]
+ impl #impl_generics #debug_trait_path for #name #ty_generics #where_clause {
+ fn fmt(&self, #formatter: &mut #fmt_path::Formatter) -> #fmt_path::Result {
+ #match_self {
+ #body
+ }
+ }
+ }
+ }
+}
+
+fn needs_debug_bound(attrs: &attr::Field) -> bool {
+ !attrs.ignore_debug() && attrs.debug_bound().is_none()
+}
+
+/// Return the path of the `Debug` trait, that is `::std::fmt::Debug`.
+fn debug_trait_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::fmt::Debug)
+ } else {
+ parse_quote!(::std::fmt::Debug)
+ }
+}
+
+/// Return the path of the `fmt` module, that is `::std::fmt`.
+fn fmt_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::fmt)
+ } else {
+ parse_quote!(::std::fmt)
+ }
+}
+
+/// Return the path of the `PhantomData` type, that is `::std::marker::PhantomData`.
+fn phantom_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::marker::PhantomData)
+ } else {
+ parse_quote!(::std::marker::PhantomData)
+ }
+}
+
+fn format_with(
+ f: &ast::Field,
+ bounds: &Option<&[syn::WherePredicate]>,
+ arg_expr: &proc_macro2::TokenStream,
+ arg_ident: &syn::Ident,
+ format_fn: &syn::Path,
+ mut generics: syn::Generics,
+) -> proc_macro2::TokenStream {
+ let debug_trait_path = debug_trait_path();
+ let fmt_path = fmt_path();
+ let phantom_path = phantom_path();
+
+ generics
+ .make_where_clause()
+ .predicates
+ .extend(f.attrs.debug_bound().unwrap_or(&[]).iter().cloned());
+
+ generics
+ .params
+ .push(syn::GenericParam::Lifetime(syn::LifetimeDef::new(
+ parse_quote!('_derivative),
+ )));
+ let where_predicates = generics
+ .type_params()
+ .map(|ty| {
+ let mut bounds = syn::punctuated::Punctuated::new();
+ bounds.push(syn::TypeParamBound::Lifetime(syn::Lifetime::new(
+ "'_derivative",
+ proc_macro2::Span::call_site(),
+ )));
+
+ let path = syn::Path::from(syn::PathSegment::from(ty.ident.clone()));
+
+ syn::WherePredicate::Type(syn::PredicateType {
+ lifetimes: None,
+ bounded_ty: syn::Type::Path(syn::TypePath { qself: None, path }),
+ colon_token: Default::default(),
+ bounds,
+ })
+ })
+ .chain(bounds.iter().flat_map(|b| b.iter().cloned()))
+ .collect::<Vec<_>>();
+ generics
+ .make_where_clause()
+ .predicates
+ .extend(where_predicates);
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let ty = f.ty;
+
+ // Leave off the type parameter bounds, defaults, and attributes
+ let phantom = generics.type_params().map(|tp| &tp.ident);
+
+ let mut ctor_generics = generics.clone();
+ *ctor_generics
+ .lifetimes_mut()
+ .last()
+ .expect("There must be a '_derivative lifetime") = syn::LifetimeDef::new(parse_quote!('_));
+ let (_, ctor_ty_generics, _) = ctor_generics.split_for_impl();
+ let ctor_ty_generics = ctor_ty_generics.as_turbofish();
+
+ // don't attach a span to prevent issue #58
+ let match_self = quote!(match self.0);
+ quote_spanned!(format_fn.span()=>
+ let #arg_ident = {
+ struct Dummy #impl_generics (&'_derivative #ty, #phantom_path <(#(#phantom,)*)>) #where_clause;
+
+ impl #impl_generics #debug_trait_path for Dummy #ty_generics #where_clause {
+ fn fmt(&self, __f: &mut #fmt_path::Formatter) -> #fmt_path::Result {
+ #match_self {
+ this => #format_fn(this, __f)
+ }
+ }
+ }
+
+ Dummy #ctor_ty_generics (&&#arg_expr, #phantom_path)
+ };
+ )
+}
diff --git a/vendor/derivative/src/default.rs b/vendor/derivative/src/default.rs
new file mode 100644
index 000000000..f36947533
--- /dev/null
+++ b/vendor/derivative/src/default.rs
@@ -0,0 +1,120 @@
+use proc_macro2;
+
+use ast;
+use attr;
+use syn;
+use utils;
+
+/// Derive `Default` for `input`.
+pub fn derive(input: &ast::Input, default: &attr::InputDefault) -> proc_macro2::TokenStream {
+ fn make_variant_data(
+ variant_name: &proc_macro2::TokenStream,
+ style: ast::Style,
+ fields: &[ast::Field],
+ ) -> proc_macro2::TokenStream {
+ let default_trait_path = default_trait_path();
+
+ match style {
+ ast::Style::Struct => {
+ let mut defaults = Vec::new();
+
+ for f in fields {
+ let name = f
+ .ident
+ .as_ref()
+ .expect("A structure field must have a name");
+ let default = f
+ .attrs
+ .default_value()
+ .map_or_else(|| quote!(#default_trait_path::default()), |v| quote!(#v));
+
+ defaults.push(quote!(#name: #default));
+ }
+
+ quote!(#variant_name { #(#defaults),* })
+ }
+ ast::Style::Tuple => {
+ let mut defaults = Vec::new();
+
+ for f in fields {
+ let default = f
+ .attrs
+ .default_value()
+ .map_or_else(|| quote!(#default_trait_path::default()), |v| quote!(#v));
+
+ defaults.push(default);
+ }
+
+ quote!(#variant_name ( #(#defaults),* ))
+ }
+ ast::Style::Unit => quote!(#variant_name),
+ }
+ }
+
+ let name = &input.ident;
+ let default_trait_path = default_trait_path();
+ let generics = utils::build_impl_generics(
+ input,
+ &default_trait_path,
+ |attrs| attrs.default_bound().is_none(),
+ |field| field.default_bound(),
+ |input| input.default_bound(),
+ );
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let body = match input.body {
+ ast::Body::Enum(ref data) => {
+ let arms = data.iter().filter_map(|variant| {
+ if variant.attrs.default.is_some() {
+ let vname = &variant.ident;
+
+ Some(make_variant_data(
+ &quote!(#name::#vname),
+ variant.style,
+ &variant.fields,
+ ))
+ } else {
+ None
+ }
+ });
+
+ quote!(#(#arms),*)
+ }
+ ast::Body::Struct(style, ref vd) => make_variant_data(&quote!(#name), style, vd),
+ };
+
+ let new_fn = if default.new {
+ Some(quote!(
+ #[allow(unused_qualifications)]
+ impl #impl_generics #name #ty_generics #where_clause {
+ /// Creates a default value for this type.
+ #[inline]
+ pub fn new() -> Self {
+ <Self as #default_trait_path>::default()
+ }
+ }
+ ))
+ } else {
+ None
+ };
+
+ quote!(
+ #new_fn
+
+ #[allow(unused_qualifications)]
+ impl #impl_generics #default_trait_path for #name #ty_generics #where_clause {
+ fn default() -> Self {
+ #body
+ }
+ }
+ )
+}
+
+/// Return the path of the `Default` trait, that is `::std::default::Default`.
+fn default_trait_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::default::Default)
+ } else {
+ parse_quote!(::std::default::Default)
+ }
+}
diff --git a/vendor/derivative/src/hash.rs b/vendor/derivative/src/hash.rs
new file mode 100644
index 000000000..8f13f80f2
--- /dev/null
+++ b/vendor/derivative/src/hash.rs
@@ -0,0 +1,97 @@
+use proc_macro2;
+
+use ast;
+use attr;
+use matcher;
+use paths;
+use syn;
+use utils;
+
+pub fn derive(input: &ast::Input) -> proc_macro2::TokenStream {
+ let hasher_trait_path = hasher_trait_path();
+ let hash_trait_path = hash_trait_path();
+
+ let discriminant = if let ast::Body::Enum(_) = input.body {
+ let discriminant = paths::discriminant_path();
+ Some(quote!(
+ #hash_trait_path::hash(&#discriminant(self), __state);
+ ))
+ } else {
+ None
+ };
+
+ let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed).build_arms(
+ input,
+ "__arg",
+ |_, _, _, _, _, bis| {
+ let field_prints = bis.iter().filter_map(|bi| {
+ if bi.field.attrs.ignore_hash() {
+ return None;
+ }
+
+ let arg = &bi.expr;
+
+ if let Some(hash_with) = bi.field.attrs.hash_with() {
+ Some(quote! {
+ #hash_with(&#arg, __state);
+ })
+ } else {
+ Some(quote! {
+ #hash_trait_path::hash(&#arg, __state);
+ })
+ }
+ });
+
+ quote! {
+ #(#field_prints)*
+ }
+ },
+ );
+
+ let name = &input.ident;
+ let generics = utils::build_impl_generics(
+ input,
+ &hash_trait_path,
+ needs_hash_bound,
+ |field| field.hash_bound(),
+ |input| input.hash_bound(),
+ );
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let hasher_ty_parameter = utils::hygienic_type_parameter(input, "__H");
+ quote! {
+ #[allow(unused_qualifications)]
+ impl #impl_generics #hash_trait_path for #name #ty_generics #where_clause {
+ fn hash<#hasher_ty_parameter>(&self, __state: &mut #hasher_ty_parameter)
+ where #hasher_ty_parameter: #hasher_trait_path
+ {
+ #discriminant
+ match *self {
+ #body
+ }
+ }
+ }
+ }
+}
+
+fn needs_hash_bound(attrs: &attr::Field) -> bool {
+ !attrs.ignore_hash() && attrs.hash_bound().is_none()
+}
+
+/// Return the path of the `Hash` trait, that is `::std::hash::Hash`.
+fn hash_trait_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::hash::Hash)
+ } else {
+ parse_quote!(::std::hash::Hash)
+ }
+}
+
+/// Return the path of the `Hasher` trait, that is `::std::hash::Hasher`.
+fn hasher_trait_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::hash::Hasher)
+ } else {
+ parse_quote!(::std::hash::Hasher)
+ }
+}
diff --git a/vendor/derivative/src/lib.rs b/vendor/derivative/src/lib.rs
new file mode 100644
index 000000000..d891948f9
--- /dev/null
+++ b/vendor/derivative/src/lib.rs
@@ -0,0 +1,94 @@
+// We need to support Rust 1.34 to stable
+#![allow(deprecated)]
+
+#![allow(renamed_and_removed_lints)] // support for multiple Clippy versions
+#![allow(clippy::unknown_clippy_lints)] // because of other #![allow]s
+#![allow(clippy::mem_replace_with_default)] // needs rustc 1.40
+#![allow(clippy::option_as_ref_deref)] // needs rustc 1.40
+#![allow(clippy::cyclomatic_complexity)] // old name of cognitive_complexity
+#![allow(clippy::cognitive_complexity)] // in code generated by macros
+#![allow(clippy::redundant_closure)]
+
+extern crate proc_macro;
+extern crate proc_macro2;
+#[macro_use]
+extern crate syn;
+
+#[macro_use]
+extern crate quote;
+
+mod ast;
+mod attr;
+mod bound;
+mod clone;
+mod cmp;
+mod debug;
+mod default;
+mod hash;
+mod matcher;
+mod paths;
+mod utils;
+
+use proc_macro::TokenStream;
+
+fn derive_impls(
+ input: &mut ast::Input,
+ errors: &mut proc_macro2::TokenStream,
+) -> proc_macro2::TokenStream {
+ let mut tokens = proc_macro2::TokenStream::new();
+
+ if input.attrs.clone.is_some() {
+ tokens.extend(clone::derive_clone(input));
+ }
+ if input.attrs.copy.is_some() {
+ tokens.extend(clone::derive_copy(input));
+ }
+ if input.attrs.debug.is_some() {
+ tokens.extend(debug::derive(input));
+ }
+ if let Some(ref default) = input.attrs.default {
+ tokens.extend(default::derive(input, default));
+ }
+ if input.attrs.eq.is_some() {
+ tokens.extend(cmp::derive_eq(input));
+ }
+ if input.attrs.hash.is_some() {
+ tokens.extend(hash::derive(input));
+ }
+ if input.attrs.partial_eq.is_some() {
+ tokens.extend(cmp::derive_partial_eq(input));
+ }
+ if input.attrs.partial_ord.is_some() {
+ tokens.extend(cmp::derive_partial_ord(input, errors));
+ }
+ if input.attrs.ord.is_some() {
+ tokens.extend(cmp::derive_ord(input, errors));
+ }
+
+ tokens.extend(std::mem::replace(
+ errors,
+ Default::default(),
+ ));
+
+ tokens
+}
+
+#[cfg_attr(not(test), proc_macro_derive(Derivative, attributes(derivative)))]
+pub fn derivative(input: TokenStream) -> TokenStream {
+ let mut errors = proc_macro2::TokenStream::new();
+
+ let mut output = match syn::parse::<syn::DeriveInput>(input) {
+ Ok(parsed) => {
+ ast::Input::from_ast(&parsed, &mut errors)
+ .map(|mut input| derive_impls(&mut input, &mut errors))
+ .unwrap_or_default()
+ },
+ Err(error) => {
+ errors.extend(error.to_compile_error());
+ Default::default()
+ }
+ };
+
+ output.extend(errors);
+ output.into()
+} \ No newline at end of file
diff --git a/vendor/derivative/src/matcher.rs b/vendor/derivative/src/matcher.rs
new file mode 100644
index 000000000..4b78fa4da
--- /dev/null
+++ b/vendor/derivative/src/matcher.rs
@@ -0,0 +1,336 @@
+#![allow(dead_code)] // TODO: remove
+
+// This is inspired from `synstructure`, but `synstructure` is not adapted in severals ways
+// including:
+// * `&mut` everywhere
+// * not generic, we use our own `ast`, `synstructure` only knows about `syn`
+// * missing information (what arm are we in?, what attributes? etc.)
+
+use proc_macro2::{self, TokenStream};
+use quote::ToTokens;
+use syn;
+
+use ast;
+use attr;
+use quote;
+
+/// The type of binding to use when generating a pattern.
+#[derive(Debug, Copy, Clone)]
+pub enum BindingStyle {
+ /// `x`
+ Move,
+ /// `mut x`
+ MoveMut,
+ /// `ref x`
+ Ref,
+ /// `ref mut x`
+ RefMut,
+}
+
+impl BindingStyle {
+ fn with_packed(self, is_packed: bool) -> BindingStyle {
+ match self {
+ BindingStyle::Move | BindingStyle::MoveMut => self,
+ BindingStyle::Ref if is_packed => BindingStyle::Move,
+ BindingStyle::RefMut if is_packed => BindingStyle::MoveMut,
+ BindingStyle::Ref | BindingStyle::RefMut => self,
+ }
+ }
+}
+
+impl quote::ToTokens for BindingStyle {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match *self {
+ BindingStyle::Move => (),
+ BindingStyle::MoveMut => tokens.extend(quote!(mut)),
+ BindingStyle::Ref => tokens.extend(quote!(ref)),
+ BindingStyle::RefMut => {
+ tokens.extend(quote!(ref mut));
+ }
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct BindingInfo<'a> {
+ pub expr: TokenStream,
+ pub ident: syn::Ident,
+ pub field: &'a ast::Field<'a>,
+}
+
+#[derive(Debug)]
+pub struct CommonVariant<'a> {
+ path: syn::Path,
+ name: &'a syn::Ident,
+ style: ast::Style,
+ attrs: &'a attr::Input,
+}
+
+pub struct Matcher<T> {
+ binding_name: String,
+ binding_style: BindingStyle,
+ is_packed: bool,
+ field_filter: T,
+}
+
+impl Matcher<fn (&ast::Field) -> bool> {
+ pub fn new(style: BindingStyle, is_packed: bool) -> Self {
+ Matcher {
+ binding_name: "__arg".into(),
+ binding_style: style.with_packed(is_packed),
+ is_packed,
+ field_filter: |_| true,
+ }
+ }
+}
+
+impl<T: Fn (&ast::Field) -> bool> Matcher<T> {
+ pub fn with_name(self, name: String) -> Self {
+ Matcher {
+ binding_name: name,
+ ..self
+ }
+ }
+
+ pub fn with_field_filter<P>(self, field_filter: P) -> Matcher<P> {
+ Matcher {
+ field_filter,
+ binding_name: self.binding_name,
+ binding_style: self.binding_style,
+ is_packed: self.is_packed,
+ }
+ }
+
+ pub fn build_arms<F>(self, input: &ast::Input, binding_name: &str, f: F) -> TokenStream
+ where
+ F: Fn(
+ syn::Path,
+ usize,
+ &syn::Ident,
+ ast::Style,
+ &attr::Input,
+ Vec<BindingInfo>,
+ ) -> TokenStream,
+ {
+ let variants = self.build_match_pattern(input, binding_name);
+
+ // Now that we have the patterns, generate the actual branches of the match
+ // expression
+ let mut t = TokenStream::new();
+ for (i, (variant, (pat, bindings))) in variants.into_iter().enumerate() {
+ let body = f(
+ variant.path,
+ i,
+ variant.name,
+ variant.style,
+ variant.attrs,
+ bindings,
+ );
+ quote!(#pat => { #body }).to_tokens(&mut t);
+ }
+
+ t
+ }
+
+ pub fn build_2_arms<F>(
+ self,
+ (left_matched_expr, right_matched_expr): (TokenStream, TokenStream),
+ left: (&ast::Input, &str),
+ right: (&ast::Input, &str),
+ f: F,
+ ) -> TokenStream
+ where
+ F: Fn(
+ usize,
+ CommonVariant,
+ CommonVariant,
+ (Vec<BindingInfo>, Vec<BindingInfo>),
+ ) -> TokenStream,
+ {
+ let left_variants = self.build_match_pattern(left.0, left.1);
+ let right_variants = self.build_match_pattern(right.0, right.1);
+
+ assert_eq!(left_variants.len(), right_variants.len());
+
+ if left_variants.len() == 1 {
+ let (left, (left_pat, left_bindings)) = left_variants.into_iter().next().unwrap();
+ let (right, (right_pat, right_bindings)) = right_variants.into_iter().next().unwrap();
+
+ let body = f(0, left, right, (left_bindings, right_bindings));
+
+ quote! {
+ match #left_matched_expr {
+ #left_pat => match #right_matched_expr {
+ #right_pat => #body,
+ },
+ }
+ }
+ } else {
+ // Now that we have the patterns, generate the actual branches of the match
+ // expression
+ let mut t = TokenStream::new();
+ for (i, (left, right)) in left_variants.into_iter().zip(right_variants).enumerate() {
+ let (left, (left_pat, left_bindings)) = left;
+ let (right, (right_pat, right_bindings)) = right;
+
+ let body = f(i, left, right, (left_bindings, right_bindings));
+ quote!((#left_pat, #right_pat) => { #body }).to_tokens(&mut t);
+ }
+
+ quote! {
+ match (&#left_matched_expr, &#right_matched_expr) {
+ #t
+ _ => unreachable!(),
+ }
+ }
+ }
+ }
+
+ /// Generate patterns for matching against all of the variants
+ pub fn build_match_pattern<'a>(
+ &self,
+ input: &'a ast::Input,
+ binding_name: &str,
+ ) -> Vec<(CommonVariant<'a>, (TokenStream, Vec<BindingInfo<'a>>))> {
+ let ident = &input.ident;
+
+ match input.body {
+ ast::Body::Enum(ref variants) => variants
+ .iter()
+ .map(|variant| {
+ let variant_ident = &variant.ident;
+ let path = parse_quote!(#ident::#variant_ident);
+
+ let pat = self.build_match_pattern_impl(
+ &path,
+ variant.style,
+ &variant.fields,
+ binding_name,
+ );
+
+ (
+ CommonVariant {
+ path,
+ name: variant_ident,
+ style: variant.style,
+ attrs: &variant.attrs,
+ },
+ pat,
+ )
+ })
+ .collect(),
+ ast::Body::Struct(style, ref vd) => {
+ let path = parse_quote!(#ident);
+ vec![(
+ CommonVariant {
+ path,
+ name: ident,
+ style,
+ attrs: &input.attrs,
+ },
+ self.build_match_pattern_impl(ident, style, vd, binding_name),
+ )]
+ }
+ }
+ }
+
+ fn build_match_pattern_impl<'a, N>(
+ &self,
+ name: &N,
+ style: ast::Style,
+ fields: &'a [ast::Field<'a>],
+ binding_name: &str,
+ ) -> (TokenStream, Vec<BindingInfo<'a>>)
+ where
+ N: quote::ToTokens,
+ {
+ let (stream, matches) = match style {
+ ast::Style::Unit => (TokenStream::new(), Vec::new()),
+ ast::Style::Tuple => {
+ let (stream, matches) = fields.iter().enumerate().fold(
+ (TokenStream::new(), Vec::new()),
+ |(stream, matches), field| {
+ self.build_inner_pattern(
+ (stream, matches),
+ field,
+ binding_name,
+ |f, ident, binding| {
+ if (self.field_filter)(f) {
+ quote!(#binding #ident ,)
+ } else {
+ quote!(_ ,)
+ }
+ },
+ )
+ },
+ );
+
+ (quote! { ( #stream ) }, matches)
+ }
+ ast::Style::Struct => {
+ let (stream, matches) = fields.iter().enumerate().fold(
+ (TokenStream::new(), Vec::new()),
+ |(stream, matches), field| {
+ self.build_inner_pattern(
+ (stream, matches),
+ field,
+ binding_name,
+ |field, ident, binding| {
+ let field_name = field.ident.as_ref().unwrap();
+ if (self.field_filter)(field) {
+ quote!(#field_name : #binding #ident ,)
+ } else {
+ quote!(#field_name : _ ,)
+ }
+ },
+ )
+ },
+ );
+
+ (quote! { { #stream } }, matches)
+ }
+ };
+
+ let mut all_tokens = TokenStream::new();
+ name.to_tokens(&mut all_tokens);
+ all_tokens.extend(stream);
+
+ (all_tokens, matches)
+ }
+
+ fn build_inner_pattern<'a>(
+ &self,
+ (mut stream, mut matches): (TokenStream, Vec<BindingInfo<'a>>),
+ (i, field): (usize, &'a ast::Field),
+ binding_name: &str,
+ f: impl FnOnce(&ast::Field, &syn::Ident, BindingStyle) -> TokenStream,
+ ) -> (TokenStream, Vec<BindingInfo<'a>>) {
+ let binding_style = self.binding_style;
+
+ let ident: syn::Ident = syn::Ident::new(
+ &format!("{}_{}", binding_name, i),
+ proc_macro2::Span::call_site(),
+ );
+ let expr = syn::Expr::Path(syn::ExprPath {
+ attrs: vec![],
+ qself: None,
+ path: syn::Path::from(ident.clone())
+ });
+
+ let expr = if self.is_packed {
+ expr.into_token_stream()
+ } else {
+ quote!((*#expr))
+ };
+
+ f(field, &ident, binding_style).to_tokens(&mut stream);
+
+ matches.push(BindingInfo {
+ expr,
+ ident,
+ field,
+ });
+
+ (stream, matches)
+ }
+}
diff --git a/vendor/derivative/src/paths.rs b/vendor/derivative/src/paths.rs
new file mode 100644
index 000000000..7a6ec7de3
--- /dev/null
+++ b/vendor/derivative/src/paths.rs
@@ -0,0 +1,10 @@
+//! Contains some standard paths.
+
+/// Return the path of the `discriminant` function, that is `::std::mem::discriminant`.
+pub fn discriminant_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::mem::discriminant)
+ } else {
+ parse_quote!(::std::mem::discriminant)
+ }
+} \ No newline at end of file
diff --git a/vendor/derivative/src/utils.rs b/vendor/derivative/src/utils.rs
new file mode 100644
index 000000000..9db21f5be
--- /dev/null
+++ b/vendor/derivative/src/utils.rs
@@ -0,0 +1,43 @@
+use proc_macro2;
+
+use ast;
+use attr;
+use bound;
+use syn;
+
+/// Make generic with all the generics in the input, plus a bound `T: <trait_path>` for each
+/// generic field type that will be shown.
+pub fn build_impl_generics<F, G, H>(
+ item: &ast::Input,
+ trait_path: &syn::Path,
+ needs_debug_bound: F,
+ field_bound: G,
+ input_bound: H,
+) -> syn::Generics
+where
+ F: Fn(&attr::Field) -> bool,
+ G: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
+ H: Fn(&attr::Input) -> Option<&[syn::WherePredicate]>,
+{
+ let generics = bound::without_defaults(item.generics);
+ let generics = bound::with_where_predicates_from_fields(item, &generics, field_bound);
+
+ match input_bound(&item.attrs) {
+ Some(predicates) => bound::with_where_predicates(&generics, predicates),
+ None => bound::with_bound(item, &generics, needs_debug_bound, trait_path),
+ }
+}
+
+/// Construct a name for the inner type parameter that can't collide with any
+/// type parameters of the item. This is achieved by starting with a base and
+/// then concatenating the names of all other type parameters.
+pub fn hygienic_type_parameter(item: &ast::Input, base: &str) -> syn::Ident {
+ let mut typaram = String::with_capacity(150);
+ typaram.push_str(base);
+ let typaram = item.generics.type_params().fold(typaram, |mut acc, ty| {
+ acc.push_str(&format!("{}", &ty.ident));
+ acc
+ });
+
+ syn::Ident::new(&typaram, proc_macro2::Span::call_site())
+}