From 17b65c332eba65e2a106fe983b731e32b32e90fa Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Thu, 27 Oct 2022 04:08:55 +0200 Subject: [PATCH 1/6] Add some forwarding impls Hash, Ord, PartialOrd --- fixed-map-derive/src/any_variants.rs | 16 +- fixed-map-derive/src/context.rs | 10 ++ fixed-map-derive/src/unit_variants.rs | 79 +++++++++- src/map.rs | 212 ++++++++++++++++++++++++++ src/set.rs | 212 ++++++++++++++++++++++++++ 5 files changed, 526 insertions(+), 3 deletions(-) diff --git a/fixed-map-derive/src/any_variants.rs b/fixed-map-derive/src/any_variants.rs index c28a245..c90ff83 100644 --- a/fixed-map-derive/src/any_variants.rs +++ b/fixed-map-derive/src/any_variants.rs @@ -32,6 +32,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let mut field_inits = Vec::new(); let mut field_clones = Vec::new(); let mut field_partial_eqs = Vec::new(); + let mut field_partial_not_eqs = Vec::new(); let mut contains_key = Vec::new(); let mut get = Vec::new(); let mut get_mut = Vec::new(); @@ -48,12 +49,19 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result field_inits.push(quote!(#name: #default::default())); field_clones.push(quote!(#name: #clone::clone(&self.#name))); + field_partial_eqs.push(quote! { - if self.#name != other.#name { + if #partial_eq::ne(&self.#name, &other.#name) { return false; } }); + field_partial_not_eqs.push(quote! { + if #partial_eq::ne(&self.#name, &other.#name) { + return true; + } + }); + let kind = match &variant.fields { Fields::Unit => { len.push(quote!(usize::from(#option::is_some(&self.#name)))); @@ -176,6 +184,12 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result #(#field_partial_eqs;)* true } + + #[inline] + fn ne(&self, other: &Storage) -> bool { + #(#field_partial_not_eqs;)* + false + } } #[automatically_derived] diff --git a/fixed-map-derive/src/context.rs b/fixed-map-derive/src/context.rs index 3425994..d7f120c 100644 --- a/fixed-map-derive/src/context.rs +++ b/fixed-map-derive/src/context.rs @@ -13,6 +13,8 @@ pub(crate) struct Toks { pub(crate) default: TokenStream, pub(crate) double_ended_iterator_t: TokenStream, pub(crate) eq: TokenStream, + pub(crate) hash: TokenStream, + pub(crate) hasher: TokenStream, pub(crate) into_iter: TokenStream, pub(crate) iterator_t: TokenStream, pub(crate) iterator_flatten: TokenStream, @@ -20,6 +22,9 @@ pub(crate) struct Toks { pub(crate) mem: TokenStream, pub(crate) option: TokenStream, pub(crate) partial_eq: TokenStream, + pub(crate) partial_ord: TokenStream, + pub(crate) ordering: TokenStream, + pub(crate) ord: TokenStream, pub(crate) slice_iter_mut: TokenStream, pub(crate) slice_iter: TokenStream, pub(crate) storage_trait: TokenStream, @@ -43,6 +48,8 @@ impl Toks { default: quote!(::core::default::Default), double_ended_iterator_t: quote!(::core::iter::DoubleEndedIterator), eq: quote!(::core::cmp::Eq), + hash: quote!(::core::hash::Hash), + hasher: quote!(::core::hash::Hasher), into_iter: quote!(::core::iter::IntoIterator::into_iter), iterator_t: quote!(::core::iter::Iterator), iterator_flatten: quote!(::core::iter::Flatten), @@ -50,6 +57,9 @@ impl Toks { mem: quote!(::core::mem), option: quote!(::core::option::Option), partial_eq: quote!(::core::cmp::PartialEq), + partial_ord: quote!(::core::cmp::PartialOrd), + ordering: quote!(::core::cmp::Ordering), + ord: quote!(::core::cmp::Ord), slice_iter_mut: quote!(::core::slice::IterMut), slice_iter: quote!(::core::slice::Iter), storage_trait: quote!(#krate::storage::Storage), diff --git a/fixed-map-derive/src/unit_variants.rs b/fixed-map-derive/src/unit_variants.rs index 8e44558..eb79be0 100644 --- a/fixed-map-derive/src/unit_variants.rs +++ b/fixed-map-derive/src/unit_variants.rs @@ -14,6 +14,8 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let copy = &cx.toks.copy; let default = &cx.toks.default; let eq = &cx.toks.eq; + let hash = &cx.toks.hash; + let hasher = &cx.toks.hasher; let into_iter = &cx.toks.into_iter; let iterator = &cx.toks.iterator_t; let iterator_flatten = &cx.toks.iterator_flatten; @@ -21,6 +23,9 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let mem = &cx.toks.mem; let option = &cx.toks.option; let partial_eq = &cx.toks.partial_eq; + let partial_ord = &cx.toks.partial_ord; + let ordering = &cx.toks.ordering; + let ord = &cx.toks.ord; let slice_iter = &cx.toks.slice_iter; let slice_iter_mut = &cx.toks.slice_iter_mut; let array_into_iter = &cx.toks.array_into_iter; @@ -191,16 +196,86 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #partial_eq for Storage where V: #partial_eq{ + impl #partial_eq for Storage where V: #partial_eq { #[inline] fn eq(&self, other: &Storage) -> bool { - self.data == other.data + #partial_eq::eq(&self.data, &other.data) + } + + #[inline] + fn ne(&self, other: &Storage) -> bool { + #partial_eq::ne(&self.data, &other.data) } } #[automatically_derived] impl #eq for Storage where V: #eq {} + #[automatically_derived] + impl #hash for Storage where V: #hash { + #[inline] + fn hash(&self, state: &mut H) + where + H: #hasher, + { + #hash::hash(&self.data, state); + } + } + + #[automatically_derived] + impl #partial_ord for Storage where V: #partial_ord { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option<#ordering> { + #partial_ord::partial_cmp(&self.data, &other.data) + } + + #[inline] + fn lt(&self, other: &Self) -> bool { + #partial_ord::lt(&self.data, &other.data) + } + + #[inline] + fn le(&self, other: &Self) -> bool { + #partial_ord::le(&self.data, &other.data) + } + + #[inline] + fn gt(&self, other: &Self) -> bool { + #partial_ord::gt(&self.data, &other.data) + } + + #[inline] + fn ge(&self, other: &Self) -> bool { + #partial_ord::ge(&self.data, &other.data) + } + } + + #[automatically_derived] + impl #ord for Storage where V: #ord { + #[inline] + fn cmp(&self, other: &Self) -> #ordering { + #ord::cmp(self, other) + } + + #[inline] + fn max(self, other: Self) -> Self { + Self { data: #ord::max(self.data, other.data) } + } + + #[inline] + fn min(self, other: Self) -> Self { + Self { data: #ord::min(self.data, other.data) } + } + + #[inline] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: #partial_ord + { + Self { data: #ord::clamp(self.data, min.data, max.data) } + } + } + #[automatically_derived] impl #default for Storage { #[inline] diff --git a/src/map.rs b/src/map.rs index 64f69c1..6582de5 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,6 +1,8 @@ //! Contains the fixed [`Map`] implementation. +use core::cmp::{Ord, Ordering, PartialOrd}; use core::fmt; +use core::hash::{Hash, Hasher}; use crate::{key::Key, storage::Storage}; @@ -1028,6 +1030,216 @@ where { } +/// [`Hash`] implementation for a [`Set`]. +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashSet; +/// +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First, 1); +/// +/// let mut set = HashSet::new(); +/// set.insert(a); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use std::collections::HashSet; +/// +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First(true), 1); +/// +/// // TODO: support this +/// // let mut set = HashSet::new(); +/// // set.insert(a); +/// ``` +impl Hash for Map +where + K: Key, + K::Storage: Hash, +{ + #[inline] + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.storage.hash(state); + } +} + +/// [`PartialOrd`] implementation for a [`Map`]. +/// +/// # Examples +/// +/// ``` +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First, 1); +/// +/// let mut b = Map::new(); +/// b.insert(Key::Second, 1); +/// +/// assert!(a > b); +/// assert!(a >= b); +/// assert!(!(a < b)); +/// assert!(!(a <= b)); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First(true), 1); +/// +/// let mut b = Map::new(); +/// b.insert(Key::Second, 1); +/// +/// // TODO: support this +/// // assert!(a > b); +/// ``` +impl PartialOrd for Map +where + K: Key, + K::Storage: PartialOrd, +{ + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.storage.partial_cmp(&other.storage) + } + + #[inline] + fn lt(&self, other: &Self) -> bool { + self.storage.lt(&other.storage) + } + + #[inline] + fn le(&self, other: &Self) -> bool { + self.storage.le(&other.storage) + } + + #[inline] + fn gt(&self, other: &Self) -> bool { + self.storage.gt(&other.storage) + } + + #[inline] + fn ge(&self, other: &Self) -> bool { + self.storage.ge(&other.storage) + } +} + +/// [`Ord`] implementation for a [`Map`]. +/// +/// # Examples +/// +/// ``` +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First, 1); +/// +/// let mut b = Map::new(); +/// b.insert(Key::Second, 1); +/// +/// let mut list = vec![a, b]; +/// list.sort(); +/// +/// assert_eq!(list, [b, a]); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First(true), 1); +/// +/// let mut b = Map::new(); +/// b.insert(Key::Second, 1); +/// +/// // TODO: support this +/// // let mut list = vec![a, b]; +/// // list.sort(); +/// ``` +impl Ord for Map +where + K: Key, + K::Storage: Ord, +{ + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.storage.cmp(&other.storage) + } + + #[inline] + fn max(self, other: Self) -> Self { + Self { + storage: self.storage.max(other.storage), + } + } + + #[inline] + fn min(self, other: Self) -> Self { + Self { + storage: self.storage.min(other.storage), + } + } + + #[inline] + fn clamp(self, min: Self, max: Self) -> Self { + Self { + storage: self.storage.clamp(min.storage, max.storage), + } + } +} + impl<'a, K, V> IntoIterator for &'a Map where K: Key, diff --git a/src/set.rs b/src/set.rs index dea79bf..3203ba5 100644 --- a/src/set.rs +++ b/src/set.rs @@ -1,6 +1,8 @@ //! Contains the fixed [`Set`] implementation. +use core::cmp::Ordering; use core::fmt; +use core::hash::{Hash, Hasher}; use core::iter; use crate::key::Key; @@ -585,6 +587,216 @@ where { } +/// [`Hash`] implementation for a [`Set`]. +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashSet; +/// +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First); +/// +/// let mut set = HashSet::new(); +/// set.insert(a); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use std::collections::HashSet; +/// +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First(true)); +/// +/// // TODO: support this +/// // let mut set = HashSet::new(); +/// // set.insert(a); +/// ``` +impl Hash for Set +where + K: Key, + K::Storage<()>: Hash, +{ + #[inline] + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.storage.hash(state); + } +} + +/// [`PartialOrd`] implementation for a [`Set`]. +/// +/// # Examples +/// +/// ``` +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First); +/// +/// let mut b = Set::new(); +/// b.insert(Key::Second); +/// +/// assert!(a > b); +/// assert!(a >= b); +/// assert!(!(a < b)); +/// assert!(!(a <= b)); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First(true)); +/// +/// let mut b = Set::new(); +/// b.insert(Key::Second); +/// +/// // TODO: support this +/// // assert!(a > b); +/// ``` +impl PartialOrd for Set +where + K: Key, + K::Storage<()>: PartialOrd, +{ + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.storage.partial_cmp(&other.storage) + } + + #[inline] + fn lt(&self, other: &Self) -> bool { + self.storage.lt(&other.storage) + } + + #[inline] + fn le(&self, other: &Self) -> bool { + self.storage.le(&other.storage) + } + + #[inline] + fn gt(&self, other: &Self) -> bool { + self.storage.gt(&other.storage) + } + + #[inline] + fn ge(&self, other: &Self) -> bool { + self.storage.ge(&other.storage) + } +} + +/// [`Ord`] implementation for a [`Set`]. +/// +/// # Examples +/// +/// ``` +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First); +/// +/// let mut b = Set::new(); +/// b.insert(Key::Second); +/// +/// let mut list = vec![a, b]; +/// list.sort(); +/// +/// assert_eq!(list, [b, a]); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First(true)); +/// +/// let mut b = Set::new(); +/// b.insert(Key::Second); +/// +/// // TODO: support this +/// // let mut list = vec![a, b]; +/// // list.sort(); +/// ``` +impl Ord for Set +where + K: Key, + K::Storage<()>: Ord, +{ + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.storage.cmp(&other.storage) + } + + #[inline] + fn max(self, other: Self) -> Self { + Self { + storage: self.storage.max(other.storage), + } + } + + #[inline] + fn min(self, other: Self) -> Self { + Self { + storage: self.storage.min(other.storage), + } + } + + #[inline] + fn clamp(self, min: Self, max: Self) -> Self { + Self { + storage: self.storage.clamp(min.storage, max.storage), + } + } +} + impl<'a, K> IntoIterator for &'a Set where K: Key, From d85726cae4fd3cdc14ba35c1c783645f65cb8e09 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Thu, 27 Oct 2022 09:23:27 +0200 Subject: [PATCH 2/6] Fix comparison operation --- fixed-map-derive/src/unit_variants.rs | 44 ++++++++++++--------------- src/map.rs | 14 ++++----- src/set.rs | 12 ++++---- 3 files changed, 33 insertions(+), 37 deletions(-) diff --git a/fixed-map-derive/src/unit_variants.rs b/fixed-map-derive/src/unit_variants.rs index eb79be0..db19360 100644 --- a/fixed-map-derive/src/unit_variants.rs +++ b/fixed-map-derive/src/unit_variants.rs @@ -59,6 +59,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let mut keys_iter_init = Vec::new(); let mut iter_init = Vec::new(); let mut entry = Vec::new(); + let mut cmp_init = Vec::new(); for (index, variant) in en.variants.iter().enumerate() { let var = &variant.ident; @@ -85,6 +86,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result iter_init.push(quote!((#ident::#var, #name))); names.push(name.clone()); entry.push(quote!(option_to_entry(#name, key))); + cmp_init.push(quote!((#index, #name))); } let count = en.variants.len(); @@ -174,6 +176,18 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result quote!() }; + let self_cmp_iter_init = quote! {{ + let [#(#names),*] = &self.data; + let init: [(usize, &Option); #count] = [#(#cmp_init),*]; + #iterator::flat_map(#into_iter(init), |(k, v)| #option::Some((k, #option::as_ref(v)?))) + }}; + + let other_cmp_iter_init = quote! {{ + let [#(#names),*] = &other.data; + let init: [(usize, &Option); #count] = [#(#cmp_init),*]; + #iterator::flat_map(#into_iter(init), |(k, v)| #option::Some((k, #option::as_ref(v)?))) + }}; + Ok(quote! { const #const_wrapper: () = { #[repr(transparent)] @@ -226,27 +240,27 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result impl #partial_ord for Storage where V: #partial_ord { #[inline] fn partial_cmp(&self, other: &Self) -> Option<#ordering> { - #partial_ord::partial_cmp(&self.data, &other.data) + #iterator::partial_cmp(#self_cmp_iter_init, #other_cmp_iter_init) } #[inline] fn lt(&self, other: &Self) -> bool { - #partial_ord::lt(&self.data, &other.data) + #iterator::lt(#self_cmp_iter_init, #other_cmp_iter_init) } #[inline] fn le(&self, other: &Self) -> bool { - #partial_ord::le(&self.data, &other.data) + #iterator::le(#self_cmp_iter_init, #other_cmp_iter_init) } #[inline] fn gt(&self, other: &Self) -> bool { - #partial_ord::gt(&self.data, &other.data) + #iterator::gt(#self_cmp_iter_init, #other_cmp_iter_init) } #[inline] fn ge(&self, other: &Self) -> bool { - #partial_ord::ge(&self.data, &other.data) + #iterator::ge(#self_cmp_iter_init, #other_cmp_iter_init) } } @@ -254,25 +268,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result impl #ord for Storage where V: #ord { #[inline] fn cmp(&self, other: &Self) -> #ordering { - #ord::cmp(self, other) - } - - #[inline] - fn max(self, other: Self) -> Self { - Self { data: #ord::max(self.data, other.data) } - } - - #[inline] - fn min(self, other: Self) -> Self { - Self { data: #ord::min(self.data, other.data) } - } - - #[inline] - fn clamp(self, min: Self, max: Self) -> Self - where - Self: #partial_ord - { - Self { data: #ord::clamp(self.data, min.data, max.data) } + #iterator::cmp(#self_cmp_iter_init, #other_cmp_iter_init) } } diff --git a/src/map.rs b/src/map.rs index 6582de5..7381273 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1105,10 +1105,10 @@ where /// let mut b = Map::new(); /// b.insert(Key::Second, 1); /// -/// assert!(a > b); -/// assert!(a >= b); -/// assert!(!(a < b)); -/// assert!(!(a <= b)); +/// assert!(a < b); +/// assert!(a <= b); +/// assert!(!(a > b)); +/// assert!(!(a >= b)); /// ``` /// /// Using a composite key: @@ -1129,7 +1129,7 @@ where /// b.insert(Key::Second, 1); /// /// // TODO: support this -/// // assert!(a > b); +/// // assert!(a < b); /// ``` impl PartialOrd for Map where @@ -1181,10 +1181,10 @@ where /// let mut b = Map::new(); /// b.insert(Key::Second, 1); /// -/// let mut list = vec![a, b]; +/// let mut list = vec![b, a]; /// list.sort(); /// -/// assert_eq!(list, [b, a]); +/// assert_eq!(list, [a, b]); /// ``` /// /// Using a composite key: diff --git a/src/set.rs b/src/set.rs index 3203ba5..76f174d 100644 --- a/src/set.rs +++ b/src/set.rs @@ -662,10 +662,10 @@ where /// let mut b = Set::new(); /// b.insert(Key::Second); /// -/// assert!(a > b); -/// assert!(a >= b); -/// assert!(!(a < b)); -/// assert!(!(a <= b)); +/// assert!(a < b); +/// assert!(a <= b); +/// assert!(!(a > b)); +/// assert!(!(a >= b)); /// ``` /// /// Using a composite key: @@ -738,10 +738,10 @@ where /// let mut b = Set::new(); /// b.insert(Key::Second); /// -/// let mut list = vec![a, b]; +/// let mut list = vec![b, a]; /// list.sort(); /// -/// assert_eq!(list, [b, a]); +/// assert_eq!(list, [a, b]); /// ``` /// /// Using a composite key: From d3fef5462d2a2a643ec680128f65d8fff6cd9279 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Thu, 27 Oct 2022 09:40:42 +0200 Subject: [PATCH 3/6] Revert "Fix comparison operation" This reverts commit d85726cae4fd3cdc14ba35c1c783645f65cb8e09. --- fixed-map-derive/src/unit_variants.rs | 44 +++++++++++++++------------ src/map.rs | 14 ++++----- src/set.rs | 12 ++++---- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/fixed-map-derive/src/unit_variants.rs b/fixed-map-derive/src/unit_variants.rs index db19360..eb79be0 100644 --- a/fixed-map-derive/src/unit_variants.rs +++ b/fixed-map-derive/src/unit_variants.rs @@ -59,7 +59,6 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let mut keys_iter_init = Vec::new(); let mut iter_init = Vec::new(); let mut entry = Vec::new(); - let mut cmp_init = Vec::new(); for (index, variant) in en.variants.iter().enumerate() { let var = &variant.ident; @@ -86,7 +85,6 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result iter_init.push(quote!((#ident::#var, #name))); names.push(name.clone()); entry.push(quote!(option_to_entry(#name, key))); - cmp_init.push(quote!((#index, #name))); } let count = en.variants.len(); @@ -176,18 +174,6 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result quote!() }; - let self_cmp_iter_init = quote! {{ - let [#(#names),*] = &self.data; - let init: [(usize, &Option); #count] = [#(#cmp_init),*]; - #iterator::flat_map(#into_iter(init), |(k, v)| #option::Some((k, #option::as_ref(v)?))) - }}; - - let other_cmp_iter_init = quote! {{ - let [#(#names),*] = &other.data; - let init: [(usize, &Option); #count] = [#(#cmp_init),*]; - #iterator::flat_map(#into_iter(init), |(k, v)| #option::Some((k, #option::as_ref(v)?))) - }}; - Ok(quote! { const #const_wrapper: () = { #[repr(transparent)] @@ -240,27 +226,27 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result impl #partial_ord for Storage where V: #partial_ord { #[inline] fn partial_cmp(&self, other: &Self) -> Option<#ordering> { - #iterator::partial_cmp(#self_cmp_iter_init, #other_cmp_iter_init) + #partial_ord::partial_cmp(&self.data, &other.data) } #[inline] fn lt(&self, other: &Self) -> bool { - #iterator::lt(#self_cmp_iter_init, #other_cmp_iter_init) + #partial_ord::lt(&self.data, &other.data) } #[inline] fn le(&self, other: &Self) -> bool { - #iterator::le(#self_cmp_iter_init, #other_cmp_iter_init) + #partial_ord::le(&self.data, &other.data) } #[inline] fn gt(&self, other: &Self) -> bool { - #iterator::gt(#self_cmp_iter_init, #other_cmp_iter_init) + #partial_ord::gt(&self.data, &other.data) } #[inline] fn ge(&self, other: &Self) -> bool { - #iterator::ge(#self_cmp_iter_init, #other_cmp_iter_init) + #partial_ord::ge(&self.data, &other.data) } } @@ -268,7 +254,25 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result impl #ord for Storage where V: #ord { #[inline] fn cmp(&self, other: &Self) -> #ordering { - #iterator::cmp(#self_cmp_iter_init, #other_cmp_iter_init) + #ord::cmp(self, other) + } + + #[inline] + fn max(self, other: Self) -> Self { + Self { data: #ord::max(self.data, other.data) } + } + + #[inline] + fn min(self, other: Self) -> Self { + Self { data: #ord::min(self.data, other.data) } + } + + #[inline] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: #partial_ord + { + Self { data: #ord::clamp(self.data, min.data, max.data) } } } diff --git a/src/map.rs b/src/map.rs index 7381273..6582de5 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1105,10 +1105,10 @@ where /// let mut b = Map::new(); /// b.insert(Key::Second, 1); /// -/// assert!(a < b); -/// assert!(a <= b); -/// assert!(!(a > b)); -/// assert!(!(a >= b)); +/// assert!(a > b); +/// assert!(a >= b); +/// assert!(!(a < b)); +/// assert!(!(a <= b)); /// ``` /// /// Using a composite key: @@ -1129,7 +1129,7 @@ where /// b.insert(Key::Second, 1); /// /// // TODO: support this -/// // assert!(a < b); +/// // assert!(a > b); /// ``` impl PartialOrd for Map where @@ -1181,10 +1181,10 @@ where /// let mut b = Map::new(); /// b.insert(Key::Second, 1); /// -/// let mut list = vec![b, a]; +/// let mut list = vec![a, b]; /// list.sort(); /// -/// assert_eq!(list, [a, b]); +/// assert_eq!(list, [b, a]); /// ``` /// /// Using a composite key: diff --git a/src/set.rs b/src/set.rs index 76f174d..3203ba5 100644 --- a/src/set.rs +++ b/src/set.rs @@ -662,10 +662,10 @@ where /// let mut b = Set::new(); /// b.insert(Key::Second); /// -/// assert!(a < b); -/// assert!(a <= b); -/// assert!(!(a > b)); -/// assert!(!(a >= b)); +/// assert!(a > b); +/// assert!(a >= b); +/// assert!(!(a < b)); +/// assert!(!(a <= b)); /// ``` /// /// Using a composite key: @@ -738,10 +738,10 @@ where /// let mut b = Set::new(); /// b.insert(Key::Second); /// -/// let mut list = vec![b, a]; +/// let mut list = vec![a, b]; /// list.sort(); /// -/// assert_eq!(list, [a, b]); +/// assert_eq!(list, [b, a]); /// ``` /// /// Using a composite key: From bc8af85048ca68da305e5ccb0ef34c6d5c0d04a8 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Thu, 27 Oct 2022 17:15:56 +0200 Subject: [PATCH 4/6] Simplify unit_variants impl --- fixed-map-derive/src/unit_variants.rs | 79 +++++++++------------------ 1 file changed, 25 insertions(+), 54 deletions(-) diff --git a/fixed-map-derive/src/unit_variants.rs b/fixed-map-derive/src/unit_variants.rs index eb79be0..4b425ff 100644 --- a/fixed-map-derive/src/unit_variants.rs +++ b/fixed-map-derive/src/unit_variants.rs @@ -1,5 +1,5 @@ use proc_macro2::{Span, TokenStream}; -use quote::quote; +use quote::{format_ident, quote}; use syn::{DataEnum, Ident}; use crate::context::Ctxt; @@ -44,51 +44,17 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result Span::call_site(), ); - let mut len = Vec::new(); - let mut is_empty = Vec::new(); - let mut pattern = Vec::new(); - let mut names = Vec::new(); - let mut fields = Vec::new(); - let mut field_inits = Vec::new(); - let mut contains_key = Vec::new(); - let mut get = Vec::new(); - let mut get_mut = Vec::new(); - let mut insert = Vec::new(); - let mut remove = Vec::new(); - let mut retain = Vec::new(); - let mut keys_iter_init = Vec::new(); - let mut iter_init = Vec::new(); - let mut entry = Vec::new(); + let count = en.variants.len(); + let mut variants = Vec::with_capacity(count); + let mut names = Vec::with_capacity(count); + let mut field_inits = Vec::with_capacity(count); for (index, variant) in en.variants.iter().enumerate() { - let var = &variant.ident; - let name = Ident::new(&format!("f{}", index), Span::call_site()); - - len.push(quote!(usize::from(#option::is_some(#name)))); - is_empty.push(quote!(#option::is_none(#name))); field_inits.push(quote!(#option::None)); - fields.push(quote!(#option)); - pattern.push(quote!(#ident::#var)); - contains_key.push(quote!(#option::is_some(#name))); - get.push(quote!(#option::as_ref(#name))); - get_mut.push(quote!(#option::as_mut(#name))); - insert.push(quote!(#mem::replace(#name, #option::Some(value)))); - remove.push(quote!(#mem::take(#name))); - retain.push(quote! { - if let Some(val) = #option::as_mut(#name) { - if !func(#ident::#var, val) { - *#name = None; - } - } - }); - keys_iter_init.push(quote!(if #name.is_some() { Some(#ident::#var) } else { None })); - iter_init.push(quote!((#ident::#var, #name))); - names.push(name.clone()); - entry.push(quote!(option_to_entry(#name, key))); + variants.push(&variant.ident); + names.push(format_ident!("_{}", index)); } - let count = en.variants.len(); - let entry_impl = if cfg!(feature = "entry") { quote! { #vis struct VacantEntry<#lt, V> { @@ -165,7 +131,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &mut self.data; match key { - #(#pattern => #entry,)* + #(#ident::#variants => option_to_entry(#names, key),)* } } } @@ -310,13 +276,13 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result #[inline] fn len(&self) -> usize { let [#(#names),*] = &self.data; - 0 #(+ #len)* + 0 #(+ usize::from(#option::is_some(#names)))* } #[inline] fn is_empty(&self) -> bool { let [#(#names),*] = &self.data; - true #(&& #is_empty)* + true #(&& #option::is_none(#names))* } #[inline] @@ -324,7 +290,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &mut self.data; match key { - #(#pattern => #insert,)* + #(#ident::#variants => #mem::replace(#names, #option::Some(value)),)* } } @@ -333,7 +299,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &self.data; match value { - #(#pattern => #contains_key,)* + #(#ident::#variants => #option::is_some(#names),)* } } @@ -342,7 +308,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &self.data; match value { - #(#pattern => #get,)* + #(#ident::#variants => #option::as_ref(#names),)* } } @@ -351,7 +317,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &mut self.data; match value { - #(#pattern => #get_mut,)* + #(#ident::#variants => #option::as_mut(#names),)* } } @@ -360,7 +326,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &mut self.data; match value { - #(#pattern => #remove,)* + #(#ident::#variants => #mem::take(#names),)* } } @@ -370,7 +336,12 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result F: FnMut(#ident, &mut V) -> bool { let [#(#names),*] = &mut self.data; - #(#retain)* + + #(if let Some(val) = #option::as_mut(#names) { + if !func(#ident::#variants, val) { + *#names = None; + } + })* } #[inline] @@ -381,13 +352,13 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result #[inline] fn iter(&self) -> Self::Iter<'_> { let [#(#names),*] = &self.data; - #iterator::flat_map(#into_iter([#(#iter_init),*]), |(k, v)| #option::Some((k, #option::as_ref(v)?))) + #iterator::flat_map(#into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, #option::as_ref(v)?))) } #[inline] fn keys(&self) -> Self::Keys<'_> { let [#(#names),*] = &self.data; - #iterator::flatten(#into_iter([#(#keys_iter_init),*])) + #iterator::flatten(#into_iter([#(if #names.is_some() { Some(#ident::#variants) } else { None }),*])) } #[inline] @@ -398,7 +369,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result #[inline] fn iter_mut(&mut self) -> Self::IterMut<'_> { let [#(#names),*] = &mut self.data; - #iterator::flat_map(#into_iter([#(#iter_init),*]), |(k, v)| #option::Some((k, #option::as_mut(v)?))) + #iterator::flat_map(#into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, #option::as_mut(v)?))) } #[inline] @@ -409,7 +380,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result #[inline] fn into_iter(self) -> Self::IntoIter { let [#(#names),*] = self.data; - #iterator::flat_map(#into_iter([#(#iter_init),*]), |(k, v)| #option::Some((k, v?))) + #iterator::flat_map(#into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, v?))) } } From 80fbf603adff257b7c743f04179d0ebc560b09cc Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Thu, 27 Oct 2022 19:04:43 +0200 Subject: [PATCH 5/6] Simplify token declarations and lazily build paths --- fixed-map-derive/src/any_variants.rs | 151 +++++++++++----------- fixed-map-derive/src/context.rs | 174 +++++++++++++++----------- fixed-map-derive/src/lib.rs | 3 +- fixed-map-derive/src/unit_variants.rs | 114 ++++++++--------- 4 files changed, 242 insertions(+), 200 deletions(-) diff --git a/fixed-map-derive/src/any_variants.rs b/fixed-map-derive/src/any_variants.rs index c90ff83..8e8b6c9 100644 --- a/fixed-map-derive/src/any_variants.rs +++ b/fixed-map-derive/src/any_variants.rs @@ -10,15 +10,15 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let ident = &cx.ast.ident; let lt = cx.lt; - let clone = &cx.toks.clone; - let copy = &cx.toks.copy; - let default = &cx.toks.default; - let eq = &cx.toks.eq; - let key_trait = &cx.toks.key_trait; - let mem = &cx.toks.mem; - let option = &cx.toks.option; - let partial_eq = &cx.toks.partial_eq; - let storage_trait = &cx.toks.storage_trait; + let clone_t = cx.toks.clone_t(); + let copy_t = cx.toks.copy_t(); + let default_t = cx.toks.default_t(); + let eq_t = cx.toks.eq_t(); + let key_t = cx.toks.key_t(); + let mem = cx.toks.mem(); + let option = cx.toks.option(); + let partial_eq_t = cx.toks.partial_eq_t(); + let storage_t = cx.toks.storage_t(); let const_wrapper = Ident::new( &format!("__IMPL_KEY_FOR_{}", cx.ast.ident), @@ -47,17 +47,17 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let var = &variant.ident; let name = Ident::new(&format!("f{}", index), Span::call_site()); - field_inits.push(quote!(#name: #default::default())); - field_clones.push(quote!(#name: #clone::clone(&self.#name))); + field_inits.push(quote!(#name: #default_t::default())); + field_clones.push(quote!(#name: #clone_t::clone(&self.#name))); field_partial_eqs.push(quote! { - if #partial_eq::ne(&self.#name, &other.#name) { + if #partial_eq_t::ne(&self.#name, &other.#name) { return false; } }); field_partial_not_eqs.push(quote! { - if #partial_eq::ne(&self.#name, &other.#name) { + if #partial_eq_t::ne(&self.#name, &other.#name) { return true; } }); @@ -75,7 +75,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result insert.push(quote!(#mem::replace(&mut self.#name, #option::Some(value)))); remove.push(quote!(#mem::replace(&mut self.#name, #option::None))); retain.push(quote! { - if let Some(val) = #option::as_mut(&mut self.#name) { + if let #option::Some(val) = #option::as_mut(&mut self.#name) { if !func(#ident::#var, val) { self.#name = None; } @@ -94,8 +94,8 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } let element = unnamed.unnamed.first().expect("Expected one element"); - let storage = quote!(<#element as #key_trait>::Storage::); - let as_storage = quote!(<#storage as #storage_trait<#element, V>>); + let storage = quote!(<#element as #key_t>::Storage::); + let as_storage = quote!(<#storage as #storage_t<#element, V>>); len.push(quote!(#as_storage::len(&self.#name))); is_empty.push(quote!(#as_storage::is_empty(&self.#name))); @@ -113,7 +113,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result #as_storage::retain(&mut self.#name, |k, v| func(#ident::#var(k), v)); }); - copy_bounds.push(quote!(#storage: #copy)); + copy_bounds.push(quote!(#storage: #copy_t)); FieldKind::Complex { element: quote!(#element), @@ -139,7 +139,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let mut iter_clone = Vec::new(); for FieldSpec { name, .. } in &field_specs { - iter_clone.push(quote!(#name: #clone::clone(&self.#name))); + iter_clone.push(quote!(#name: #clone_t::clone(&self.#name))); } let pattern = &pattern; @@ -165,7 +165,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #clone for Storage where V: #clone { + impl #clone_t for Storage where V: #clone_t { #[inline] fn clone(&self) -> Storage { Storage { @@ -175,10 +175,10 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #copy for Storage where V: #copy, #(#copy_bounds,)* {} + impl #copy_t for Storage where V: #copy_t, #(#copy_bounds,)* {} #[automatically_derived] - impl #partial_eq for Storage where V: #partial_eq { + impl #partial_eq_t for Storage where V: #partial_eq_t { #[inline] fn eq(&self, other: &Storage) -> bool { #(#field_partial_eqs;)* @@ -193,10 +193,10 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #eq for Storage where V: #eq {} + impl #eq_t for Storage where V: #eq_t {} #[automatically_derived] - impl #default for Storage { + impl #default_t for Storage { #[inline] fn default() -> Self { Self { @@ -206,7 +206,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #storage_trait<#ident, V> for Storage { + impl #storage_t<#ident, V> for Storage { type Iter<#lt> = Iter<#lt, V> where V: #lt; type Keys<#lt> = Keys<#lt, V> where V: #lt; type Values<#lt> = Values<#lt, V> where V: #lt; @@ -328,7 +328,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #key_trait for #ident { + impl #key_t for #ident { type Storage = Storage; } @@ -353,9 +353,9 @@ fn build_iter_next( assoc_type: &Ident, lt: Option<&syn::Lifetime>, ) -> Result<(), ()> { - let option = &cx.toks.option; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; + let option = cx.toks.option(); + let iterator_t = cx.toks.iterator_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); let ident = &cx.ast.ident; for FieldSpec { @@ -431,13 +431,14 @@ fn build_iter_impl( let type_name = syn::Ident::new(id, Span::call_site()); let lt = cx.lt; - let option = &cx.toks.option; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; - let clone = &cx.toks.clone; let ident = &cx.ast.ident; let vis = &cx.ast.vis; + let option = cx.toks.option(); + let iterator_t = cx.toks.iterator_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); + let clone_t = cx.toks.clone_t(); + let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -455,7 +456,7 @@ fn build_iter_impl( )?; for FieldSpec { name, kind, .. } in field_specs { - iter_clone.push(quote!(#name: #clone::clone(&self.#name))); + iter_clone.push(quote!(#name: #clone_t::clone(&self.#name))); match kind { FieldKind::Simple => { @@ -484,7 +485,7 @@ fn build_iter_impl( } #[automatically_derived] - impl<#lt, V> #clone for #type_name<#lt, V> where V: #lt { + impl<#lt, V> #clone_t for #type_name<#lt, V> where V: #lt { #[inline] fn clone(&self) -> Self { Self { @@ -528,15 +529,16 @@ fn build_keys_impl( let type_name = syn::Ident::new(id, Span::call_site()); let lt = cx.lt; - let option = &cx.toks.option; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; - let clone = &cx.toks.clone; - let bool_type = &cx.toks.bool_type; - let mem = &cx.toks.mem; let ident = &cx.ast.ident; let vis = &cx.ast.vis; + let bool_type = cx.toks.bool_type(); + let clone_t = cx.toks.clone_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); + let iterator_t = cx.toks.iterator_t(); + let mem = cx.toks.mem(); + let option = cx.toks.option(); + let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -553,7 +555,7 @@ fn build_keys_impl( .. } in field_specs { - iter_clone.push(quote!(#name: #clone::clone(&self.#name))); + iter_clone.push(quote!(#name: #clone_t::clone(&self.#name))); match kind { FieldKind::Simple => { @@ -622,7 +624,7 @@ fn build_keys_impl( } #[automatically_derived] - impl<#lt, V> #clone for #type_name<#lt, V> where V: #lt { + impl<#lt, V> #clone_t for #type_name<#lt, V> where V: #lt { #[inline] fn clone(&self) -> Self { Self { @@ -666,12 +668,13 @@ fn build_values_impl( let type_name = syn::Ident::new(id, Span::call_site()); let lt = cx.lt; - let option = &cx.toks.option; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; - let clone = &cx.toks.clone; let vis = &cx.ast.vis; + let clone_t = cx.toks.clone_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); + let iterator_t = cx.toks.iterator_t(); + let option = cx.toks.option(); + let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -687,7 +690,7 @@ fn build_values_impl( .. } in field_specs { - iter_clone.push(quote!(#name: #clone::clone(&self.#name))); + iter_clone.push(quote!(#name: #clone_t::clone(&self.#name))); match kind { FieldKind::Simple => { @@ -756,7 +759,7 @@ fn build_values_impl( } #[automatically_derived] - impl<#lt, V> #clone for #type_name<#lt, V> where V: #lt { + impl<#lt, V> #clone_t for #type_name<#lt, V> where V: #lt { #[inline] fn clone(&self) -> Self { Self { @@ -799,12 +802,13 @@ fn build_iter_mut_impl( ) -> Result<(TokenStream, Vec), ()> { let type_name = syn::Ident::new(id, Span::call_site()); - let lt = cx.lt; let ident = &cx.ast.ident; + let lt = cx.lt; let vis = &cx.ast.vis; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; - let option = &cx.toks.option; + + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); + let iterator_t = cx.toks.iterator_t(); + let option = cx.toks.option(); let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -885,11 +889,12 @@ fn build_values_mut_impl( let type_name = syn::Ident::new(id, Span::call_site()); let lt = cx.lt; - let option = &cx.toks.option; - let iterator_t = &cx.toks.iterator_t; - let clone = &cx.toks.clone; let vis = &cx.ast.vis; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; + + let option = cx.toks.option(); + let iterator_t = cx.toks.iterator_t(); + let clone_t = cx.toks.clone_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -906,7 +911,7 @@ fn build_values_mut_impl( .. } in field_specs { - iter_clone.push(quote!(#name: #clone::clone(&self.#name))); + iter_clone.push(quote!(#name: #clone_t::clone(&self.#name))); match kind { FieldKind::Simple => { @@ -1008,10 +1013,11 @@ fn build_into_iter_impl( let ident = &cx.ast.ident; let vis = &cx.ast.vis; - let option = &cx.toks.option; - let clone = &cx.toks.clone; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; + + let option = cx.toks.option(); + let clone_t = cx.toks.clone_t(); + let iterator_t = cx.toks.iterator_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -1031,7 +1037,7 @@ fn build_into_iter_impl( )?; for FieldSpec { name, kind, .. } in field_specs { - field_clone.push(quote!(#name: #clone::clone(&self.#name))); + field_clone.push(quote!(#name: #clone_t::clone(&self.#name))); match kind { FieldKind::Simple => { @@ -1045,7 +1051,7 @@ fn build_into_iter_impl( } => { field_decls.push(quote!(#name: #as_storage::IntoIter)); init.push(quote!(#name: #storage::into_iter(self.#name))); - clone_bounds.push(quote!(#as_storage::IntoIter: #clone)); + clone_bounds.push(quote!(#as_storage::IntoIter: #clone_t)); } } } @@ -1060,7 +1066,7 @@ fn build_into_iter_impl( } #[automatically_derived] - impl #clone for #type_name where V: Clone, #(#clone_bounds,)* { + impl #clone_t for #type_name where V: Clone, #(#clone_bounds,)* { #[inline] fn clone(&self) -> Self { Self { @@ -1157,14 +1163,15 @@ fn build_entry_impl(cx: &Ctxt<'_>, field_specs: &[FieldSpec<'_>]) -> Result Self { - Self { - array_into_iter: quote!(::core::array::IntoIter), - bool_type: quote!(::core::primitive::bool), - clone: quote!(::core::clone::Clone), - copy: quote!(::core::marker::Copy), - default: quote!(::core::default::Default), - double_ended_iterator_t: quote!(::core::iter::DoubleEndedIterator), - eq: quote!(::core::cmp::Eq), - hash: quote!(::core::hash::Hash), - hasher: quote!(::core::hash::Hasher), - into_iter: quote!(::core::iter::IntoIterator::into_iter), - iterator_t: quote!(::core::iter::Iterator), - iterator_flatten: quote!(::core::iter::Flatten), - key_trait: quote!(#krate::key::Key), - mem: quote!(::core::mem), - option: quote!(::core::option::Option), - partial_eq: quote!(::core::cmp::PartialEq), - partial_ord: quote!(::core::cmp::PartialOrd), - ordering: quote!(::core::cmp::Ordering), - ord: quote!(::core::cmp::Ord), - slice_iter_mut: quote!(::core::slice::IterMut), - slice_iter: quote!(::core::slice::Iter), - storage_trait: quote!(#krate::storage::Storage), - iterator_flat_map: quote!(::core::iter::FlatMap), - storage_entry_trait: quote!(#krate::storage::entry::StorageEntry), - occupied_entry_trait: quote!(#krate::storage::entry::OccupiedEntry), - vacant_entry_trait: quote!(#krate::storage::entry::VacantEntry), - entry_enum: quote!(#krate::storage::entry::Entry), - option_bucket_option: quote!(#krate::option_bucket::OptionBucket), - option_bucket_some: quote!(#krate::option_bucket::SomeBucket), - option_bucket_none: quote!(#krate::option_bucket::NoneBucket), +// Builder function to use when constructing token. +type Builder = fn(&Toks<'_>) -> Path; + +// Helper macro to define re-usable token paths. +macro_rules! toks { + ($vis:vis struct $ident:ident <$lt:lifetime> { $($field:ident = [$($path:tt)*]),* $(,)? }) => { + $vis struct $ident<$lt> { + core: Path, + crate_prefix: &$lt Path, + $($field: Builder,)* } + + impl<$lt> $ident<$lt> { + /// Construct path tokens with the given prefix. + pub(crate) fn new(crate_prefix: &$lt Path) -> Self { + let core = leading_path(["core"]); + + Self { + core, + crate_prefix, + $($field: toks!(@path $($path)*),)* + } + } + + $( + #[inline] + $vis fn $field(&self) -> Path { + let f = self.$field; + f(self) + } + )* + } + }; + + (@path ::core $(:: $rest:tt)*) => { + |s| suffixed(&s.core, [$(stringify!($rest)),*]) + }; + + (@path crate $(:: $rest:tt)*) => { + |s| suffixed(&s.crate_prefix, [$(stringify!($rest)),*]) + }; +} + +toks! { + pub(crate) struct Toks<'a> { + array_into_iter = [::core::array::IntoIter], + bool_type = [::core::primitive::bool], + clone_t = [::core::clone::Clone], + copy_t = [::core::marker::Copy], + default_t = [::core::default::Default], + double_ended_iterator_t = [::core::iter::DoubleEndedIterator], + entry_enum = [crate::storage::entry::Entry], + eq_t = [::core::cmp::Eq], + hash_t = [::core::hash::Hash], + hasher_t = [::core::hash::Hasher], + into_iterator_t = [::core::iter::IntoIterator], + iterator_flat_map = [::core::iter::FlatMap], + iterator_flatten = [::core::iter::Flatten], + iterator_t = [::core::iter::Iterator], + key_t = [crate::key::Key], + mem = [::core::mem], + occupied_entry_t = [crate::storage::entry::OccupiedEntry], + option = [::core::option::Option], + option_bucket_none = [crate::option_bucket::NoneBucket], + option_bucket_option = [crate::option_bucket::OptionBucket], + option_bucket_some = [crate::option_bucket::SomeBucket], + ord_t = [::core::cmp::Ord], + ordering = [::core::cmp::Ordering], + partial_eq_t = [::core::cmp::PartialEq], + partial_ord_t = [::core::cmp::PartialOrd], + slice_iter = [::core::slice::Iter], + slice_iter_mut = [::core::slice::IterMut], + storage_entry_t = [crate::storage::entry::StorageEntry], + storage_t = [crate::storage::Storage], + vacant_entry_t = [crate::storage::entry::VacantEntry], + } +} + +/// Construct a leading path. +pub(crate) fn leading_path(parts: [&'static str; N]) -> Path { + let mut path = Path { + leading_colon: Some(::default()), + segments: syn::punctuated::Punctuated::default(), + }; + + for part in parts { + let segment = syn::PathSegment::from(syn::Ident::new(part, Span::call_site())); + path.segments.push(segment); } + + path +} + +/// Add the given parts as suffix to the specified prefix path. +fn suffixed(prefix: &Path, parts: [&'static str; N]) -> Path { + let mut path = prefix.clone(); + + for part in parts { + let segment = syn::PathSegment::from(syn::Ident::new(part, Span::call_site())); + path.segments.push(segment); + } + + path } pub(crate) struct Ctxt<'a> { /// Errors collected in the context. errors: RefCell>, /// Generated tokens. - pub(crate) toks: &'a Toks, + pub(crate) toks: &'a Toks<'a>, /// Input ast. pub(crate) ast: &'a DeriveInput, /// Usable lifetime parameter. @@ -87,7 +121,7 @@ pub(crate) struct Ctxt<'a> { } impl<'a> Ctxt<'a> { - pub(crate) fn new(tokens: &'a Toks, ast: &'a DeriveInput, lt: &'a syn::Lifetime) -> Self { + pub(crate) fn new(tokens: &'a Toks<'a>, ast: &'a DeriveInput, lt: &'a syn::Lifetime) -> Self { Self { errors: RefCell::new(Vec::new()), toks: tokens, diff --git a/fixed-map-derive/src/lib.rs b/fixed-map-derive/src/lib.rs index cef94e1..e9c7b72 100644 --- a/fixed-map-derive/src/lib.rs +++ b/fixed-map-derive/src/lib.rs @@ -144,7 +144,8 @@ pub fn storage_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream let ast = syn::parse_macro_input!(input as DeriveInput); let lt = syn::Lifetime::new("'a", ast.span()); - let tokens = context::Toks::new("e!(fixed_map)); + let crate_prefix = context::leading_path(["fixed_map"]); + let tokens = context::Toks::new(&crate_prefix); let cx = context::Ctxt::new(&tokens, &ast, <); let result = impl_storage(&cx); diff --git a/fixed-map-derive/src/unit_variants.rs b/fixed-map-derive/src/unit_variants.rs index 4b425ff..3b94fe5 100644 --- a/fixed-map-derive/src/unit_variants.rs +++ b/fixed-map-derive/src/unit_variants.rs @@ -8,36 +8,36 @@ use crate::context::Ctxt; pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result { let vis = &cx.ast.vis; let ident = &cx.ast.ident; - let lt = cx.lt; - let clone = &cx.toks.clone; - let copy = &cx.toks.copy; - let default = &cx.toks.default; - let eq = &cx.toks.eq; - let hash = &cx.toks.hash; - let hasher = &cx.toks.hasher; - let into_iter = &cx.toks.into_iter; - let iterator = &cx.toks.iterator_t; - let iterator_flatten = &cx.toks.iterator_flatten; - let key_trait = &cx.toks.key_trait; - let mem = &cx.toks.mem; - let option = &cx.toks.option; - let partial_eq = &cx.toks.partial_eq; - let partial_ord = &cx.toks.partial_ord; - let ordering = &cx.toks.ordering; - let ord = &cx.toks.ord; - let slice_iter = &cx.toks.slice_iter; - let slice_iter_mut = &cx.toks.slice_iter_mut; - let array_into_iter = &cx.toks.array_into_iter; - let storage_trait = &cx.toks.storage_trait; - let iterator_flat_map = &cx.toks.iterator_flat_map; - let storage_entry_trait = &cx.toks.storage_entry_trait; - let occupied_entry_trait = &cx.toks.occupied_entry_trait; - let vacant_entry_trait = &cx.toks.vacant_entry_trait; - let entry_enum = &cx.toks.entry_enum; - let option_bucket_option = &cx.toks.option_bucket_option; - let option_bucket_some = &cx.toks.option_bucket_some; - let option_bucket_none = &cx.toks.option_bucket_none; + + let array_into_iter = cx.toks.array_into_iter(); + let clone_t = cx.toks.clone_t(); + let copy_t = cx.toks.copy_t(); + let default = cx.toks.default_t(); + let entry_enum = cx.toks.entry_enum(); + let eq = cx.toks.eq_t(); + let hash = cx.toks.hash_t(); + let hasher = cx.toks.hasher_t(); + let into_iterator_t = cx.toks.into_iterator_t(); + let iterator_flat_map = cx.toks.iterator_flat_map(); + let iterator_flatten = cx.toks.iterator_flatten(); + let iterator_t = cx.toks.iterator_t(); + let key_trait = cx.toks.key_t(); + let mem = cx.toks.mem(); + let occupied_entry_t = cx.toks.occupied_entry_t(); + let option = cx.toks.option(); + let option_bucket_none = cx.toks.option_bucket_none(); + let option_bucket_option = cx.toks.option_bucket_option(); + let option_bucket_some = cx.toks.option_bucket_some(); + let ord_t = cx.toks.ord_t(); + let ordering = cx.toks.ordering(); + let partial_eq_t = cx.toks.partial_eq_t(); + let partial_ord_t = cx.toks.partial_ord_t(); + let slice_iter = cx.toks.slice_iter(); + let slice_iter_mut = cx.toks.slice_iter_mut(); + let storage_entry_t = cx.toks.storage_entry_t(); + let storage_trait = cx.toks.storage_t(); + let vacant_entry_t = cx.toks.vacant_entry_t(); let const_wrapper = Ident::new( &format!("__IMPL_KEY_FOR_{}", cx.ast.ident), @@ -63,7 +63,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl<#lt, V> #vacant_entry_trait<#lt, #ident, V> for VacantEntry<#lt, V> { + impl<#lt, V> #vacant_entry_t<#lt, #ident, V> for VacantEntry<#lt, V> { #[inline] fn key(&self) -> #ident { self.key @@ -81,7 +81,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl<#lt, V> #occupied_entry_trait<#lt, #ident, V> for OccupiedEntry<#lt, V> { + impl<#lt, V> #occupied_entry_t<#lt, #ident, V> for OccupiedEntry<#lt, V> { #[inline] fn key(&self) -> #ident { self.key @@ -122,7 +122,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #storage_entry_trait<#ident, V> for Storage { + impl #storage_entry_t<#ident, V> for Storage { type Occupied<#lt> = OccupiedEntry<#lt, V> where V: #lt; type Vacant<#lt> = VacantEntry<#lt, V> where V: #lt; @@ -148,29 +148,29 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #clone for Storage where V: #clone { + impl #clone_t for Storage where V: #clone_t { #[inline] fn clone(&self) -> Storage { Storage { - data: #clone::clone(&self.data), + data: #clone_t::clone(&self.data), } } } #[automatically_derived] - impl #copy for Storage where V: #copy { + impl #copy_t for Storage where V: #copy_t { } #[automatically_derived] - impl #partial_eq for Storage where V: #partial_eq { + impl #partial_eq_t for Storage where V: #partial_eq_t { #[inline] fn eq(&self, other: &Storage) -> bool { - #partial_eq::eq(&self.data, &other.data) + #partial_eq_t::eq(&self.data, &other.data) } #[inline] fn ne(&self, other: &Storage) -> bool { - #partial_eq::ne(&self.data, &other.data) + #partial_eq_t::ne(&self.data, &other.data) } } @@ -189,56 +189,56 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #partial_ord for Storage where V: #partial_ord { + impl #partial_ord_t for Storage where V: #partial_ord_t { #[inline] fn partial_cmp(&self, other: &Self) -> Option<#ordering> { - #partial_ord::partial_cmp(&self.data, &other.data) + #partial_ord_t::partial_cmp(&self.data, &other.data) } #[inline] fn lt(&self, other: &Self) -> bool { - #partial_ord::lt(&self.data, &other.data) + #partial_ord_t::lt(&self.data, &other.data) } #[inline] fn le(&self, other: &Self) -> bool { - #partial_ord::le(&self.data, &other.data) + #partial_ord_t::le(&self.data, &other.data) } #[inline] fn gt(&self, other: &Self) -> bool { - #partial_ord::gt(&self.data, &other.data) + #partial_ord_t::gt(&self.data, &other.data) } #[inline] fn ge(&self, other: &Self) -> bool { - #partial_ord::ge(&self.data, &other.data) + #partial_ord_t::ge(&self.data, &other.data) } } #[automatically_derived] - impl #ord for Storage where V: #ord { + impl #ord_t for Storage where V: #ord_t { #[inline] fn cmp(&self, other: &Self) -> #ordering { - #ord::cmp(self, other) + #ord_t::cmp(self, other) } #[inline] fn max(self, other: Self) -> Self { - Self { data: #ord::max(self.data, other.data) } + Self { data: #ord_t::max(self.data, other.data) } } #[inline] fn min(self, other: Self) -> Self { - Self { data: #ord::min(self.data, other.data) } + Self { data: #ord_t::min(self.data, other.data) } } #[inline] fn clamp(self, min: Self, max: Self) -> Self where - Self: #partial_ord + Self: #partial_ord_t { - Self { data: #ord::clamp(self.data, min.data, max.data) } + Self { data: #ord_t::clamp(self.data, min.data, max.data) } } } @@ -337,7 +337,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result { let [#(#names),*] = &mut self.data; - #(if let Some(val) = #option::as_mut(#names) { + #(if let #option::Some(val) = #option::as_mut(#names) { if !func(#ident::#variants, val) { *#names = None; } @@ -352,35 +352,35 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result #[inline] fn iter(&self) -> Self::Iter<'_> { let [#(#names),*] = &self.data; - #iterator::flat_map(#into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, #option::as_ref(v)?))) + #iterator_t::flat_map(#into_iterator_t::into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, #option::as_ref(v)?))) } #[inline] fn keys(&self) -> Self::Keys<'_> { let [#(#names),*] = &self.data; - #iterator::flatten(#into_iter([#(if #names.is_some() { Some(#ident::#variants) } else { None }),*])) + #iterator_t::flatten(#into_iterator_t::into_iter([#(if #names.is_some() { Some(#ident::#variants) } else { None }),*])) } #[inline] fn values(&self) -> Self::Values<'_> { - #iterator::flatten(#into_iter(&self.data)) + #iterator_t::flatten(#into_iterator_t::into_iter(&self.data)) } #[inline] fn iter_mut(&mut self) -> Self::IterMut<'_> { let [#(#names),*] = &mut self.data; - #iterator::flat_map(#into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, #option::as_mut(v)?))) + #iterator_t::flat_map(#into_iterator_t::into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, #option::as_mut(v)?))) } #[inline] fn values_mut(&mut self) -> Self::ValuesMut<'_> { - #iterator::flatten(#into_iter(&mut self.data)) + #iterator_t::flatten(#into_iterator_t::into_iter(&mut self.data)) } #[inline] fn into_iter(self) -> Self::IntoIter { let [#(#names),*] = self.data; - #iterator::flat_map(#into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, v?))) + #iterator_t::flat_map(#into_iterator_t::into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, v?))) } } From 15c82feb442df421ccc23d508c9cf6572c767f9a Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Thu, 27 Oct 2022 19:11:03 +0200 Subject: [PATCH 6/6] Go gently into that dark night Clippy --- fixed-map-derive/src/context.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/fixed-map-derive/src/context.rs b/fixed-map-derive/src/context.rs index 8ffda17..70ae631 100644 --- a/fixed-map-derive/src/context.rs +++ b/fixed-map-derive/src/context.rs @@ -30,6 +30,7 @@ macro_rules! toks { $( #[inline] + #[allow(clippy::wrong_self_convention)] $vis fn $field(&self) -> Path { let f = self.$field; f(self)