@@ -11,6 +11,7 @@ use rustc_middle::lint::in_external_macro;
1111use rustc_semver:: RustcVersion ;
1212use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
1313use rustc_span:: symbol:: sym;
14+ use serde:: Deserialize ;
1415use std:: ops:: ControlFlow ;
1516
1617declare_clippy_lint ! {
@@ -47,12 +48,16 @@ declare_clippy_lint! {
4748
4849pub struct ManualLetElse {
4950 msrv : Option < RustcVersion > ,
51+ matches_behaviour : MatchLintBehaviour ,
5052}
5153
5254impl ManualLetElse {
5355 #[ must_use]
54- pub fn new ( msrv : Option < RustcVersion > ) -> Self {
55- Self { msrv }
56+ pub fn new ( msrv : Option < RustcVersion > , matches_behaviour : MatchLintBehaviour ) -> Self {
57+ Self {
58+ msrv,
59+ matches_behaviour,
60+ }
5661 }
5762}
5863
@@ -89,6 +94,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
8994 }
9095 } ,
9196 IfLetOrMatch :: Match ( _match_expr, arms, source) => {
97+ if self . matches_behaviour == MatchLintBehaviour :: Never {
98+ return ;
99+ }
92100 if source != MatchSource :: Normal {
93101 return ;
94102 }
@@ -97,6 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
97105 if arms. len ( ) != 2 {
98106 return ;
99107 }
108+ let check_types = self . matches_behaviour == MatchLintBehaviour :: WellKnownTypes ;
100109 // We iterate over both arms, trying to find one that is an identity,
101110 // one that diverges. Our check needs to work regardless of the order
102111 // of both arms.
@@ -109,7 +118,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
109118 }
110119 if expr_is_simple_identity ( arm. pat , arm. body ) {
111120 found_identity_arm = true ;
112- } else if expr_diverges ( cx, arm. body ) && pat_allowed_for_else ( cx, arm. pat ) {
121+ } else if expr_diverges ( cx, arm. body ) && pat_allowed_for_else ( cx, arm. pat , check_types ) {
113122 found_diverging_arm = true ;
114123 }
115124 }
@@ -178,7 +187,7 @@ fn expr_diverges(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
178187 . is_some ( )
179188}
180189
181- fn pat_allowed_for_else ( cx : & LateContext < ' _ > , pat : & ' _ Pat < ' _ > ) -> bool {
190+ fn pat_allowed_for_else ( cx : & LateContext < ' _ > , pat : & ' _ Pat < ' _ > , check_types : bool ) -> bool {
182191 // Check whether the pattern contains any bindings, as the
183192 // binding might potentially be used in the body.
184193 // TODO: only look for *used* bindings.
@@ -188,6 +197,11 @@ fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>) -> bool {
188197 return false ;
189198 }
190199
200+ // If we shouldn't check the types, exit early.
201+ if !check_types {
202+ return true ;
203+ }
204+
191205 // Check whether any possibly "unknown" patterns are included,
192206 // because users might not know which values some enum has.
193207 // Well-known enums are excepted, as we assume people know them.
@@ -245,3 +259,10 @@ fn expr_is_simple_identity(pat: &'_ Pat<'_>, expr: &'_ Expr<'_>) -> bool {
245259 }
246260 true
247261}
262+
263+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , Deserialize ) ]
264+ pub enum MatchLintBehaviour {
265+ AllTypes ,
266+ WellKnownTypes ,
267+ Never ,
268+ }
0 commit comments