3 ms·
This isn't really something you usually encounter, but I have to bring this cute example: pub fn foo() -> impl FnOnce() { let non_copy: String = St
by afdbcreid 4y ago
This isn't really something you usually encounter, but I have to bring this cute example:
pub fn foo() -> impl FnOnce() {
let non_copy: String = String::new();
let copy: i32 = 123;
|| {
drop(non_copy); // Works
drop(copy); // error[E0373]
}
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8407d92696525bf915875e9a8d09bff0 https://play.rust-lang.org/?version=stable&mode=debug&editio...
- nyanpasu64 4y agoThis is another reason that I find (optional but first-class) explicit lambda captures (adding syntax for C++'s approach) is better, because it prevents this kind of implicit and surprising behavior.
- nynx 4y agoThere’s no implicit behavior here. It won’t compile if you don’t explicitly move the string into the closure.
- nyanpasu64 4y agoThe implicit behavior is that using a string moves it into the closure, and does compile even without `move || {...non_copy}` (which surprised even me), whereas using an integer takes a reference, and you have to "slap on `move` to make it work".
- afdbcreid 4y agoThe surprising part is that it does not compile with `Copy`, not that it compiles with `Copy`. The rules are that if a move a necessary then it is performed. The tricky part is that move is not necessary for `Copy` types, because you can capture a reference and still get an owned value.