From f2830758ab34e52a32a8ee8e24d70a3231b884fc Mon Sep 17 00:00:00 2001 From: Tomasz Kulik Date: Sat, 20 Apr 2024 17:00:04 +0200 Subject: [PATCH 1/3] feat: Remove types forwarding to interface in sv::messages --- README.md | 52 ----- .../contracts/cw1-subkeys/src/contract.rs | 2 +- .../contracts/cw1-whitelist/src/contract.rs | 2 +- examples/contracts/cw20-base/src/contract.rs | 2 +- .../generic_contract/src/bin/schema.rs | 4 +- .../generic_contract/src/contract.rs | 32 ++-- .../src/custom_and_generic.rs | 32 ++-- .../contracts/generic_contract/src/cw1.rs | 31 +-- .../contracts/generic_contract/src/generic.rs | 32 ++-- .../generic_iface_on_contract/src/contract.rs | 4 +- .../generics_forwarded/src/bin/schema.rs | 6 +- .../generics_forwarded/src/contract.rs | 36 ++-- .../src/custom_and_generic.rs | 36 ++-- .../contracts/generics_forwarded/src/cw1.rs | 35 ++-- .../generics_forwarded/src/generic.rs | 36 ++-- sylvia-derive/src/input.rs | 7 +- sylvia-derive/src/interfaces.rs | 62 +++--- sylvia-derive/src/message.rs | 179 +++++++++--------- sylvia-derive/src/multitest.rs | 50 +++-- .../src/parser/attributes/messages.rs | 2 +- sylvia-derive/src/querier.rs | 2 +- sylvia-derive/src/utils.rs | 27 +-- sylvia/tests/api.rs | 4 +- sylvia/tests/multitest.rs | 4 +- sylvia/tests/querier.rs | 2 +- .../messages/unexpected_token.stderr | 2 +- 26 files changed, 311 insertions(+), 372 deletions(-) diff --git a/README.md b/README.md index 383f1df6..856d9e21 100644 --- a/README.md +++ b/README.md @@ -689,58 +689,6 @@ where } ``` -### Implement interface - -```rust -impl - Generic - for crate::contract::GenericContract< - InstantiateParam, - ExecParam, - FieldType, - > -{ - type Error = StdError; - type ExecParam = ExecParam; - type QueryParam: SvCustomMsg; - type RetType = SvCustomMsg; - - fn generic_exec( - &self, - _ctx: ExecCtx, - _msgs: Vec>, - ) -> StdResult { - Ok(Response::new()) - } - - fn generic_query( - &self, - _ctx: QueryCtx, - _msg: Self::QueryParam, - ) -> StdResult { - Ok(SvCustomMsg {}) - } -} -``` - -Now we have to inform Sylvia that the interface implemented for the contract has associated types. -We have to list those types (generics or concrete) next to the interface in the `#[sv::messages]` -attribute: - -```rust -#[contract] -#[sv::messages(generic as Generic)] -impl - GenericContract -where - for<'msg_de> InstantiateParam: CustomMsg + Deserialize<'msg_de> + 'msg_de, - ExecParam: CustomMsg + DeserializeOwned + 'static, - FieldType: 'static, -{ - ... -} -``` - ### Generics in entry_points Entry points have to be generated with concrete types. Using the `entry_points` macro diff --git a/examples/contracts/cw1-subkeys/src/contract.rs b/examples/contracts/cw1-subkeys/src/contract.rs index 30deacb4..131c887d 100644 --- a/examples/contracts/cw1-subkeys/src/contract.rs +++ b/examples/contracts/cw1-subkeys/src/contract.rs @@ -36,7 +36,7 @@ pub struct Cw1SubkeysContract<'a> { #[sv::error(ContractError)] #[sv::messages(cw1 as Cw1)] #[sv::messages(whitelist as Whitelist)] -impl Cw1SubkeysContract<'_> { +impl<'abcd> Cw1SubkeysContract<'abcd> { pub const fn new() -> Self { Self { whitelist: Cw1WhitelistContract::new(), diff --git a/examples/contracts/cw1-whitelist/src/contract.rs b/examples/contracts/cw1-whitelist/src/contract.rs index a1738d31..fd73cd7f 100644 --- a/examples/contracts/cw1-whitelist/src/contract.rs +++ b/examples/contracts/cw1-whitelist/src/contract.rs @@ -22,7 +22,7 @@ pub struct Cw1WhitelistContract<'a> { #[sv::error(ContractError)] #[sv::messages(cw1 as Cw1)] #[sv::messages(whitelist as Whitelist)] -impl Cw1WhitelistContract<'_> { +impl<'a> Cw1WhitelistContract<'a> { pub const fn new() -> Self { Self { admins: Map::new("admins"), diff --git a/examples/contracts/cw20-base/src/contract.rs b/examples/contracts/cw20-base/src/contract.rs index 8979c729..c594fe26 100644 --- a/examples/contracts/cw20-base/src/contract.rs +++ b/examples/contracts/cw20-base/src/contract.rs @@ -78,7 +78,7 @@ pub struct Cw20Base<'a> { #[sv::messages(cw20_allowances as Allowances)] #[sv::messages(cw20_marketing as Marketing)] #[sv::messages(cw20_minting as Minting)] -impl Cw20Base<'_> { +impl<'abcd> Cw20Base<'abcd> { pub const fn new() -> Self { Self { token_info: Item::new("token_info"), diff --git a/examples/contracts/generic_contract/src/bin/schema.rs b/examples/contracts/generic_contract/src/bin/schema.rs index 5cb3b229..6cd3cfdc 100644 --- a/examples/contracts/generic_contract/src/bin/schema.rs +++ b/examples/contracts/generic_contract/src/bin/schema.rs @@ -7,7 +7,7 @@ fn main() { write_api! { instantiate: InstantiateMsg, - execute: ContractExecMsg, - query: ContractQueryMsg, + execute: ContractExecMsg, + query: ContractQueryMsg, } } diff --git a/examples/contracts/generic_contract/src/contract.rs b/examples/contracts/generic_contract/src/contract.rs index cf97a4ad..2b641522 100644 --- a/examples/contracts/generic_contract/src/contract.rs +++ b/examples/contracts/generic_contract/src/contract.rs @@ -50,8 +50,8 @@ pub struct GenericContract< #[cfg_attr(not(feature = "library"), entry_points(generics))] #[contract] #[sv::messages(cw1 as Cw1: custom(msg, query))] -#[sv::messages(generic as Generic: custom(msg, query))] -#[sv::messages(custom_and_generic as CustomAndGeneric)] +#[sv::messages(generic as Generic: custom(msg, query))] +#[sv::messages(custom_and_generic as CustomAndGeneric)] #[sv::custom(msg=SvCustomMsg, query=SvCustomQuery)] impl< InstantiateT, @@ -194,7 +194,7 @@ where #[cfg(test)] mod tests { use super::sv::mt::CodeId; - use super::{SvCustomMsg, SvCustomQuery}; + use super::{GenericContract, SvCustomMsg, SvCustomQuery}; use crate::contract::sv::mt::GenericContractProxy; use cw_multi_test::IntoBech32; use sylvia::multitest::App; @@ -204,18 +204,20 @@ mod tests { let app = App::>::custom(|_, _, _| {}); #[allow(clippy::type_complexity)] let code_id: CodeId< - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - String, + GenericContract< + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + String, + >, _, > = CodeId::store_code(&app); diff --git a/examples/contracts/generic_contract/src/custom_and_generic.rs b/examples/contracts/generic_contract/src/custom_and_generic.rs index ba635625..001cb74a 100644 --- a/examples/contracts/generic_contract/src/custom_and_generic.rs +++ b/examples/contracts/generic_contract/src/custom_and_generic.rs @@ -2,7 +2,7 @@ use cosmwasm_std::{CosmosMsg, Response, StdError, StdResult}; use custom_and_generic::CustomAndGeneric; use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; -use crate::contract::{SvCustomMsg, SvCustomQuery}; +use crate::contract::{GenericContract, SvCustomMsg, SvCustomQuery}; impl< InstantiateT, @@ -18,7 +18,7 @@ impl< MigrateT, FieldT, > CustomAndGeneric - for crate::contract::GenericContract< + for GenericContract< InstantiateT, Exec1T, Exec2T, @@ -104,7 +104,7 @@ impl< #[cfg(test)] mod tests { - use super::{SvCustomMsg, SvCustomQuery}; + use super::{GenericContract, SvCustomMsg, SvCustomQuery}; use crate::contract::sv::mt::CodeId; use custom_and_generic::sv::mt::CustomAndGenericProxy; use cw_multi_test::IntoBech32; @@ -114,18 +114,20 @@ mod tests { fn proxy_methods() { let app = App::>::custom(|_, _, _| {}); let code_id = CodeId::< - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - String, + GenericContract< + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + String, + >, _, >::store_code(&app); diff --git a/examples/contracts/generic_contract/src/cw1.rs b/examples/contracts/generic_contract/src/cw1.rs index fddbacf0..fff63bbd 100644 --- a/examples/contracts/generic_contract/src/cw1.rs +++ b/examples/contracts/generic_contract/src/cw1.rs @@ -1,3 +1,4 @@ +use crate::contract::GenericContract; use cosmwasm_std::{CosmosMsg, Response, StdError, StdResult}; use cw1::{CanExecuteResp, Cw1}; use sylvia::types::{ExecCtx, QueryCtx}; @@ -16,7 +17,7 @@ impl< MigrateT, FieldT, > Cw1 - for crate::contract::GenericContract< + for GenericContract< InstantiateT, Exec1T, Exec2T, @@ -50,7 +51,7 @@ impl< #[cfg(test)] mod tests { use crate::contract::sv::mt::CodeId; - use crate::contract::{SvCustomMsg, SvCustomQuery}; + use crate::contract::{GenericContract, SvCustomMsg, SvCustomQuery}; use cosmwasm_std::{CosmosMsg, Empty}; use cw1::sv::mt::Cw1Proxy; use cw_multi_test::IntoBech32; @@ -60,18 +61,20 @@ mod tests { fn proxy_methods() { let app = App::>::custom(|_, _, _| {}); let code_id = CodeId::< - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - String, + GenericContract< + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + String, + >, _, >::store_code(&app); diff --git a/examples/contracts/generic_contract/src/generic.rs b/examples/contracts/generic_contract/src/generic.rs index 4c073c85..59541e16 100644 --- a/examples/contracts/generic_contract/src/generic.rs +++ b/examples/contracts/generic_contract/src/generic.rs @@ -3,7 +3,7 @@ use generic::Generic; use serde::Deserialize; use sylvia::types::{CustomMsg, ExecCtx, QueryCtx, SudoCtx}; -use crate::contract::SvCustomMsg; +use crate::contract::{GenericContract, SvCustomMsg}; impl< InstantiateT, @@ -19,7 +19,7 @@ impl< MigrateT, FieldT, > Generic - for crate::contract::GenericContract< + for GenericContract< InstantiateT, Exec1T, Exec2T, @@ -117,7 +117,7 @@ where #[cfg(test)] mod tests { use crate::contract::sv::mt::CodeId; - use crate::contract::{SvCustomMsg, SvCustomQuery}; + use crate::contract::{GenericContract, SvCustomMsg, SvCustomQuery}; use cosmwasm_std::CosmosMsg; use cw_multi_test::IntoBech32; use generic::sv::mt::GenericProxy; @@ -128,18 +128,20 @@ mod tests { let app = App::>::custom(|_, _, _| {}); #[allow(clippy::type_complexity)] let code_id: CodeId< - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - String, + GenericContract< + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + String, + >, _, > = CodeId::store_code(&app); diff --git a/examples/contracts/generic_iface_on_contract/src/contract.rs b/examples/contracts/generic_iface_on_contract/src/contract.rs index 1d89d3c8..43f94183 100644 --- a/examples/contracts/generic_iface_on_contract/src/contract.rs +++ b/examples/contracts/generic_iface_on_contract/src/contract.rs @@ -17,8 +17,8 @@ impl cosmwasm_std::CustomQuery for SvCustomQuery {} #[cfg_attr(not(feature = "library"), entry_points)] #[contract] -#[sv::messages(generic as Generic: custom(msg, query))] -#[sv::messages(custom_and_generic as CustomAndGeneric)] +#[sv::messages(generic as Generic: custom(msg, query))] +#[sv::messages(custom_and_generic as CustomAndGeneric)] #[sv::messages(cw1 as Cw1: custom(msg, query))] /// Required if interface returns generic `Response` #[sv::custom(msg=SvCustomMsg, query=SvCustomQuery)] diff --git a/examples/contracts/generics_forwarded/src/bin/schema.rs b/examples/contracts/generics_forwarded/src/bin/schema.rs index 3295c812..deec2b7b 100644 --- a/examples/contracts/generics_forwarded/src/bin/schema.rs +++ b/examples/contracts/generics_forwarded/src/bin/schema.rs @@ -3,7 +3,7 @@ use cosmwasm_schema::write_api; #[cfg(not(tarpaulin_include))] fn main() { use generics_forwarded::contract::sv::{ContractExecMsg, ContractQueryMsg, InstantiateMsg}; - use generics_forwarded::contract::SvCustomMsg; + use generics_forwarded::contract::{SvCustomMsg, SvCustomQuery}; write_api! { instantiate: InstantiateMsg, @@ -18,7 +18,7 @@ fn main() { // This potentially could be done with some type alias, not sure how it would affect the // schema. // execute: ::ContractExec, - execute: ContractExecMsg, - query: ContractQueryMsg, + execute: ContractExecMsg, + query: ContractQueryMsg, } } diff --git a/examples/contracts/generics_forwarded/src/contract.rs b/examples/contracts/generics_forwarded/src/contract.rs index 6e7d4f59..945ff615 100644 --- a/examples/contracts/generics_forwarded/src/contract.rs +++ b/examples/contracts/generics_forwarded/src/contract.rs @@ -53,9 +53,9 @@ pub struct GenericsForwardedContract< #[cfg_attr(not(feature = "library"), sylvia::entry_points(generics, custom(msg=SvCustomMsg, query=SvCustomQuery)))] #[contract] #[sv::error(ContractError)] -#[sv::messages(generic as Generic: custom(msg, query))] +#[sv::messages(generic as Generic: custom(msg, query))] #[sv::messages(cw1 as Cw1: custom(msg, query))] -#[sv::messages(custom_and_generic as CustomAndGeneric)] +#[sv::messages(custom_and_generic as CustomAndGeneric)] #[sv::custom(msg=CustomMsgT, query=CustomQueryT)] impl< InstantiateT, @@ -204,7 +204,7 @@ where #[cfg(test)] mod tests { use super::sv::mt::CodeId; - use super::{SvCustomMsg, SvCustomQuery}; + use super::{GenericsForwardedContract, SvCustomMsg, SvCustomQuery}; use crate::contract::sv::mt::GenericsForwardedContractProxy; use cw_multi_test::IntoBech32; use sylvia::multitest::App; @@ -214,20 +214,22 @@ mod tests { let app = App::>::custom(|_, _, _| {}); #[allow(clippy::type_complexity)] let code_id: CodeId< - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomQuery, - String, + GenericsForwardedContract< + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomQuery, + String, + >, _, > = CodeId::store_code(&app); diff --git a/examples/contracts/generics_forwarded/src/custom_and_generic.rs b/examples/contracts/generics_forwarded/src/custom_and_generic.rs index 32271367..2d2996a8 100644 --- a/examples/contracts/generics_forwarded/src/custom_and_generic.rs +++ b/examples/contracts/generics_forwarded/src/custom_and_generic.rs @@ -3,7 +3,7 @@ use custom_and_generic::CustomAndGeneric; use serde::Deserialize; use sylvia::types::{CustomMsg, CustomQuery, ExecCtx, QueryCtx, SudoCtx}; -use crate::contract::SvCustomMsg; +use crate::contract::{GenericsForwardedContract, SvCustomMsg}; use crate::error::ContractError; impl< @@ -22,7 +22,7 @@ impl< CustomQueryT, FieldT, > CustomAndGeneric - for crate::contract::GenericsForwardedContract< + for GenericsForwardedContract< InstantiateT, Exec1T, Exec2T, @@ -126,7 +126,7 @@ where #[cfg(test)] mod tests { use crate::contract::sv::mt::CodeId; - use crate::contract::{SvCustomMsg, SvCustomQuery}; + use crate::contract::{GenericsForwardedContract, SvCustomMsg, SvCustomQuery}; use cosmwasm_std::CosmosMsg; use custom_and_generic::sv::mt::CustomAndGenericProxy; use cw_multi_test::IntoBech32; @@ -136,20 +136,22 @@ mod tests { fn proxy_methods() { let app = App::>::custom(|_, _, _| {}); let code_id = CodeId::< - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomQuery, - String, + GenericsForwardedContract< + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomQuery, + String, + >, _, >::store_code(&app); diff --git a/examples/contracts/generics_forwarded/src/cw1.rs b/examples/contracts/generics_forwarded/src/cw1.rs index 0111c87c..a4ddc172 100644 --- a/examples/contracts/generics_forwarded/src/cw1.rs +++ b/examples/contracts/generics_forwarded/src/cw1.rs @@ -5,6 +5,7 @@ use serde::de::DeserializeOwned; use serde::Deserialize; use sylvia::types::{CustomQuery, ExecCtx, QueryCtx}; +use crate::contract::GenericsForwardedContract; use crate::error::ContractError; impl< @@ -23,7 +24,7 @@ impl< CustomQueryT, FieldT, > Cw1 - for crate::contract::GenericsForwardedContract< + for GenericsForwardedContract< InstantiateT, Exec1T, Exec2T, @@ -74,7 +75,7 @@ where #[cfg(test)] mod tests { use crate::contract::sv::mt::CodeId; - use crate::contract::{SvCustomMsg, SvCustomQuery}; + use crate::contract::{GenericsForwardedContract, SvCustomMsg, SvCustomQuery}; use cosmwasm_std::{CosmosMsg, Empty}; use cw1::sv::mt::Cw1Proxy; use cw_multi_test::IntoBech32; @@ -84,20 +85,22 @@ mod tests { fn proxy_methods() { let app = App::>::custom(|_, _, _| {}); let code_id = CodeId::< - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomQuery, - String, + GenericsForwardedContract< + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomQuery, + String, + >, _, >::store_code(&app); diff --git a/examples/contracts/generics_forwarded/src/generic.rs b/examples/contracts/generics_forwarded/src/generic.rs index 28f943f4..c5817544 100644 --- a/examples/contracts/generics_forwarded/src/generic.rs +++ b/examples/contracts/generics_forwarded/src/generic.rs @@ -3,7 +3,7 @@ use generic::Generic; use serde::Deserialize; use sylvia::types::{CustomMsg, CustomQuery, ExecCtx, QueryCtx, SudoCtx}; -use crate::contract::SvCustomMsg; +use crate::contract::{GenericsForwardedContract, SvCustomMsg}; use crate::error::ContractError; impl< @@ -22,7 +22,7 @@ impl< CustomQueryT, FieldT, > Generic - for crate::contract::GenericsForwardedContract< + for GenericsForwardedContract< InstantiateT, Exec1T, Exec2T, @@ -124,7 +124,7 @@ where #[cfg(test)] mod tests { use crate::contract::sv::mt::CodeId; - use crate::contract::{SvCustomMsg, SvCustomQuery}; + use crate::contract::{GenericsForwardedContract, SvCustomMsg, SvCustomQuery}; use cosmwasm_std::CosmosMsg; use cw_multi_test::IntoBech32; use generic::sv::mt::GenericProxy; @@ -135,20 +135,22 @@ mod tests { let app = App::>::custom(|_, _, _| {}); #[allow(clippy::type_complexity)] let code_id: CodeId< - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomMsg, - SvCustomQuery, - String, + GenericsForwardedContract< + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomMsg, + SvCustomQuery, + String, + >, _, > = CodeId::store_code(&app); diff --git a/sylvia-derive/src/input.rs b/sylvia-derive/src/input.rs index 0dccfd98..dbf79105 100644 --- a/sylvia-derive/src/input.rs +++ b/sylvia-derive/src/input.rs @@ -200,14 +200,13 @@ impl<'a> ImplInput<'a> { item, generics, custom, - interfaces, .. } = self; let multitest_helpers = self.emit_multitest_helpers(); let querier = ContractQuerier::new(item).emit(); let messages = self.emit_messages(); - let contract_api = ContractApi::new(item, generics, custom, interfaces).emit(); + let contract_api = ContractApi::new(item, generics, custom).emit(); quote! { pub mod sv { @@ -264,16 +263,12 @@ impl<'a> ImplInput<'a> { } fn emit_glue_msg(&self, msg_ty: MsgType) -> TokenStream { - let Self { generics, item, .. } = self; - let where_clause = &item.generics.where_clause; - let variants = MsgVariants::new(item.as_variants(), msg_ty, generics, where_clause); GlueMessage::new( self.item, msg_ty, &self.error, &self.custom, &self.interfaces, - variants, ) .emit() } diff --git a/sylvia-derive/src/interfaces.rs b/sylvia-derive/src/interfaces.rs index fefc45c2..3cd104de 100644 --- a/sylvia-derive/src/interfaces.rs +++ b/sylvia-derive/src/interfaces.rs @@ -1,7 +1,7 @@ use proc_macro2::{Ident, TokenStream}; use quote::quote; use syn::spanned::Spanned; -use syn::{GenericArgument, ItemImpl}; +use syn::{ItemImpl, Type}; use crate::crate_module; use crate::parser::attributes::msg::MsgType; @@ -18,26 +18,19 @@ impl Interfaces { Self { interfaces } } - pub fn emit_glue_message_variants(&self, msg_ty: &MsgType) -> Vec { - let sylvia = crate_module(); - + pub fn emit_glue_message_variants( + &self, + msg_ty: &MsgType, + contract: &Type, + ) -> Vec { self.interfaces .iter() .map(|interface| { let ContractMessageAttr { - module, - variant, - generics, - .. + module, variant, .. } = interface; - let generics = if !generics.is_empty() { - quote! { < #generics > } - } else { - quote! {} - }; - let interface_enum = - quote! { <#module ::sv::Api #generics as #sylvia ::types::InterfaceApi> }; + let interface_enum = quote! { < #contract as #module ::sv::InterfaceMessagesApi> }; let type_name = msg_ty.as_accessor_name(); quote! { #variant ( #interface_enum :: #type_name) } @@ -45,6 +38,20 @@ impl Interfaces { .collect() } + pub fn emit_glue_message_types(&self, msg_ty: &MsgType, contract: &Type) -> Vec { + self.interfaces + .iter() + .map(|interface| { + let ContractMessageAttr { module, .. } = interface; + + let interface_enum = quote! { < #contract as #module ::sv::InterfaceMessagesApi> }; + let type_name = msg_ty.as_accessor_name(); + + quote! { #interface_enum :: #type_name } + }) + .collect() + } + pub fn emit_messages_call(&self, msg_ty: &MsgType) -> Vec { self.interfaces .iter() @@ -83,25 +90,21 @@ impl Interfaces { .collect() } - pub fn emit_response_schemas_calls(&self, msg_ty: &MsgType) -> Vec { - let sylvia = crate_module(); - + pub fn emit_response_schemas_calls( + &self, + msg_ty: &MsgType, + contract: &Type, + ) -> Vec { self.interfaces .iter() .map(|interface| { let ContractMessageAttr { - module, generics, .. + module, .. } = interface; - let generics = if !generics.is_empty() { - quote! { < #generics > } - } else { - quote! {} - }; - let type_name = msg_ty.as_accessor_name(); quote! { - <#module ::sv::Api #generics as #sylvia ::types::InterfaceApi> :: #type_name :: response_schemas_impl() + <#contract as #module ::sv::InterfaceMessagesApi> :: #type_name :: response_schemas_impl() } }) .collect() @@ -130,11 +133,4 @@ impl Interfaces { } }).collect() } - - pub fn as_generic_args(&self) -> Vec<&GenericArgument> { - self.interfaces - .iter() - .flat_map(|interface| &interface.generics) - .collect() - } } diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs index 64bb5f77..3100e09e 100644 --- a/sylvia-derive/src/message.rs +++ b/sylvia-derive/src/message.rs @@ -9,12 +9,11 @@ use crate::parser::{ use crate::strip_generics::StripGenerics; use crate::strip_self_path::StripSelfPath; use crate::utils::{ - as_where_clause, emit_bracketed_generics, extract_return_type, filter_generics, filter_wheres, - process_fields, SvCasing, + as_where_clause, emit_bracketed_generics, extract_return_type, filter_wheres, process_fields, + SvCasing, }; use crate::variant_descs::{AsVariantDescs, VariantDescs}; use convert_case::{Case, Casing}; -use itertools::Itertools; use proc_macro2::{Span, TokenStream}; use proc_macro_error::emit_error; use quote::{quote, ToTokens}; @@ -817,7 +816,6 @@ pub struct GlueMessage<'a> { error: &'a ContractErrorAttr, custom: &'a Custom, interfaces: &'a Interfaces, - variants: MsgVariants<'a, GenericParam>, } impl<'a> GlueMessage<'a> { @@ -827,7 +825,6 @@ impl<'a> GlueMessage<'a> { error: &'a ContractErrorAttr, custom: &'a Custom, interfaces: &'a Interfaces, - variants: MsgVariants<'a, GenericParam>, ) -> Self { GlueMessage { source, @@ -836,7 +833,6 @@ impl<'a> GlueMessage<'a> { error, custom, interfaces, - variants, } } @@ -849,54 +845,27 @@ impl<'a> GlueMessage<'a> { error, custom, interfaces, - variants, + .. } = self; let generics: Vec<_> = source.generics.params.iter().collect(); - let interface_generic_args = interfaces.as_generic_args(); - let interface_used_generics = filter_generics(&generics, &interface_generic_args); - let used_generics = variants.used_generics(); - - let wrapper_generics: Vec<_> = interface_used_generics - .iter() - .chain(used_generics.iter()) - .unique() - .copied() - .collect(); - - let unused_generics: Vec<_> = variants - .unused_generics() - .iter() - .filter(|unused| !wrapper_generics.iter().any(|used| used == *unused)) - .collect(); - let full_where_clause = &source.generics.where_clause; - let wrapper_predicates = filter_wheres(full_where_clause, &generics, &wrapper_generics); - let wrapper_where_clause = if !wrapper_predicates.is_empty() { - quote! { where #(#wrapper_predicates,)* } - } else { - quote! {} + let bracketed_wrapper_generics = match generics.is_empty() { + true => quote! {}, + false => quote! { < #(#generics,)* > }, }; - let unused_generics = emit_bracketed_generics(&unused_generics); - let bracketed_used_generics = emit_bracketed_generics(used_generics); - let bracketed_wrapper_generics = emit_bracketed_generics(&wrapper_generics); - let contract_enum_name = msg_ty.emit_msg_wrapper_name(); - let enum_name = msg_ty.emit_msg_name(); + let enum_accessor = msg_ty.as_accessor_name(); let contract_name = StripGenerics.fold_type((*contract).clone()); - let variants = interfaces.emit_glue_message_variants(msg_ty); + let variants = interfaces.emit_glue_message_variants(msg_ty, contract); + let types = interfaces.emit_glue_message_types(msg_ty, contract); let ep_name = msg_ty.emit_ep_name(); let messages_fn_name = Ident::new(&format!("{}_messages", ep_name), contract.span()); - let contract_variant = quote! { #contract_name ( #enum_name #bracketed_used_generics ) }; + let contract_variant = quote! { #contract_name ( <#contract as #sylvia ::types::ContractApi> :: #enum_accessor ) }; let mut messages_call = interfaces.emit_messages_call(msg_ty); - let prefixed_used_generics = if !used_generics.is_empty() { - quote! { :: #bracketed_used_generics } - } else { - quote! {} - }; messages_call.push(quote! { &#messages_fn_name() }); let variants_cnt = messages_call.len(); @@ -921,15 +890,15 @@ impl<'a> GlueMessage<'a> { let ctx_type = msg_ty.emit_ctx_type(&custom.query_or_default()); let ret_type = msg_ty.emit_result_type(&custom.msg_or_default(), &error.error); - let mut response_schemas_calls = interfaces.emit_response_schemas_calls(msg_ty); + let mut response_schemas_calls = interfaces.emit_response_schemas_calls(msg_ty, contract); response_schemas_calls - .push(quote! {#enum_name #prefixed_used_generics :: response_schemas_impl()}); + .push(quote! {<#contract as #sylvia ::types::ContractApi> :: #enum_accessor ::response_schemas_impl()}); let response_schemas = match msg_ty { MsgType::Query => { quote! { #[cfg(not(target_arch = "wasm32"))] - impl #bracketed_wrapper_generics #sylvia ::cw_schema::QueryResponses for #contract_enum_name #bracketed_wrapper_generics #wrapper_where_clause { + impl #bracketed_wrapper_generics #sylvia ::cw_schema::QueryResponses for #contract_enum_name #bracketed_wrapper_generics #full_where_clause { fn response_schemas_impl() -> std::collections::BTreeMap { let responses = [#(#response_schemas_calls),*]; responses.into_iter().flatten().collect() @@ -944,15 +913,55 @@ impl<'a> GlueMessage<'a> { quote! { #[allow(clippy::derive_partial_eq_without_eq)] - #[derive(#sylvia ::serde::Serialize, Clone, Debug, PartialEq, #sylvia ::schemars::JsonSchema)] + #[derive(#sylvia ::serde::Serialize, Clone, Debug, PartialEq)] #[serde(rename_all="snake_case", untagged)] - pub enum #contract_enum_name #bracketed_wrapper_generics #wrapper_where_clause { + pub enum #contract_enum_name #bracketed_wrapper_generics #full_where_clause { #(#variants,)* #contract_variant } - impl #bracketed_wrapper_generics #contract_enum_name #bracketed_wrapper_generics #wrapper_where_clause { - pub fn dispatch #unused_generics ( + // `schemars` v0.8.16 requires every generic type to implement JsonSchema in + // order to use derive JsonSchema macro. The goal of that trait bound is to + // generate schema_name. Currently there's no way to provide such a name in an + // attribute, so Sylvia needs to implement this trait manually: + // + impl #bracketed_wrapper_generics #sylvia ::schemars::JsonSchema + for #contract_enum_name #bracketed_wrapper_generics #full_where_clause { + + fn schema_name() -> std::string::String { + { + let res = format!( + "{0}", + std::any::type_name::() + ); + res + } + } + + fn json_schema( + gen: &mut #sylvia ::schemars::gen::SchemaGenerator, + ) -> #sylvia ::schemars::schema::Schema { + schemars::schema::Schema::Object(schemars::schema::SchemaObject { + subschemas: Some( + Box::new(schemars::schema::SubschemaValidation { + any_of: Some( + <[_]>::into_vec( + Box::new([ + #(gen.subschema_for::<#types>(),)* + gen.subschema_for::< <#contract as #sylvia ::types::ContractApi> :: #enum_accessor >(), + ]), + ), + ), + ..Default::default() + }), + ), + ..Default::default() + }) + } + } + + impl #bracketed_wrapper_generics #contract_enum_name #bracketed_wrapper_generics #full_where_clause { + pub fn dispatch ( self, contract: &#contract, ctx: #ctx_type, @@ -971,9 +980,9 @@ impl<'a> GlueMessage<'a> { #response_schemas - impl<'de, #(#wrapper_generics,)* > serde::Deserialize<'de> for #contract_enum_name #bracketed_wrapper_generics #wrapper_where_clause { + impl<'sv_deserializde_lifetime, #(#generics,)* > serde::Deserialize<'sv_deserializde_lifetime> for #contract_enum_name #bracketed_wrapper_generics #full_where_clause { fn deserialize(deserializer: D) -> Result - where D: serde::Deserializer<'de>, + where D: serde::Deserializer<'sv_deserializde_lifetime>, { use serde::de::Error; @@ -1021,16 +1030,10 @@ pub struct ContractApi<'a> { sudo_variants: MsgVariants<'a, GenericParam>, generics: &'a [&'a GenericParam], custom: &'a Custom, - interfaces: &'a Interfaces, } impl<'a> ContractApi<'a> { - pub fn new( - source: &'a ItemImpl, - generics: &'a [&'a GenericParam], - custom: &'a Custom, - interfaces: &'a Interfaces, - ) -> Self { + pub fn new(source: &'a ItemImpl, generics: &'a [&'a GenericParam], custom: &'a Custom) -> Self { let exec_variants = MsgVariants::new( source.as_variants(), MsgType::Exec, @@ -1075,7 +1078,6 @@ impl<'a> ContractApi<'a> { sudo_variants, generics, custom, - interfaces, } } @@ -1090,7 +1092,7 @@ impl<'a> ContractApi<'a> { sudo_variants, generics, custom, - interfaces, + .. } = self; let where_clause = &source.generics.where_clause; @@ -1101,34 +1103,12 @@ impl<'a> ContractApi<'a> { let migrate_generics = &migrate_variants.used_generics; let sudo_generics = &sudo_variants.used_generics; - let interface_generics = interfaces.as_generic_args(); - let interface_generics = filter_generics(generics, &interface_generics); - - let contract_exec_generics: Vec<_> = interface_generics - .iter() - .chain(exec_generics.iter()) - .unique() - .collect(); - let contract_query_generics: Vec<_> = interface_generics - .iter() - .chain(query_generics.iter()) - .unique() - .collect(); - let contract_sudo_generics: Vec<_> = interface_generics - .iter() - .chain(sudo_generics.iter()) - .unique() - .collect(); - let bracket_generics = emit_bracketed_generics(generics); let exec_bracketed_generics = emit_bracketed_generics(exec_generics); let query_bracketed_generics = emit_bracketed_generics(query_generics); let sudo_bracketed_generics = emit_bracketed_generics(sudo_generics); let instantiate_bracketed_generics = emit_bracketed_generics(instantiate_generics); let migrate_bracketed_generics = emit_bracketed_generics(migrate_generics); - let contract_exec_bracketed_generics = emit_bracketed_generics(&contract_exec_generics); - let contract_query_bracketed_generics = emit_bracketed_generics(&contract_query_generics); - let contract_sudo_bracketed_generics = emit_bracketed_generics(&contract_sudo_generics); let migrate_type = if migrate_variants.variants().count() != 0 { quote! { type Migrate = MigrateMsg #migrate_bracketed_generics; } @@ -1139,9 +1119,9 @@ impl<'a> ContractApi<'a> { quote! { impl #bracket_generics #sylvia ::types::ContractApi for #contract_name #where_clause { - type ContractExec = ContractExecMsg #contract_exec_bracketed_generics; - type ContractQuery = ContractQueryMsg #contract_query_bracketed_generics; - type ContractSudo = ContractSudoMsg #contract_sudo_bracketed_generics; + type ContractExec = ContractExecMsg #bracket_generics; + type ContractQuery = ContractQueryMsg #bracket_generics; + type ContractSudo = ContractSudoMsg #bracket_generics; type Exec = ExecMsg #exec_bracketed_generics; type Query = QueryMsg #query_bracketed_generics; type Sudo = SudoMsg #sudo_bracketed_generics; @@ -1181,6 +1161,7 @@ impl<'a> InterfaceApi<'a> { associated_types, } = self; + let interface_name = &source.ident; let generics: Vec<_> = associated_types .without_special() .map(ItemType::as_name) @@ -1210,11 +1191,6 @@ impl<'a> InterfaceApi<'a> { let query_generics = &query_variants.used_generics; let sudo_generics = &sudo_variants.used_generics; - let bracket_generics = emit_bracketed_generics(&generics); - let exec_bracketed_generics = emit_bracketed_generics(exec_generics); - let query_bracketed_generics = emit_bracketed_generics(query_generics); - let sudo_bracketed_generics = emit_bracketed_generics(sudo_generics); - let phantom = if !generics.is_empty() { quote! { _phantom: std::marker::PhantomData<( #(#generics,)* )>, @@ -1224,14 +1200,29 @@ impl<'a> InterfaceApi<'a> { }; quote! { - pub struct Api #bracket_generics { + pub trait InterfaceMessagesApi { + type Exec; + type Query; + type Sudo; + type Querier<'querier>; + } + + impl InterfaceMessagesApi for Contract { + type Exec = ExecMsg < #(:: #exec_generics,)* >; + type Query = QueryMsg < #(:: #query_generics,)* >; + type Sudo = SudoMsg < #(:: #sudo_generics ,)* >; + type Querier<'querier> = #sylvia ::types::BoundQuerier<'querier, #custom_query, Contract >; + } + + + pub struct Api < #(#generics,)* > { #phantom } - impl #bracket_generics #sylvia ::types::InterfaceApi for Api #bracket_generics #where_clause { - type Exec = ExecMsg #exec_bracketed_generics; - type Query = QueryMsg #query_bracketed_generics; - type Sudo = SudoMsg #sudo_bracketed_generics; + impl < #(#generics,)* > #sylvia ::types::InterfaceApi for Api < #(#generics,)* > #where_clause { + type Exec = ExecMsg < #(#exec_generics,)* >; + type Query = QueryMsg < #(#query_generics,)* >; + type Sudo = SudoMsg < #(#sudo_generics,)* >; type Querier<'querier, Contract> = #sylvia ::types::BoundQuerier<'querier, #custom_query, Contract >; } } diff --git a/sylvia-derive/src/multitest.rs b/sylvia-derive/src/multitest.rs index 28f26f78..00541604 100644 --- a/sylvia-derive/src/multitest.rs +++ b/sylvia-derive/src/multitest.rs @@ -140,6 +140,14 @@ impl<'a> ContractMtHelpers<'a> { }; let api = quote! { < #contract_name as #sylvia ::types::ContractApi> }; + let contract_ident = get_ident_from_type(contract_name); + let contract: Type = if !generic_params.is_empty() { + parse_quote! { #contract_ident ::< #(#generic_params,)* > } + } else { + parse_quote! { #contract_ident } + }; + let trait_name = Ident::new(&format!("{}Proxy", contract_ident), contract_ident.span()); + let exec_methods = exec_variants.variants().map(|variant| { variant.emit_mt_method_definition(&custom_msg, &mt_app, error_type, &api) }); @@ -172,17 +180,14 @@ impl<'a> ContractMtHelpers<'a> { let impl_contract = self.emit_impl_contract(); let code_id = self.emit_code_id(); - let instantiate_proxy = self.emit_instantiate_proxy(); - - let contract = get_ident_from_type(contract_name); - let trait_name = Ident::new(&format!("{}Proxy", contract), contract.span()); + let instantiate_proxy = self.emit_instantiate_proxy(&contract); quote! { pub mod mt { use super::*; use #sylvia ::cw_multi_test::Executor; - pub trait #trait_name <'app, MtApp, #(#generic_params,)* > + pub trait #trait_name <'app, #(#generic_params,)* MtApp > #where_clause { #( #exec_methods_declarations )* @@ -191,8 +196,8 @@ impl<'a> ContractMtHelpers<'a> { #( #sudo_methods_declarations )* } - impl<'app, BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, #(#generic_params,)* > - #trait_name <'app, #mt_app, #(#generic_params,)* > + impl<'app, #(#generic_params,)* BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT > + #trait_name <'app, #(#generic_params,)* #mt_app > for #sylvia ::multitest::Proxy <'app, #mt_app, #contract_name > where CustomT: #sylvia ::cw_multi_test::Module, @@ -234,6 +239,15 @@ impl<'a> ContractMtHelpers<'a> { .. } = self; + let generic_params_lifetimes_replaced = + generic_params.iter().cloned().cloned().map(|generic| { + if let GenericParam::Lifetime(_) = generic { + parse_quote! { '_ } + } else { + generic + } + }); + let fields_names = instantiate_variants .get_only_variant() .map(MsgVariant::as_fields_names) @@ -250,11 +264,11 @@ impl<'a> ContractMtHelpers<'a> { .as_ref() .map(|where_clause| &where_clause.predicates); - let contract = get_ident_from_type(contract_name); + let contract_ident = get_ident_from_type(contract_name); let contract = if !generic_params.is_empty() { - quote! { #contract ::< #(#generic_params,)* > } + quote! { #contract_ident ::< #(#generic_params,)* > } } else { - quote! { #contract } + quote! { #contract_ident } }; let instantiate_msg = if !used_generics.is_empty() { @@ -291,14 +305,14 @@ impl<'a> ContractMtHelpers<'a> { }; quote! { - pub struct CodeId<'app, #(#generic_params,)* MtApp> { + pub struct CodeId<'app, Contract, MtApp> { code_id: u64, app: &'app #sylvia ::multitest::App, - _phantom: std::marker::PhantomData<( #(#generic_params,)* )>, + _phantom: std::marker::PhantomData, } - impl<'app, BankT, ApiT, StorageT, CustomT, StakingT, DistrT, IbcT, GovT, #(#generic_params,)* > CodeId<'app, #(#generic_params,)* #mt_app > + impl<'app, #(#generic_params,)* BankT, ApiT, StorageT, CustomT, StakingT, DistrT, IbcT, GovT > CodeId<'app, #contract, #mt_app > where BankT: #sylvia ::cw_multi_test::Bank, ApiT: #sylvia ::cw_std::Api, @@ -313,7 +327,7 @@ impl<'a> ContractMtHelpers<'a> { pub fn store_code(app: &'app #sylvia ::multitest::App< #mt_app >) -> Self { let code_id = app .app_mut() - .store_code(Box::new(#contract ::new())); + .store_code(Box::new( #contract_ident:: < #(#generic_params_lifetimes_replaced),* > ::new() )); Self { code_id, app, _phantom: std::marker::PhantomData::default() } } @@ -327,7 +341,7 @@ impl<'a> ContractMtHelpers<'a> { &self, #(#fields,)* ) -> InstantiateProxy<'_, 'app, #(#generic_params,)* #mt_app > { let msg = #instantiate_msg {#(#fields_names,)*}; - InstantiateProxy::< #(#generic_params,)* _> { + InstantiateProxy::<'_, 'app, #(#generic_params,)* _> { code_id: self, funds: &[], label: "Contract", @@ -340,7 +354,7 @@ impl<'a> ContractMtHelpers<'a> { } } - fn emit_instantiate_proxy(&self) -> TokenStream { + fn emit_instantiate_proxy(&self, contract: &Type) -> TokenStream { let sylvia = crate_module(); let Self { error_type, @@ -364,7 +378,7 @@ impl<'a> ContractMtHelpers<'a> { quote! { pub struct InstantiateProxy<'proxy, 'app, #(#generic_params,)* MtApp> { - code_id: &'proxy CodeId <'app, #(#generic_params,)* MtApp>, + code_id: &'proxy CodeId <'app, #contract, MtApp>, funds: &'proxy [#sylvia ::cw_std::Coin], label: &'proxy str, admin: Option, @@ -385,7 +399,7 @@ impl<'a> ContractMtHelpers<'a> { Self { label, ..self } } - pub fn with_admin<'s>(self, admin: impl Into>) -> Self { + pub fn with_admin<'sv_admins_lifetime>(self, admin: impl Into>) -> Self { let admin = admin.into().map(str::to_owned); Self { admin, ..self } } diff --git a/sylvia-derive/src/parser/attributes/messages.rs b/sylvia-derive/src/parser/attributes/messages.rs index 6f49b702..0b9e8dfa 100644 --- a/sylvia-derive/src/parser/attributes/messages.rs +++ b/sylvia-derive/src/parser/attributes/messages.rs @@ -105,7 +105,7 @@ impl Parse for ContractMessageAttr { if !input.is_empty() { emit_error!(input.span(), "Unexpected tokens inside `sv::messages` attribtue."; - note = "Maximal supported form of attribute: `#[sv::messages(interface::path as InterfaceName: custom(msg, query))]`." + note = "Maximal supported form of attribute: `#[sv::messages(interface::path as InterfaceName: custom(msg, query))]`." ) } Ok(Self { diff --git a/sylvia-derive/src/querier.rs b/sylvia-derive/src/querier.rs index 0aae9f25..61d24c5a 100644 --- a/sylvia-derive/src/querier.rs +++ b/sylvia-derive/src/querier.rs @@ -145,7 +145,7 @@ impl<'a> ContractQuerier<'a> { #(#methods_declaration)* } - impl <'a, C: #sylvia ::cw_std::CustomQuery, #(#generics,)*> Querier #bracketed_generics for #sylvia ::types::BoundQuerier<'a, C, #contract_name > #where_clause { + impl <'sv_querier_lifetime, #(#generics,)* C: #sylvia ::cw_std::CustomQuery> Querier #bracketed_generics for #sylvia ::types::BoundQuerier<'sv_querier_lifetime, C, #contract_name > #where_clause { #(#types_implementation)* #(#methods_impl)* diff --git a/sylvia-derive/src/utils.rs b/sylvia-derive/src/utils.rs index 9be66310..c15b9a29 100644 --- a/sylvia-derive/src/utils.rs +++ b/sylvia-derive/src/utils.rs @@ -5,8 +5,8 @@ use quote::{quote, ToTokens}; use syn::spanned::Spanned; use syn::visit::Visit; use syn::{ - parse_quote, FnArg, GenericArgument, GenericParam, Ident, Path, PathArguments, ReturnType, - Signature, Type, WhereClause, WherePredicate, + parse_quote, FnArg, GenericArgument, Ident, Path, PathArguments, ReturnType, Signature, Type, + WhereClause, WherePredicate, }; use crate::check_generics::{CheckGenerics, GetPath}; @@ -36,29 +36,6 @@ pub fn filter_wheres<'a, Generic: GetPath + PartialEq>( .unwrap_or_default() } -/// Filters generic arguments, which are a concrete types, -/// from the generic parameters -/// -/// f.e. -/// impl MyTrait for MyContract -/// -/// where generic parameters are `[A, B, C]` and generic arguments are `[A, B, D]` -/// should return us the `[A, B]`. -pub fn filter_generics<'a>( - generic_params: &'a [&'a GenericParam], - generic_args: &'a [&'a GenericArgument], -) -> Vec<&'a GenericParam> { - generic_params - .iter() - .filter(|param| { - generic_args - .iter() - .any(|arg| param.get_path() == arg.get_path()) - }) - .copied() - .collect() -} - pub fn process_fields<'s, Generic>( sig: &'s Signature, generics_checker: &mut CheckGenerics, diff --git a/sylvia/tests/api.rs b/sylvia/tests/api.rs index e742d439..ba2b3ebe 100644 --- a/sylvia/tests/api.rs +++ b/sylvia/tests/api.rs @@ -89,7 +89,7 @@ mod tests { SvCustomMsg ); - let _: crate::sv::ContractExecMsg = = = = ::store_code(&app); + let code_id = sv::mt::CodeId::, _>::store_code(&app); let _: sylvia::multitest::Proxy<_, SomeContract> = code_id .instantiate(Empty {}) @@ -48,7 +48,7 @@ fn instantiate_with_salt() { fn code_info() { let app = App::default(); - let code_id = sv::mt::CodeId::::store_code(&app); + let code_id = sv::mt::CodeId::, _>::store_code(&app); let _: CodeInfoResponse = code_id.code_info().unwrap(); let _: CodeInfoResponse = app.code_info(code_id.code_id()).unwrap(); diff --git a/sylvia/tests/querier.rs b/sylvia/tests/querier.rs index 917ad90f..fe39632d 100644 --- a/sylvia/tests/querier.rs +++ b/sylvia/tests/querier.rs @@ -95,7 +95,7 @@ pub struct CounterContract<'a> { #[contract] #[sv::messages(counter)] -impl CounterContract<'_> { +impl<'asdf> CounterContract<'asdf> { #[allow(clippy::new_without_default)] pub fn new() -> Self { Self { diff --git a/sylvia/tests/ui/attributes/messages/unexpected_token.stderr b/sylvia/tests/ui/attributes/messages/unexpected_token.stderr index fada5852..6e1bcc93 100644 --- a/sylvia/tests/ui/attributes/messages/unexpected_token.stderr +++ b/sylvia/tests/ui/attributes/messages/unexpected_token.stderr @@ -1,6 +1,6 @@ error: Unexpected tokens inside `sv::messages` attribtue. - = note: Maximal supported form of attribute: `#[sv::messages(interface::path as InterfaceName: custom(msg, query))]`. + = note: Maximal supported form of attribute: `#[sv::messages(interface::path as InterfaceName: custom(msg, query))]`. --> tests/ui/attributes/messages/unexpected_token.rs:24:25 | From dc8747a3438617aa16646d8b29f8bc55568f260c Mon Sep 17 00:00:00 2001 From: Tomasz Kulik Date: Tue, 23 Apr 2024 20:20:53 +0200 Subject: [PATCH 2/3] chore: Update after review --- sylvia-derive/src/message.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs index 3100e09e..365f1538 100644 --- a/sylvia-derive/src/message.rs +++ b/sylvia-derive/src/message.rs @@ -850,10 +850,7 @@ impl<'a> GlueMessage<'a> { let generics: Vec<_> = source.generics.params.iter().collect(); let full_where_clause = &source.generics.where_clause; - let bracketed_wrapper_generics = match generics.is_empty() { - true => quote! {}, - false => quote! { < #(#generics,)* > }, - }; + let bracketed_wrapper_generics = emit_bracketed_generics(&generics); let contract_enum_name = msg_ty.emit_msg_wrapper_name(); let enum_accessor = msg_ty.as_accessor_name(); @@ -941,9 +938,9 @@ impl<'a> GlueMessage<'a> { fn json_schema( gen: &mut #sylvia ::schemars::gen::SchemaGenerator, ) -> #sylvia ::schemars::schema::Schema { - schemars::schema::Schema::Object(schemars::schema::SchemaObject { + #sylvia ::schemars::schema::Schema::Object( #sylvia ::schemars::schema::SchemaObject { subschemas: Some( - Box::new(schemars::schema::SubschemaValidation { + Box::new( #sylvia ::schemars::schema::SubschemaValidation { any_of: Some( <[_]>::into_vec( Box::new([ @@ -980,9 +977,9 @@ impl<'a> GlueMessage<'a> { #response_schemas - impl<'sv_deserializde_lifetime, #(#generics,)* > serde::Deserialize<'sv_deserializde_lifetime> for #contract_enum_name #bracketed_wrapper_generics #full_where_clause { + impl<'sv_de, #(#generics,)* > serde::Deserialize<'sv_de> for #contract_enum_name #bracketed_wrapper_generics #full_where_clause { fn deserialize(deserializer: D) -> Result - where D: serde::Deserializer<'sv_deserializde_lifetime>, + where D: serde::Deserializer<'sv_de>, { use serde::de::Error; From 51653016cf3b490bb9c881283318c268e2f1be0a Mon Sep 17 00:00:00 2001 From: Tomasz Kulik Date: Tue, 7 May 2024 10:40:33 +0200 Subject: [PATCH 3/3] docs: Update MIGRATING.md --- MIGRATING.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/MIGRATING.md b/MIGRATING.md index 6099eda4..556b1b67 100644 --- a/MIGRATING.md +++ b/MIGRATING.md @@ -2,6 +2,53 @@ This guide explains what is needed to upgrade contracts when migrating over major releases of `sylvia`. Note that you can also view the [complete CHANGELOG](https://github.com/CosmWasm/sylvia/blob/main/CHANGELOG.md) to understand the differences. + +## 1.0.2 -> + + +### Generics in `sv::messages` not required +```diff +-#[contract] +-#[sv::messages(generic as Generic +-impl Contract {} ++#[contract] ++#[sv::messages(generic as Generic)] ++impl Contract {} +``` + +This change is optional, since the generics are still accepted by the parser. Though they are +ignored in the further process. + + +### CodeId generic over the Contract type +```diff +-let code_id: CodeId< +- SvCustomMsg, +- SvCustomMsg, +- _, +-> = CodeId::store_code(&app); ++let code_id: CodeId< ++ GenericContract< ++ SvCustomMsg, ++ SvCustomMsg, ++ >, ++ _, ++> = CodeId::store_code(&app); +``` + +### Lifetime ellision in a contract's impl block not supported +```diff +-#[contract] +-impl Cw1SubkeysContract<'_> { +- // [...] +-} ++#[contract] ++impl<'a> Cw1SubkeysContract<'a> { ++ // [...] ++} +``` + + ## 0.9.3 -> 0.10.0 ## Multitest proxy