mirror of
https://github.com/enso-org/enso.git
synced 2024-12-18 19:41:32 +03:00
#[derive(CloneRef)] also works on types with type-level bounds. (https://github.com/enso-org/ide/pull/323)
Original commit: b9f9c37d96
This commit is contained in:
parent
546aeb4ec0
commit
0c5b5b8081
@ -7,13 +7,13 @@ pub use enso_prelude as prelude;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use proc_macro2::TokenTree;
|
||||
use quote::quote;
|
||||
use syn;
|
||||
use syn::visit::Visit;
|
||||
use proc_macro2::TokenStream;
|
||||
use proc_macro2::TokenTree;
|
||||
|
||||
|
||||
use syn::WhereClause;
|
||||
use syn::WherePredicate;
|
||||
|
||||
// =========================
|
||||
// === Token Stream Utils ===
|
||||
@ -240,6 +240,18 @@ pub fn variant_depends_on
|
||||
|
||||
|
||||
|
||||
// ===================
|
||||
// === WhereClause ===
|
||||
// ===================
|
||||
|
||||
/// Creates a new where clause from provided sequence of where predicates.
|
||||
pub fn new_where_clause(predicates:impl IntoIterator<Item=WherePredicate>) -> WhereClause {
|
||||
let predicates = syn::punctuated::Punctuated::from_iter(predicates);
|
||||
WhereClause {where_token:default(),predicates}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// =============
|
||||
// === Tests ===
|
||||
// =============
|
||||
|
@ -36,3 +36,21 @@ struct StructUnnamedBound<T>(T);
|
||||
#[derive(CloneRef,Clone)]
|
||||
#[clone_ref(bound="T:CloneRef,U:CloneRef")]
|
||||
struct StructUnnamedBoundTwoPatams<T,U>(T,U);
|
||||
|
||||
#[derive(Clone,CloneRef)]
|
||||
#[clone_ref(bound="T:Clone+Display")]
|
||||
struct StructBoundGeneric<T:Display>(Rc<T>);
|
||||
|
||||
#[derive(CloneRef,Derivative)]
|
||||
#[derivative(Clone(bound=""))]
|
||||
// Note: CloneRef "knows" about `Display` bound.
|
||||
struct StructGenericLifetime<'t>(Rc<&'t String>);
|
||||
|
||||
#[derive(CloneRef,Derivative)]
|
||||
#[derivative(Clone(bound=""))]
|
||||
struct StructWhereClause<T>(Rc<T>) where T:Debug;
|
||||
|
||||
#[derive(CloneRef,Clone)]
|
||||
#[clone_ref(bound="T:CloneRef")]
|
||||
// Here derive macro must correctly merge user-provided bound, generics list bound and where clause.
|
||||
struct StructVariousBounds<T:Display>(T) where T:Debug;
|
||||
|
@ -5,11 +5,12 @@ use macro_utils::identifier_sequence;
|
||||
use macro_utils::index_sequence;
|
||||
use macro_utils::path_matching_ident;
|
||||
use syn::Attribute;
|
||||
use syn::Ident;
|
||||
use syn::DeriveInput;
|
||||
use syn::Data;
|
||||
use syn::DataEnum;
|
||||
use syn::DataStruct;
|
||||
use syn::Fields;
|
||||
use syn::Ident;
|
||||
use syn::Lit;
|
||||
use syn::Meta;
|
||||
use syn::MetaNameValue;
|
||||
@ -19,6 +20,7 @@ use syn::WhereClause;
|
||||
use syn::WherePredicate;
|
||||
|
||||
|
||||
|
||||
// ==============
|
||||
// === Consts ===
|
||||
// ==============
|
||||
@ -184,8 +186,7 @@ pub fn clone_ref_bounds(attr:&Attribute) -> Option<Vec<WherePredicate>> {
|
||||
/// Derives `CloneRef` implementation, refer to `crate::derive_clone_ref` for details.
|
||||
pub fn derive
|
||||
(input:proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let decl = syn::parse_macro_input!(input as syn::DeriveInput);
|
||||
let params = &decl.generics.params.iter().collect::<Vec<_>>();
|
||||
let decl = syn::parse_macro_input!(input as DeriveInput);
|
||||
let ident = &decl.ident;
|
||||
let body = match &decl.data {
|
||||
Data::Struct(data_struct) => body_for_struct(ident,data_struct),
|
||||
@ -193,10 +194,20 @@ pub fn derive
|
||||
Data::Union(_) =>
|
||||
panic!("CloneRef cannot be derived for an untagged union input."),
|
||||
};
|
||||
let bounds = decl.attrs.iter().filter_map(clone_ref_bounds).flatten();
|
||||
|
||||
let (impl_generics, ty_generics, inherent_where_clause_opt) = &decl.generics.split_for_impl();
|
||||
|
||||
// Where clause must contain both user-provided bounds and bounds inherent due to type
|
||||
// declaration-level where clause.
|
||||
let user_requested_bounds = decl.attrs.iter().filter_map(clone_ref_bounds).flatten();
|
||||
let mut where_clause = macro_utils::new_where_clause(user_requested_bounds);
|
||||
for inherent_where_clause in inherent_where_clause_opt {
|
||||
where_clause.predicates.extend(inherent_where_clause.predicates.iter().cloned())
|
||||
}
|
||||
|
||||
let output = quote!{
|
||||
impl <#(#params),*> CloneRef for #ident<#(#params),*>
|
||||
where #(#bounds),* {
|
||||
impl #impl_generics CloneRef for #ident #ty_generics
|
||||
#where_clause {
|
||||
fn clone_ref(&self) -> Self {
|
||||
#body
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user