Hello, in the library I'm writing, basically all the functions and types I use have the same set of generics (both const and types). I wanted to put everything into a bag (let's call it Module) so that it's easier to read both in the library code and user-side. Something like:
This, and bound checking (index > Self::ROW), are basically the only usage I will have of this feature.
I already use a nightly compiler for this lib (to get the generators), so I don't mind adding another feature. The question is: is it advanced enough to handle my usecase?
Also, when trying this, I get some weird errors:
error: unconstrained generic constant
--> src/lib.rs:12:10
|
12 | baz: [[bool; M::COL]; M::ROW],
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); M::COL]:`
error: unconstrained generic constant
--> src/lib.rs:12:10
|
12 | baz: [[bool; M::COL]; M::ROW],
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); M::ROW]:`
I'm not sure about what that means.
Edit: it looks like I can get rid of the errors with a where [[bool; M::COL]; M::ROW]: Sized bound (taken from this SO entry), but the main question remains.
BTW, I wonder if I can put this bound on the trait directly, somehow.
I would say it's highly unstable, but for experimenting simple cases like this I guess it's fine. You still should expect bugs/crashes, and definitely not using this in serious project.
It just means M::COL and M::ROW can be evaluated without a panic. Since it's ok to write something like this:
My project is somewhat serious because I plan to publish it. I guess I'm stuck with my list of generics for now, then.
Your explanation about why I must put any random constraint implying the const generic parameter is really clear, thanks!
It does not make really sense IMHO, since if I attempt to use a panicking const, the code fails to compile anyway.
I wonder if adding this kind of bound is temporary, and if it is not, if I can add a constraint directly into the trait saying that it is forbidden to use something else than an usize.
I have no idea about whether the bound could be omitted, but I guess it's hard to. Omitting the bound kind of making your struct have implicit bound, for example, if you wrote this instead:
baz: [bool; { M::COL * M::ROW }]
Then then bound would have to requirer M::COL * M::ROW evaluates. Of course we can make this a somewhat non-local error that happens after monomorphization. So there's a chance. I don't really know.
I think it's kind of hard to add a constraint like that. Since you can do arbitrary computation with generic_const_exprs, it's hard (read: impossible) to prove it's always well-formed.
Hum, the idea was to shove all the generic parameters into one trait to have a single generic parameter to pass around (to mimic a bit the OCaml module system); so while your workaround is cool, it defeats to purpose of my Module trait.
That's what I meant, that during the monomorphization, the compiler knows which one is well or ill-formed.
Anyway, I understand it's better to not use that in something else than an experiment, and since this lib is to be used on controllers, I better stay away from it.