There exists a possible solution for this. Unimock selects a responder type based on the return signature. The new algorithm would select Generic<Result<Owned<i32>, Owned<i32>>> naively (for Result<i32, i32>. But that's just the semantics of the Generic responder: its inner types also need to implement Respond (so they can actually be nested, which is the whole point).
But there could also be a LeafGeneric responder. The structure -> SomethingGeneric<NonGenericType1, NonGenericType2> could select that instead. The semantics would be that the contained type is not interpreted as a responder, but as the direct response type.
Then the super-generic responder would only be chosen at the outer level in this scenario: -> SomethingGeneric<SomethingElseGeneric<NonGeneric>>.
status
This is now implemented and it works!
The "type hack" is also working. I've chosen some other names for the types, all of the output/responder code has been completely rewritten with a new fundamental architecture and foundational traits.
The core trait is output::Kind, a kind-of higher-kinded descriptor for output categories. The MockFn how has an OutputKind: Kind associated type.
Output kinds have to specify two associated types: Return and Respond types. The former is for storing a value in unimock and the latter is for responding through ApplyFn. The latter represents opt-out of Send + Sync.
Then there are the kinds themselves. The type-hack is about type kinds with generic parameters. A type signature with Option<T> has the Shallow kind, where the T itself is not a kind. A type signature with Option<Option<T>> has a Deep kind, applied in the following way: Deep<Option<Shallow<Option<T>>>>. So the innermost generic type has no restrictions on type aliasing (type MyResult<T> = Result<T, MyError>;), but the outermost has.
fixes #29
It's a major redesign of the responder/output-related traits.
~It (currently) comes with the following caveat:~ (edit: this is fixed for one generics-level)
There exists a possible solution for this. Unimock selects a responder type based on the return signature. The new algorithm would select
Generic<Result<Owned<i32>, Owned<i32>>>
naively (forResult<i32, i32>
. But that's just the semantics of theGeneric
responder: its inner types also need to implementRespond
(so they can actually be nested, which is the whole point).But there could also be a
LeafGeneric
responder. The structure-> SomethingGeneric<NonGenericType1, NonGenericType2>
could select that instead. The semantics would be that the contained type is not interpreted as a responder, but as the direct response type.Then the super-generic responder would only be chosen at the outer level in this scenario:
-> SomethingGeneric<SomethingElseGeneric<NonGeneric>>
.status
This is now implemented and it works!
The "type hack" is also working. I've chosen some other names for the types, all of the output/responder code has been completely rewritten with a new fundamental architecture and foundational traits.
The core trait is
output::Kind
, a kind-of higher-kinded descriptor for output categories. TheMockFn
how has anOutputKind: Kind
associated type.Output kinds have to specify two associated types:
Return
andRespond
types. The former is for storing a value in unimock and the latter is for responding throughApplyFn
. The latter represents opt-out ofSend + Sync
.Then there are the kinds themselves. The type-hack is about type kinds with generic parameters. A type signature with
Option<T>
has theShallow
kind, where theT
itself is not a kind. A type signature withOption<Option<T>>
has aDeep
kind, applied in the following way:Deep<Option<Shallow<Option<T>>>>
. So the innermost generic type has no restrictions on type aliasing (type MyResult<T> = Result<T, MyError>;
), but the outermost has.