4 ms·
> I can't find an explanation in the Rust documentation but I expect the reason is that someone could implement another trait that provides .into_iter() on what
by junon 1y ago
> I can't find an explanation in the Rust documentation but I expect the reason is that someone could implement another trait that provides .into_iter() on whatever the x is in for y in x, thus resulting in a compiler error because there would be two candidate implementations.
Because nothing in Rust is identifier-based. Unlike python, all syntax magic (even the ? operator) relies on traits defined by `core`.
for x in y {
desugars to
let mut iter = IntoIterator::into_iter(y);
while let Some(x) = y.next() {
and
x?
desugars to
match x {
Ok(x) => x,
Err(e) => {
return Err(From::from(e));
}
}
and
x + y
desugars to
core::ops::Add::add(x, y)
etc.
All of those traits are expected to live explicitly in the core crate at well known paths. Otherwise you'd be writing methods with absolutely no idea how the language would interact with it. And if you had a Set type implement `add`, it'd have to accept exactly 2 arguments to be compatible with the language's `add` or something equally as unergonomic.
It's traits all the way down! There'd be no explanation needed because it'd be antithetical and contradictory to traits to begin with. Once one understands how traits are intended to be used, the explanation for why there aren't identifier based resolution semantics becomes obvious.
- saagarjha 1y agoSwift has overloading and its own version of traits. None of what you said is actually required.
- norman784 1y agoInteresting, I didn't knew about the for loop and the ops desugars to something in core, I though it was deal in the compiler, but makes sense since you can implement the ops::* traits for your custom types.
- writebetterc 1y agoIt's a bit annoying that there is a standard desugaring of all of this, but there's no actual way of implementing this sugaring yourself. I guess you could have a token macro (or whatever they're called) at the top scope and do it yourself? Anyway, my conclusion is that in order to learn Rust you can't use any syntactic sugar the language provides, those are 'expert features'. There's no way I'd be able to figure out why this happens. Do rust-analyzer provide a way of desugaring these constructs?
- steveklabnik 1y ago> there's no actual way of implementing this sugaring yourself. This is the common case in languages with sugar. Heck, you could consider all of Rust sugar for MIR... > There's no way I'd be able to figure out why this happens. You don't generally need to, but most of this is documented: https://doc.rust-lang.org/stable/std/iter/index.html#for-loops-and-intoiterator https://doc.rust-lang.org/stable/std/iter/index.html#for-loo... https://doc.rust-lang.org/stable/std/ops/trait.Add.html#implementing-add-with-generics https://doc.rust-lang.org/stable/std/ops/trait.Add.html#impl... ?'s desugaring isn't documented because the desugaring is subject to change.
- tialaramex 1y agoSeveral of those de-sugarings are wrong. The book explains how Rust's `for` is actually de-sugared, and that ? is a Try operator, so unsurprisingly it de-sugars to a use of Try::branch and that gets you a ControlFlow which is then pattern matched. Also, they don't need to live "at well known paths". Instead they're marked as "langitems", with the magic attribute lang: #[lang = "add_assign"] // Signifies that this trait is what the compiler wanted to make the += operator work in the language.
- dietr1ch 1y agoIs there a way of looking at desugared code? Maybe things won't change that much, but I feel that documentation on how desugaring is supposed to be done will be increasingly wrong as things change. Maybe it's stable enough, but It'd be cool to have a nice way of verifying things are happening the way they are supposed to.
- junon 1y agoYes, while you're correct, my comment was more or less illustrative. Apologies if that wasn't clear. Explaining the nuance of langitems wasn't really the point I was trying to make. Also AFAIR Try traits are relatively new, and are still unstable. Last I checked it was indeed a desugar to either From or Into (pretty sure it was From).
- steveklabnik 1y agoOther than what other people said, the question is to why that desugaring is chosen, not that it's because of a specific one. That is, why let mut iter = IntoIterator::into_iter(y); instead of let mut iter = y.into_iter(); That could have been done, but it wasn't. > Otherwise you'd be writing methods with absolutely no idea how the language would interact with it. Right, this is what's guessed, because it makes the most sense.