I have two problems with this design. The ad-hoc attribute should be replaced by a reasonable trait. The best we can get without a coherence disaster is
impl FloatLit for Meter {
type SUFFIX = "m";
const fn float_lit(lit: f?) -> Self { .. }
}
What f?
is is my second problem. I detest the fact that C++ uses a builtin, fixed-width type, which is nonsense when you realize your literal constructor should be const
anyways. I've actually already proposed the necessary types for this, [Pre-RFC] Integer/Float literal types, for this exact purpose.
The other problem is that that you'll get a coherence disaster anyways if several such types make their way into scope. An alternative definition which sidesteps this is
enum m {}
impl FloatLit for m {
type Output = Meter;
// ..
}
This ensures that literals have an identifier name and have a path; their path is that of the type that provides the name. Plus, you get to do silly things like
impl FloatInt for Meter {
type Output = Self;
// ..
}
Now, to import the literal you simply import my_units::meter::m
, and name collision will take care of the rest. This even interacts nicely with the vanilla literals!
Though this seems like a bit of a syntactical foot gun, since people will expect to implement FloatInt
on the output type rather than the symbol type.
Finally, I think we should avoid table the brackets syntax for now, since it goes quite afield; far more than the proposal should be allowing at this point in time.
Can both features just exist alongside each other? I think most uses of a custom literal are better suited as const fn
s, and I'd like to have to call the format prefix as "..."!fmt
or something.