Not linting irrefutable_let_patterns on let chains *[View all comments](https://triagebot.infra.rust-lang.org/gh-comments/rust-lang/rust/pull/146832)* # Description this PR makes the lint `irrefutable_let_patterns` not check for `let chains`, only check for single `if let`, `while let`, and `if let guard`. # Motivation Since `let chains` were stabilized, the following code has become common: ```rust fn max() -> usize { 42 } fn main() { if let mx = max() && mx < usize::MAX { /* */ } } ``` This code naturally expresses "please call that function and then do something if the return value satisfies a condition". Putting the let binding outside the if would be bad as then it remains in scope after the if, which is not the intent. Current Output: ```bash warning: leading irrefutable pattern in let chain --> src/main.rs:7:8 | 7 | if let mx = max() && mx < usize::MAX { | ^^^^^^^^^^^^^^ | = note: this pattern will always match = help: consider moving it outside of the construct = note: `#[warn(irrefutable_let_patterns)]` on by default ``` Another common case is progressively destructuring a struct with enum fields, or an enum with struct variants: ```rust struct NameOfOuterStruct { middle: NameOfMiddleEnum, other: (), } enum NameOfMiddleEnum { Inner(NameOfInnerStruct), Other(()), } struct NameOfInnerStruct { id: u32, } fn test(outer: NameOfOuterStruct) { if let NameOfOuterStruct { middle, .. } = outer && let NameOfMiddleEnum::Inner(inner) = middle && let NameOfInnerStruct { id } = inner { /* */ } } ``` Current Output: ```bash warning: leading irrefutable pattern in let chain --> src\main.rs:17:8 | 17 | if let NameOfOuterStruct { middle, .. } = outer | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this pattern will always match = help: consider moving it outside of the construct = note: `#[warn(irrefutable_let_patterns)]` on by default warning: trailing irrefutable pattern in let chain --> src\main.rs:19:12 | 19 | && let NameOfInnerStruct { id } = inner | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this pattern will always match = help: consider moving it into the body ``` To avoid the warning, the readability would be much worse: ```rust fn test(outer: NameOfOuterStruct) { if let NameOfOuterStruct { middle: NameOfMiddleEnum::Inner(NameOfInnerStruct { id }), .. } = outer { /* */ } } ``` # related issue * rust-lang/rust#139369 # possible questions 1. Moving the irrefutable pattern at the head of the chain out of it would cause a variable that was intended to be temporary to remain in scope, so we remove it. However, should we keep the check for moving the irrefutable pattern at the tail into the body? 2. Should we still lint `entire chain is made up of irrefutable let`? --- This is my first time contributing non-documentation code to Rust. If there are any irregularities, please feel free to point them out. : )
This is the main source code repository for Rust. It contains the compiler, standard library, and documentation.
Why Rust?
-
Performance: Fast and memory-efficient, suitable for critical services, embedded devices, and easily integrated with other languages.
-
Reliability: Our rich type system and ownership model ensure memory and thread safety, reducing bugs at compile-time.
-
Productivity: Comprehensive documentation, a compiler committed to providing great diagnostics, and advanced tooling including package manager and build tool (Cargo), auto-formatter (rustfmt), linter (Clippy) and editor support (rust-analyzer).
Quick Start
Read "Installation" from The Book.
Installing from Source
If you really want to install from source (though this is not recommended), see INSTALL.md.
Getting Help
See https://www.rust-lang.org/community for a list of chat platforms and forums.
Contributing
See CONTRIBUTING.md.
License
Rust is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0), with portions covered by various BSD-like licenses.
See LICENSE-APACHE, LICENSE-MIT, and COPYRIGHT for details.
Trademark
The Rust Foundation owns and protects the Rust and Cargo trademarks and logos (the "Rust Trademarks").
If you want to use these names or brands, please read the Rust language trademark policy.
Third-party logos may be subject to third-party copyrights and trademarks. See Licenses for details.