Live data from Hacker News

Common Rust Lifetime Misconceptions (2020)

github.com

71–80 of 89 posts

Re: Common Rust Lifetime Misconceptions (2020)

#71
post #60

I just clone everywhere and write Rust like a high level language. Then, once I need to optimize more, if I ever do (as Rust is many times faster than other languages even with liberal cloning), then I simply go through and remove the clone where needed.

> as Rust is many times faster than other languages even with liberal cloning Have you really compared? I have. Rust was faster for "small input", but quickly got beaten by Java and other languages I tried because the cost of doing things this way grows exponentially. I suggest you run benchmarks before you make your mind up and start throwing opinions around.

My other languages generally used are Python and TypeScript of which it absolutely is faster. I don't write Java anymore, generally speaking, so it could be faster, but it has its own problems, such as having null pointers and exceptions.

Re: Common Rust Lifetime Misconceptions (2020)

#72

Earlier quoted context omitted.

burntsushi actually regrets making regex replace return a Cow : https://github.com/rust-lang/regex/issues/676#issuecomment-6... . I’m glad it does, and wish it took an impl Into > there, for the reasons discussed in the issue, but burntsushi has a lot more experience of the practical outcomes of this. Just something more to think about.

So from reading those comments, I'd come to the opposite conclusion: Cow is absolutely the right choice and perhaps String should really have been Cow . Insofar as taking an impl into, burntsushi linked to a rust playground demonstrating where that approach falls down. In general (heh) taking arguments , especially options or stringy ones, that are generalized over an into impl is one of those things that seems real…

In my defense, I said I occasionally regret the choice. But in rebuttal, I certainly do not have your confidence that returning Cow is the right choice. Basically, when it comes down to it, I'm not 100% convinced that it pulls its weight. But like I said in the issue, it's decently motivated.

I don't think String could be a Cow. Remember, Cow is actually a Cow, and if you want to borrow a &str from a Cow, the lifetime of that &str is not 'a, but rather, attached to the Cow itself. (This is necessary because the Cow may contain an owned String.) This in turn would effectively kill string slicing.

In order for something like Cow to be the default, you need more infrastructure. Maybe something like hipstr[1]. It is a nice abstraction, but not one that would be appropriate for std.

[1]: https://docs.rs/hipstr/latest/hipstr/

Re: Common Rust Lifetime Misconceptions (2020)

#73

How I bail myself out of Rust lifetime problems as somebody who probably learned Rust the wrong way (by just trying to build stuff as if it were C/node.js and run into problems instead of slowing down + reading): 1. .clone() / .to_owned() 1. String -> vs &String/&str with & borrow 1. lazy_static / OnceCell + Lazy / OnceLock 1. Arc > with lots of .lock(). What would start off as like NULL in Java/C is Arc >> and you h…

I know there was a thread involving a rust team member saying that clone / to_owned is ok to start with The memory copying just nags and distracts me from moving on

Yes, it absolutely is.

And it's even okay beyond just starting with.

Search the regex crate repository for clones. There are a lot of them. Hell, Regex::new accepts a &str for a pattern, and one of the first things it does is convert it to a String.

Re: Common Rust Lifetime Misconceptions (2020)

#74

Earlier quoted context omitted.

tokio is so wide spread now such that Arc > is coincidentally the right choice. I'm not saying that's a good thing.

Doesn't tokio have a single-threaded runtime where that's not needed?

Yes but Send + Sync is required everywhere regardless.

Re: Common Rust Lifetime Misconceptions (2020)

#75

Earlier quoted context omitted.

Me too. I also do this with .unwrap() - when I'm pretty sure of the happy path - while I'm prototyping. It's pretty easy afterwards to run back through and replace .unwrap() calls with better error handling. But as I improve, I'm getting more in the habit of using matching directly. Understanding lifetimes is probably really helpful for understanding library errors though and I need to go deeper there for sure

This is what I love about Rust, and other languages with these kinds of constructs. You have to acknowledge that something might e.g. fail. You can choose to do "nothing" (e.g. unwrap), but it must be done explicitly, which makes the ignored cases simple to identify later

