- Feature Name: `let_chains_2` - Start Date: 2018-07-13 - RFC PR: [rust-lang/rfcs#2497](https://github.com/rust-lang/rfcs/pull/2497) - Rust Issue: [rust-lang/rust#53667](https://github.com/rust-lang/rust/issues/53667) - Rust Issue: [rust-lang/rust#53668](https://github.com/rust-lang/rust/issues/53668) # Summary [summary]: #summary Extends `if let` and `while let`-expressions with chaining, allowing you to combine multiple `let`s and `bool`-typed conditions together naturally. After implementing this RFC, you'll be able to write, among other things: ```rust fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ParamEnv<'tcx> { if let Some(Def::Existential(_)) = tcx.describe_def(def_id) && let Some(node_id) = tcx.hir.as_local_node_id(def_id) && let hir::map::NodeItem(item) = tcx.hir.get(node_id) && let hir::ItemExistential(ref exist_ty) = item.node && let Some(parent) = exist_ty.impl_trait_fn { return param_env(tcx, parent); } ... } ``` and with side effects: ```rust while let Ok(user) = read_user(::std::io::stdin()) && user.name == "Alan Turing" && let Ok(hobby) = read_hobby_of(&user) { if hobby == "Hacking Enigma" { println!("Yep, It's you."); return Some(read_encrypted_stuff()); } else { println!("You can't be Alan! "); } } return None; ``` The main aim of this RFC is to decide that this is a problem worth solving as well as discussing a few available options. **Most importantly, we want to make `if let PAT = EXPR && ..` a possible option for Rust 2018.** # Motivation [motivation]: #motivation The main motivation for this RFC is improving readability, ergonomics, and reducing paper cuts. ## Right-ward drift Today, each `if let` needs a brace, which means that you usually, to keep the code readable, indent once to the right each time. Thus, matching multiple things quickly leads to way too much indent that overflows the typical text editor or IDE horizontally. This is in particular bad for readers that can only fit around 80-100 characters per line in their editor. Keeping in mind that code is read more than written, it is important to improve readability where possible. ### Other solution: Tuples One solution is matching a tuple, but that is a poor solution when there are side effects or expensive computations involved, and doesn't necessarily work as *DSTs* and *lvalues* can't go in tuples. ### Other solution: `break ...` Another solution to avoid right-ward drift is to create a new function for part of the indentation. When the inner scopes depend on a lot of variables and state from outer scopes, all of these variables have to be passed on to the newly created function, which may not even be a natural unit to abstract into a function. Creating a new function, especially one that feels artificial, can also inhibit local reasoning. A new level of function (or [IIFE]) also changes the behaviour of `return`, `break`, `?`, and friends. [IIFE]: https://en.wikipedia.org/wiki/Immediately-invoked_function_expression A third solution involves using the expression form `break '