There should be no real difference, since IntoIterator implementation for Optionin the end just calls take, which delegates to mem::take. However, if let should be in most cases more clear for future readers.
@2e71828 That's a good question. I'm not sure either, but here's my guess:
Looking at the list of all "Correctness" lints, it seems that these lints flag code that probably don't work the way the author intends. For this one, it is possible that one erroneously iterates over an iterator wrapped in an Option and intends to iterate over the contained iterator instead. For example: (contrived)
let names = /* Option<Vec<String>> */;
for name in names {
println!("{}", name);
}
Second reason: for <pattern> in opt is an expression that consumes / takes ownership of opt, no matter the <pattern> used, whereas if let Some(<pattern>) = opt will only consume opt if the <pattern> does:
let mut opt;
opt = Some(42);
if let Some(ref mut x) = opt {
*x += 27;
}
assert_eq!(opt, Some(42 + 27)); // Passes
opt = Some(42);
for ref mut x in opt {
*x += 27;
}
assert_eq!(opt, Some(42 + 27)); // Fails
for x in option looks like a bug to me. I know it technically works, but whenever I see such code I doubt whether the author actually meant to make a loop out of a single element, and suspect the code accidentally failed to unwrap somewhere.
As for "which generates better code", you can check at https://rust.godbolt.org/ (but don't forget to add -O to flags, because godbolt defaults to debug mode, which always generates awful code that is not representative of performant use of rust)