Closed jawoznia closed 6 months ago
Found while implementing #263
Ok, I was thinking through that slowly. The question here is - why the querier is not generic over all the generic types? The answer is - because some of the types are not used at all, which causes compilation error. If the querier trait would always be generic over exactly the same types the contract is, there would not really be a problem. So what is the reason we dont use some generics? The reason is - because querier is not actually using all the generics. It uses only those used by query functions, but if you have some generics used only by execs or sudos, you do not need those for queriers. I was looking at the solutions, and then I got hit by one fact - how many implementations of this querier can exist on the single contract type (monomorphized one)? Obviously - exactly one. It is due to a fact, that we would have couple functions for the same query message. This is invalid. We do that for traits for couple reasons, and none of the reasons are good I think. You can never have a contract properly implementing multiple interfaces. Contract can be generic, for extensibility purposes, but for interfaces we would always need to use associated types. Ill explain it more on call I think
Closed, generics not to be supported: #303
Concrete uniqueness
Contract
call on interface implementation generates implementation ofinterface::Querier
oncontract::BoundQuerier
. This requires us to determine which generics should be forwarded to theinterface::Querier
. In case of generic values it's easy as we only have to determine which ones are used in thequery
methods. We are only interested in unique types and can use the same logic frominterface
macro.Problem appears when we try to use concrete types. If for below interface messages with four generic types
[QueryT1, QueryT2, QueryT3, RetT]
we will use concrete types as below
Sylvia
will think that there are only two generic types and will try to forward them to theQuerier
.If we would use the same path here f.e.
SvCustomMsg
in place ofsylvia::types::SvCustomMsg
only a single type would be forwarded as generic.This provides us an workaround allowing user to work with aliases/different versions of paths, but it's a bad solution and we should find a better one.
Solution here might be to drop
unique
filtering for generic arguments, but it will cause more troubles as in above example we would jump from two generics to six (while expecting four).Another way would be to provide a new attribute here, but it would only serve as a way to provide generics defined for a trait and I don't see as a much better solution then using type aliases.
We also can't distribute proper generics to
Querier
in theInterfaceApi
as this is a trait.At this moment I don't see a proper way to fix it and we most likely will have to fix it after the
1.0.0
release.