Closed taitruong closed 5 months ago
I also tried removing Generics in interface by using type aliases:
#[interface]
pub trait MyInterface {
type Error: From<StdError>;
type Msg: Serialize;
#[msg(exec)]
fn foo(&self, ctx: ExecCtx, msg: Self::Msg) -> StdResult<Response> {
}
But I get this error:
no variant named
Msg
found for enumMyInterfaceExecMsg
Seems like Self
cant be used in param?
Trying sylvia v0.7.1, seems like generics aren't supported at various places? Like here:
pub struct MyContract<'a, T> {
pub(crate) msgs: Map<'a, String, T>,
}
#[entry_points]
#[contract]
impl MyContract<'static, ExecMsg> {
pub const fn new() -> Self {
Self {
msgs: Map::new("msgs"),
}
}
#[msg(instantiate)]
pub fn instantiate(&self, _ctx: InstantiateCtx) -> StdResult<Response> {
Ok(Response::default())
}
}
Error:
error[E0107]: missing generics for struct contract::MyContract
--> contracts/my-contract/src/contract.rs:15:615 impl MyContract<'static, ExecMsg> { ^^^^^^^^^^ expected 1 generic argument
note: struct defined here, with 1 generic parameter: T
--> contracts/my-contract/src/contract.rs:8:128 pub struct MyContract<'a, T> { ^^^^^^^^^^ - help: add missing generic argument 15 impl MyContract <'static, ExecMsg> { +++
Hi @taitruong could you share your code?
Also did it work for you in previous versions of sylvia
and failed while migrating to the 0.7.1
?
@taitruong generic traits should be valid interfaces, but they are tricky to handle. Even contracts should be generic, but at the end of the day, for the contract, there has to be a specific set of types that are passed as generic parameters so the final messages are well-defined.
I don't remember the implementation, but what I see in your question is:
#[messages(crate::my_interface as MyInterface)]
This sounds off to me - I don't see any generic argument list, so when contract messages are generated, Sylvia doesn't know what types should be used instead of generics. This is not well documented in Sylvia, but looking at the code, it should look like this:
#[messages(crate::my_interface: exec<T1, T2>, query<T3, T4> as MyInterface)]
The idea is that when Sylvia generates enum messages, it would include generics from the interface used by those messages, so as an example:
#[interface]
trait MyInterface<T: Serialize + Deserialize, U: Serialize + Deserialize, V: Serialize + Deserialize> {
#[msg(exec)]
fn my_exec(ctx: ExecCtx, t: T, v: V) -> StdResult<Response>;
#[msg(query)]
fn my_query(ctx: QueryCtx, u: U, v: V) -> StdResult<QueryResp>;
}
Should generate messages for this interface equivalent to:
enum ExecMsg<T: Serialize + Deserialize, V: Serialize + Deserialize> {
MyExec { t: T, v: V }
}
enum QueryMsg<U: Serialize + Deserialize, V: Serialize + Deserialize> {
MyQuery { u: U, v: V }
}
Note that only generics. which are used by enum are included in the message - this is to avoid errors with unused generics. The other option would be to add the additional variant like __Phantom(PhantomData<(T, U, V)>)
just to use the generics - it might be a better approach to make usage cleaner (used don't need to know which generics are used where it makes API more stable) but honestly - we didn't put too much thought into that yet, as there we more urgent needs, so API here might change.
Anyway - for the contract implementation, the #[contract]
macro has to know precisely how to monomorphise generics in the interface, and that is why there are exec<...>
and query<...>
additions to the #[message]
attribute which would be used why naming the exec/query message types for the contract which are missing in your example.
The best would be if you provided us with minimal failing examples - it would help us verify if you met the case we missed. Right now, developing Sylvia, we prioritize cases used by actual developers, so if you have this issue, which we didn't need before, we can focus on improving this particular thing. Or if there is a case that all works fine, but documentation is not good enough, we are happy to improve it.
Hi, I've create a simple example here: https://github.com/taitruong/sylvia-generics-example
First commit is without generics and it works. Second commit trying to add a simple generic - breaking code.
So cool seeing Sylvia will support generics (#223). Once this is complete, I'll be happy to extensively test and use it. Imo this would be the missing part for using Sylvia 100% in production.
@taitruong sylvia 0.9.0
released featuring support for generics.
Please visit MIGRATING.md
as we changed the way we generate the code.
Everything sylvia
generates is put in the sv
module.
The article about assoc types vs. generics in traits can be found here: https://medium.com/confio/generics-vs-associated-types-in-sylvia-traits-design-689a16e09e56
I have something like this:
But when adding this to contract, I get this error:
Contract: