use syn::{
GenericParam, Ident, Meta, Path, Type, WherePredicate, punctuated::Punctuated, token::Comma,
};
use crate::common::{
r#type::BoundExceptions,
where_predicates_bool::{
WherePredicates, WherePredicatesOrBool,
create_where_predicates_from_all_generic_parameters,
create_where_predicates_from_bare_field_types, create_where_predicates_from_field_types,
meta_2_where_predicates,
},
};
pub(crate) const BOUND_EXCEPTIONS_CLONE: BoundExceptions = BoundExceptions {
unconditional_types: &["Arc", "Rc", "Weak", "NonNull", "Cow", "Discriminant"],
forwarding_types: &[
"Option",
"Result",
"Box",
"Vec",
"VecDeque",
"LinkedList",
"BTreeMap",
"BTreeSet",
"BinaryHeap",
"HashMap",
"HashSet",
"RefCell",
"Wrapping",
"Reverse",
"Saturating",
],
shared_reference_is_unconditional: true,
};
pub(crate) const BOUND_EXCEPTIONS_COPY: BoundExceptions = BoundExceptions {
unconditional_types: &["Arc", "Rc", "Weak", "NonNull", "Cow", "Discriminant"],
forwarding_types: &["Option", "Result", "Wrapping", "Reverse", "Saturating"],
shared_reference_is_unconditional: true,
};
pub(crate) const BOUND_EXCEPTIONS_DEBUG: BoundExceptions = BoundExceptions {
unconditional_types: &["Weak", "NonNull", "AtomicPtr", "Discriminant"],
forwarding_types: &[
"Option",
"Result",
"Box",
"Vec",
"VecDeque",
"LinkedList",
"BTreeMap",
"BTreeSet",
"BinaryHeap",
"HashMap",
"HashSet",
"Arc",
"Rc",
"RefCell",
"Mutex",
"RwLock",
"Wrapping",
"Reverse",
"Saturating",
],
shared_reference_is_unconditional: false,
};
const FORWARDING_TYPES_COMPARISON: &[&str] = &[
"Option",
"Result",
"Box",
"Vec",
"VecDeque",
"LinkedList",
"BTreeMap",
"BTreeSet",
"Arc",
"Rc",
"RefCell",
"Wrapping",
"Reverse",
"Saturating",
];
pub(crate) const BOUND_EXCEPTIONS_EQUALITY: BoundExceptions = BoundExceptions {
unconditional_types: &["NonNull", "Discriminant"],
forwarding_types: FORWARDING_TYPES_COMPARISON,
shared_reference_is_unconditional: false,
};
pub(crate) const BOUND_EXCEPTIONS_HASH: BoundExceptions = BoundExceptions {
unconditional_types: &["NonNull", "Discriminant"],
forwarding_types: &[
"Option",
"Result",
"Box",
"Vec",
"VecDeque",
"LinkedList",
"BTreeMap",
"BTreeSet",
"Arc",
"Rc",
"Wrapping",
"Reverse",
"Saturating",
],
shared_reference_is_unconditional: false,
};
pub(crate) const BOUND_EXCEPTIONS_ORDER: BoundExceptions = BoundExceptions {
unconditional_types: &["NonNull"],
forwarding_types: FORWARDING_TYPES_COMPARISON,
shared_reference_is_unconditional: false,
};
pub(crate) const BOUND_EXCEPTIONS_DEFAULT: BoundExceptions = BoundExceptions {
unconditional_types: &[
"Option",
"Vec",
"VecDeque",
"LinkedList",
"HashMap",
"HashSet",
"BTreeMap",
"BTreeSet",
"Weak",
],
forwarding_types: &[
"Box",
"Arc",
"Rc",
"Cell",
"RefCell",
"Mutex",
"RwLock",
"Wrapping",
"Reverse",
"Saturating",
],
shared_reference_is_unconditional: false,
};
pub(crate) enum Bound {
Disabled,
Auto,
All,
Custom(WherePredicates),
}
impl Bound {
#[inline]
pub(crate) fn from_meta(meta: &Meta) -> syn::Result<Self> {
debug_assert!(meta.path().is_ident("bound"));
Ok(match meta_2_where_predicates(meta)? {
WherePredicatesOrBool::WherePredicates(where_predicates) => {
Self::Custom(where_predicates)
},
WherePredicatesOrBool::Bool(b) => {
if b {
Self::Auto
} else {
Self::Disabled
}
},
WherePredicatesOrBool::All => Self::All,
})
}
}
impl Bound {
#[inline]
pub(crate) fn into_where_predicates_by_generic_parameters_check_types(
self,
params: &Punctuated<GenericParam, Comma>,
bound_trait: &Path,
types: &[&Type],
self_ident: &Ident,
exceptions: &BoundExceptions,
) -> Punctuated<WherePredicate, Comma> {
match self {
Self::Disabled => Punctuated::new(),
Self::Auto => create_where_predicates_from_field_types(
params,
bound_trait,
types,
self_ident,
exceptions,
),
Self::All => create_where_predicates_from_all_generic_parameters(params, bound_trait),
Self::Custom(where_predicates) => where_predicates,
}
}
#[inline]
pub(crate) fn into_where_predicates_by_generic_parameters_check_types_shallow(
self,
params: &Punctuated<GenericParam, Comma>,
bound_trait: &Path,
types: &[&Type],
) -> Punctuated<WherePredicate, Comma> {
match self {
Self::Disabled => Punctuated::new(),
Self::Auto => create_where_predicates_from_bare_field_types(params, bound_trait, types),
Self::All => create_where_predicates_from_all_generic_parameters(params, bound_trait),
Self::Custom(where_predicates) => where_predicates,
}
}
}