Hi!
tl;dr: I have two types that are equal according to TypeId
but are not equal according to trait resolution.
It looks like I'm breaking something in the type-system with mutual trait-recursion and the specialization feature.
Lengthy details of what I'm trying to achieve
I'm trying to write a compile-time dictionary/map that can map types to integers. I want to be able to add these, element wise. So Dict(A => 3) + Dict(A => 1, B => 2) = Dict(A => 4, B => 2)
. For that I'm trying to first find the union of all keys: {A, B} and then write a trait/function that can obtain the sum for each key from both dicts to create the final result.
This must be done at compile-time because I want to get compile-time guarantees from it. Specifically I'm looking for something like the uom or dimensioned crate, but with the ability to add quantities/dimensions to a system of quantities without changing all other dimension definitions.
The uom and dimensioned crates realize units using a type a bit like like this:
type Meter = Dimensioned<f64, Length=1, Mass=0, Time=0>;
type Kilogram = Dimensioned<f64, Length=0, Mass=1, Time=0>;
type Time = Dimensioned<f64, Length=0, Mass=0, Time=1>;
type Acceleration = Dimensioned<f64, Length=1, Mass=0, Time=-2>;
When multiplying two numbers you add their dimensions, so acceleration = m/(s^2) = Meter - Time - Time.
I want to achieve the same, but I don't want to fix a specific number of dimensions beforehand, so users can extend the dimensions from outside of the crate, without needing to re-define the entire system of quantities again.
To do that I want to implement essentially a dictionary at a type-system level (with a crappy O(n^2) complexity of adding two dictionaries).
There's two errors:
- from test case 4 where it fails to compute
Test4ListResult
because a trait bound is not satisfied.
In this error it mentions that
the trait bound
<TArr<B, TArrEnd> as RemoveTypeFromList<A>>::Output: Dedup
is not satisfied
However, it does implement Dedup
! The linked playground compiles and runs without errors, which means:
a) Test4IntermediateResult
and Test4IntermediateExpectedResult
are the same type according to TypeId
b) Test4IntermediateExpectedResult
implements Dedup
(where Test4IntermediateResult = <TArr<B, TArrEnd> as RemoveTypeFromList<A>>::Output
, from the error message above).
- the other error is that
Test4IntermediateResult
(which is supposed to be equal toTest4IntermediateExpectedResult
and implementsDedup
) does not implementDedup
I get that the specializations feature is not ready, but is there anything that can be done here?
What's the reason for this mismatch?
Does the rust compiler not fully evaluate the type of Test4IntermediateResult
? Can I tell it to?
Can I achieve my dream of a compile-time dict in a different way?
Thanks for reading, and thanks for any replies and comments in advance!
ambiso
I think I might want something like Zig's comptime in Rust? Having access to, and being able to compute on types in something like a proc-macro.