You could make it available as a value, but it couldn't be a constant value, nor accessible through on the type. For example, consider the following valid code:
(Less trivial but equally troublesome cases would be where foo takes two or more&Ts instead of zero, and does an actual const {...} computation using the associated constant — then there is no single value that matches.)
There is no value for foo::<dyn MaybeSigned>() to return. Yet according to the bounds, dyn MaybeSigned meets the requirements of T. So, we'd either need some new kind of trait bound, or dyn MaybeSigned would exist but not actually meet the trait bound (which is somewhat useful, but weird and would itself need new rules).
hmm, so it seems like it's mainly a syntactic issue, not a semantic one?
perhaps we could implement a dyn const construct, in generic contexts, these constants would be accessed like fields: x.IS_SIGNED.
for all instantiations that do not use dyn, this would be exactly equivalent to an associated constant lookup. however, in the case of dyn Trait, it would simply look up the value in the vtable.
this should be a bit more performant than using methods that return fixed values, since i is just an offset read instead of a function call.
This could work if associated consts became named parameters to the dyn Trait ala associated types. In the meanwhile you can approximate it with a type-per-const-value and a shadow trait.
I don't think "it's in the vtable" is enough with consts in the type system. A &dyn Trait value can change between vtables without changing type.
That is certainly interesting. I suppose what's occurring is that essentially the compiler provides something equivalent to
impl Weird for dyn Weird + '_
where
BoundGuard<Self>: BoundTrait,
{
}
and permits dyn Weird to be used since Weird is allegedly dyn-safe, but the additional bound means that dyn Weird: Weird never holds. And this behaves differently from where Self: SuperTrait because bounds directly on Self are treated differently due to being automatically elaborated.
I wonder if you could abuse this and write a bound on TIdentity<Self>::Output: SuperTrait to get an effective supertrait bound but without supertrait bound elaboration or upcasting.
You could call this a nit, but parts of the vtable are accessed. (The drop pointer and the supertrait methods, in the playground.) ((Probably also the size and maybe alignment too, if I had boxed it.))
(Edit: eh, you need to box it for the drop to be accessed via vtable too, but you get the point.)
As a slight aside, I wish there was a convenient way to provide a default method body that assumes Self: Sized but still allows the method to be dispatched via vtable. That would allow a solution like this:
i think this would work fine with dyn const, since the semantics would be identical to that of a struct field. it couldn't actually be used in constant expressions in a generic context.
Rust doesn't have "trait fields" either, though it has been proposed. But even if it did, you can use an associated const without having a value of the type around.
The thing I'm proposing, dyn const, would restrict that, they would only be accessible from a value that implements that trait, not from the type itself.