Wouldn’t some kind of “untyped number” (<- const only) type be a alternative solution?
e.g. const FOO: UntypedNumber = 123456;
Where the constant FOO is interpreted dependent on it’s context. And a error(warning?) is thrown if the given typed number does not fit into the given numeric type.
Wrt. to backward compatibility and name collision UntypedNumber would be type in std marked with #[lang_item="untyped_number"] (also it should be zero sized with a single private zero sized field to prevent usage elsewhere, maybe also warning if used in generics etc.).
Not that I intentionally used “number” not integer, there is no reason to limit this functionally to integers e.g. let x: f32 = FOO; should then be equivilant to let x: f32 = 123456f32 and FOO could aso be const FOO: UntypedNumber = 12.4; making it usable with f32/f64 and possible other native number types if they are added to rust.
Additionally std might provide a simple (const) fn to hint the type (as is not enough as as would also be used for casting. E.g. let x = FOO as u8; is ambiguous between Error 1234 does not fit into u8 and 1234<?> as u8, defaulting to the former one would be unnecessary error prone. Basically a (#[inline(always)] const) fn typed<T>(x: T) -> T { x } (not the ( .. ) is because I’m not sure about #[inline(always)] and const is not stable, also the combination of both makes little sense
)
TL;DR:
in (e.g.) std/const/lib.rs
#[lang_item = "untyped_number" ]
pub struct UntypedNumber {
_no_construction: ()
}
pub const fn typed<T>(x: T) { x }
in example
use std::const::{UntypedNumber, typed};
const FOO: UntypedNumber = 1234;
const BAR: UntypedNumber =12.4; //ok, through works only with f32/f64 etc.
fn main() {
// for simplicity I will only use `let var =` and `let var: type =` state ments
// for all cases where the type of `var` is unknown and know through other
// means respectively
let a: u32 = FOO; //FOO equiv. 1234u32
let b: f32 = FOO; //FOO equiv. 1234f32
let c = typed::<f32>(FOO); //equiv. to `typed::<f32>(1234f32)`
let a = FOO; //error can't resolve type
let a: u8 = FOO; //error u8 can only contain numbers in range [0;255] got 1234
let a = FOO as u8; //error can't resolve type, abiguity between typing and casting
let a = FOO as u32; //aslo? error can't resolve type, abiguity between typing and casting or not??
let a = typed::<u32>(FOO) as u8; //equiv. to `1234u32 as u8`
}
not that typed is no “magic” at all just a (additional) way to hint the type to the compiler (it’s not necessary needed, if it is wanted I do not know).
Note that currently typed::<f32>(12) does not compile as 12 is a {integer}. Through it would be fine with FOO as, given the type hint of T=f32, FOO would be equivalent to “1234 f32”, and not just “1234”.
Question 1: is there any non number usage for “untyped” constants
Question 2: is there any case where a typed::<...>(FOO) should not error if the number does not fit into the type (e.g. warn instead and use as ...). Also wrt. float
we would have to take the closest actual representable number (else 0.1 won’t work),
but when(if at all) do/should we error/warn that f32’s precision is to low for given number?
EDIT:
I just noticed that I only read from @retep998 post (nr. 14, 6.3.2017) onward and
a similar Idea had already been mentioned.