@@ -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 }
@@ -183,7 +192,7 @@ fn expr_diverges(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
183192 does_diverge
184193}
185194
186- fn pat_allowed_for_else ( cx : & LateContext < ' _ > , pat : & ' _ Pat < ' _ > ) -> bool {
195+ fn pat_allowed_for_else ( cx : & LateContext < ' _ > , pat : & ' _ Pat < ' _ > , check_types : bool ) -> bool {
187196 // Check whether the pattern contains any bindings, as the
188197 // binding might potentially be used in the body.
189198 // TODO: only look for *used* bindings.
@@ -193,6 +202,11 @@ fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>) -> bool {
193202 return false ;
194203 }
195204
205+ // If we shouldn't check the types, exit early.
206+ if !check_types {
207+ return true ;
208+ }
209+
196210 // Check whether any possibly "unknown" patterns are included,
197211 // because users might not which values some enum has.
198212 // Well-known enums are excepted, as we assume people know them.
@@ -250,3 +264,10 @@ fn expr_is_simple_identity(pat: &'_ Pat<'_>, expr: &'_ Expr<'_>) -> bool {
250264 }
251265 true
252266}
267+
268+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , Deserialize ) ]
269+ pub enum MatchLintBehaviour {
270+ AllTypes ,
271+ WellKnownTypes ,
272+ Never ,
273+ }
0 commit comments