.unwrap() is the new // TODO:

Re: Common Rust Lifetime Misconceptions (2020)

#76

How I bail myself out of Rust lifetime problems as somebody who probably learned Rust the wrong way (by just trying to build stuff as if it were C/node.js and run into problems instead of slowing down + reading): 1. .clone() / .to_owned() 1. String -> vs &String/&str with & borrow 1. lazy_static / OnceCell + Lazy / OnceLock 1. Arc > with lots of .lock(). What would start off as like NULL in Java/C is Arc >> and you h…

This is totally valid. Lifetimes can be an optimization you go back and add later as needed; in structs, especially, they require a ton of code changes to add and a ton of code changes to change your mind about later, so they should be used judiciously

Other things I would add to this list:

- For structs that don't own anything on the heap, derive Copy. Then you can just pass them around willy-nilly without explicit clone()s

- Using a functional style where it makes sense to helps a lot; it can be really easy to pass things by reference when they only need to be temporarily, immutably used by that one function. And if you make Copyable structs, you can pass owned structs and return owned structs and not worry about any of it

Re: Common Rust Lifetime Misconceptions (2020)

#77

Earlier quoted context omitted.

Doesn't tokio have a single-threaded runtime where that's not needed?

Yes but Send + Sync is required everywhere regardless.

This is not true, you can run non-send futures using Tokio: https://docs.rs/tokio/latest/tokio/task/struct.LocalSet.html

Re: Common Rust Lifetime Misconceptions (2020)

#78
post #31

Incredible. I never held the quoted misconception about `T: '*`, but I didn't understand it. It was a known unknown - I simply applied it when told to do so. This is the first time someone has explained it an understandable way, I guess the implications (it's a ref of that lifetime or an owned) are a better explanation than the technical (T is bounded by the lifetime).

“Applied it when told to do so.” This is my beginner-level experience with Rust. It’s amazing that the compiler can be so specific about what’s wrong. But taking the error and getting explanations that even I can understand has been tricky.

If you have thoughts on how to improve the output for better understanding, do file a ticket against rustc. We are space constrained, so we try to avoid long explanations as much as possible, but we sometimes do or add links to the right spot in the docs.

Re: Common Rust Lifetime Misconceptions (2020)

#79

Earlier quoted context omitted.

“Applied it when told to do so.” This is my beginner-level experience with Rust. It’s amazing that the compiler can be so specific about what’s wrong. But taking the error and getting explanations that even I can understand has been tricky.

If you have thoughts on how to improve the output for better understanding, do file a ticket against rustc. We are space constrained, so we try to avoid long explanations as much as possible, but we sometimes do or add links to the right spot in the docs.

Oh, I don’t have any criticism for the messages. It’s amazing that they can be so correct. And I’ve yet to find one I cannot quickly and accurately google. I’m criticizing my inability to convert them into knowledge vs just blindly doing what it’s telling me to do.

I would personally discourage trying to accomplish too much in the error messages. As long as they are a sufficient breadcrumb for what’s wrong, where, and enough key words to research, that seems ideal.

Re: Common Rust Lifetime Misconceptions (2020)

#80

Earlier quoted context omitted.

So from reading those comments, I'd come to the opposite conclusion: Cow is absolutely the right choice and perhaps String should really have been Cow . Insofar as taking an impl into, burntsushi linked to a rust playground demonstrating where that approach falls down. In general (heh) taking arguments , especially options or stringy ones, that are generalized over an into impl is one of those things that seems real…

In my defense, I said I occasionally regret the choice. But in rebuttal, I certainly do not have your confidence that returning Cow is the right choice. Basically, when it comes down to it, I'm not 100% convinced that it pulls its weight. But like I said in the issue, it's decently motivated. I don't think String could be a Cow . Remember, Cow is actually a Cow , and if you want to borrow a &str from a Cow, the lifet…

(Sorry I missed the word “occasionally” there!)
Post reply on HN