match is exhaustive, which is powerful but verbose when you care about exactly one pattern. The let-family of constructs are the ergonomic shortcuts for that common case.
if let — one pattern, ignore the rest
if let Some(x) = opt { ... } runs the block only when the pattern matches, binding x for use inside. Everything else is silently skipped. You can add an else for the non-matching case. It's exactly a match with one real arm and a _ => {}, but without the ceremony.
let else — match or bail out
let Some(x) = opt else { return; }; binds x if the pattern matches, and otherwise runs the else block, which must diverge (return, break, panic). After this line, x is available in the rest of the function — no nesting. It's the clean way to handle 'if this isn't present, stop here' at the top of a function.
if let { ... }, use let ... else { return } to handle the bad case early and keep the main logic un-indented. It's the Rust answer to the early-return guard clause.while let — loop until the pattern fails
while let Some(x) = iter.next() { ... } keeps looping as long as the pattern matches, stopping the moment it gets None. It's the natural way to drain a stack, consume an iterator manually, or process a queue until empty.