News for hackers. Stuff that matters.
Re:Beginner's guide to error handling in Rust by Someone on Sunday July 10, 2022 @01:25PM (#32046729)
FTA: let result = reqwest::blocking::get(url);

  let response = match result {
    Ok(res) => res,
    Err(err) => return Err(err),
  };
Is that truly idiomatic? I would think the Err(err) => return Err(err) line needlessly constructs a copy of result. Or is that necessary because of the borrow checker?

(Also, for those unfamiliar with it: reqwest is not a typo. See https://github.com/seanmonstar/reqwest)

Re:Beginner's guide to error handling in Rust by Ambroisie on Sunday July 10, 2022 @01:55PM (#32047050)
As pointed out, the idiomatic way to do this is to use the try operator (`?`).

But to answer your question about copies : Rust is a move-only language, copies are actually called `.clone()`, except for a few types which are cheap enough to copy that they implement the `Copy` trait.

So in the code you quoted, the match is done on the value of `result` (notice that there is not borrowing/`&` operator). The match arm `Err(err)` moves `err` out of `result` and returns it. Obviously, the compiler will optimize away all those moves, it's as if they did not exist.

Re:Beginner's guide to error handling in Rust by littlestymaar on Sunday July 10, 2022 @04:07PM (#32048452)
> But to answer your question about copies : Rust is a move-only language, copies are actually called `.clone()`, except for a few types which are cheap enough to copy that they implement the `Copy` trait.

This is almost true, but not exact. Copy is for everything where cloning is just memcopy, that doesn't means it's necessarily cheap ([42;4_000_000] implements Copy, yet it's not cheap to copy at all…).

And moving things sometimes (but not always) means the thing is getting memcopied (or it could use a pointer, depending on the optimizer's m̶o̶o̶d̶ euristics)

Re:Beginner's guide to error handling in Rust by throwaway234232 on Sunday July 10, 2022 @02:00PM (#32047122)
> I would think the Err(err) => return Err(err) line needlessly constructs a copy of result

It sounds like this is coming from a C++ bias? So please forgive me if this is wrong.

Rust, in my experience, favors move semantics first, then copy semantics after.

I know in C++, we had implicit copy constructors, with move semantics after with rvalue references, where you need to use `std::move` in a lot of cases.

So what helps, in my opinion, is to think of Rust as using `std::move` as a default.

Re:Beginner's guide to error handling in Rust by saghm on Sunday July 10, 2022 @03:07PM (#32047848)
> So what helps, in my opinion, is to think of Rust as using `std::move` as a default

Even more than that, with the exception of types that implement `Copy` (e.g. bools, integers, etc.), using after a move won't just silently degrade to a copy, but will cause a compiler error. Copying is required to be explicit for all but the most trivial types.

Re:Beginner's guide to error handling in Rust by jcranmer on Sunday July 10, 2022 @02:25PM (#32047397)
> I would think the Err(err) => return Err(err) line needlessly constructs a copy of result.

You would think wrong. In Rust, everything is move by default. To create a copy, you need to explicitly call .clone() on an object (assuming it implements Clone, of course), or you can implement Copy for the type, which will cause .clone() to be called instead of moving the value.

(I'm not actually sure where the compiler will generate calls to clone() on Copy types in favor of moving. In practice, you're not going to implement Copy for a type that isn't trivially copyable anyways [using the C++ definition], so any optimizer would easily be able to elide any excessive copy operations.)

Re:Beginner's guide to error handling in Rust by joaonmatos on Sunday July 10, 2022 @04:10PM (#32048482)
Copy types must be trivially copiable bitwise (the clone implementation is returning the deref of the cloned type), so a copy is a move except for the fact that the previous reference is not invalidated.

The docs for the trait (core::marker::Copy) are pretty good

Re:Beginner's guide to error handling in Rust by masklinn on Sunday July 10, 2022 @02:24PM (#32047396)
> Or is that necessary because of the borrow checker?

It’s not because of the borrow checker, it’s because Rust defaults to (destructive) moves, and implicit copies can only be trivial.

Any non-trivial copy has to go through an explicit clone() instead.

Re:Beginner's guide to error handling in Rust by richardwhiuk on Sunday July 10, 2022 @01:38PM (#32046867)
The idiomatic way to write this would be:

let response = reqwest::blocking::get(url)?;

In the way written there's no additional copy.