I'm hoping that we provide ergonomic alternatives for all the individual use cases. The brevity of `as` is a major reason we haven't removed it yet.
We have `.into()` for lossless conversions like u32 to u64.
We need to fix the fact that `usize` doesn't participate in lossless conversions (e.g. even on 64-bit you can't convert `usize` to `u64` via `.into()`).
We need to fix the fact that you can't write `.into::<u64>()` to disambiguate types.
And I'm hoping we add `.trunc()` for lossy conversion.
And eventually, after we provide alternatives for all of those and some others, we've talked about changing `as` to be shorthand for `.into()`.
A method call like `.trunc()` is still going to be abysmally less ergonomic than `as`. It relies on inference or turbofish to pick a type, and it has all the syntactic noise of a function call on top of that.
Not to mention this sort of proliferation of micro-calls for what should be <= 1 instruction has a cost to debug performance and/or compile times (though this is something that should be fixed regardless).
> A method call like `.trunc()` is still going to be abysmally less ergonomic than `as`. It relies on inference or turbofish to pick a type, and it has all the syntactic noise of a function call on top of that.
If `as` gets repurposed for safe conversions (e.g. u32 to u64), there's some merit to the more hazardous conversions being slightly noisier. I'm all for them being no noisier than necessary, but even in my most conversion-heavy code (which has to convert regularly between usize and u64), I'd be fine writing `.into()` or `.trunc()` everywhere, as long as I don't have to write `.try_into()?` or similar.
> Not to mention this sort of proliferation of micro-calls for what should be <= 1 instruction has a cost to debug performance and/or compile times (though this is something that should be fixed regardless).
I fully expect that such methods will be inlined, likely even in debug mode (e.g. `#[inline(always)]`), and compile down to the same minimal instructions.
Yes, this is specifically what I'm disagreeing with.
> I fully expect that such methods will be inlined, likely even in debug mode (e.g. `#[inline(always)]`), and compile down to the same minimal instructions.
Many things in the language theoretically go through a trait as well, except that we have special cases in the compiler to handle those traits more efficiently. If this were a performance issue, there's no reason we couldn't do the same for `.trunc()` or `.into()`.
The compiler doesn't have to implement a call as a call; having "magic functions" calls to which are special-cased by the code generator is an old and time-honored tradition.
> We need to fix the fact that you can't write `.into::<u64>()` to disambiguate types.
Yes, that would be great. In the meantime, if you can't wait but want something like this, you can DIY it via an extension trait.
It's very easy to write it yourself, this is all it takes:
pub trait To {
fn to<T>(self) -> T where Self: Into<T> {
<Self as Into<T>>::into(self)
}
}
Now whenever this trait is in scope, you get to simply do .to::<u64>() and it does exactly what Into does. If you prefer adding a tiny dependency over copy-pasting code, I've also published a crate that provides this: https://crates.io/crates/to_method
> We need to fix the fact that you can't write `.into::<u64>()` to disambiguate types.
This confused me too at first. You have to do `u64::from(_)` right? It makes sense in a certain way, similar to how you have to do `Vec::<u64>::new()` rather than `Vec::new::<u64>()`, but it is definitely more annoying for `into`.
> And eventually, after we provide alternatives for all of those and some others, we've talked about changing `as` to be shorthand for `.into()`.
Whoa, that could be awesome. It's always felt a bit unfortunate that you can't write `val.into::<SomeExplicitType>::()`—because the type parameter is on the trait, not the method. Of course, `SomeExplicitType::from` works, but sometimes that slightly upsets the flow of code.
Having just `val as SomeExplicitType` might be really nice for that common case. I do wonder if it'd feel too magic… but I'm optimistic to see what the lang team comes up with.
We have `.into()` for lossless conversions like u32 to u64.
We need to fix the fact that `usize` doesn't participate in lossless conversions (e.g. even on 64-bit you can't convert `usize` to `u64` via `.into()`).
We need to fix the fact that you can't write `.into::<u64>()` to disambiguate types.
And I'm hoping we add `.trunc()` for lossy conversion.
And eventually, after we provide alternatives for all of those and some others, we've talked about changing `as` to be shorthand for `.into()`.