@@ -189,73 +189,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
189189 if arms. len ( ) == 2 {
190190 let node_pair = ( & arms[ 0 ] . pat . kind , & arms[ 1 ] . pat . kind ) ;
191191
192- let found_good_method = match node_pair {
193- (
194- PatKind :: TupleStruct ( ref path_left, patterns_left, _) ,
195- PatKind :: TupleStruct ( ref path_right, patterns_right, _) ,
196- ) if patterns_left. len ( ) == 1 && patterns_right. len ( ) == 1 => {
197- if let ( PatKind :: Wild , PatKind :: Wild ) = ( & patterns_left[ 0 ] . kind , & patterns_right[ 0 ] . kind ) {
198- find_good_method_for_match (
199- cx,
200- arms,
201- path_left,
202- path_right,
203- Item :: Lang ( ResultOk ) ,
204- Item :: Lang ( ResultErr ) ,
205- "is_ok()" ,
206- "is_err()" ,
207- )
208- . or_else ( || {
209- find_good_method_for_match (
210- cx,
211- arms,
212- path_left,
213- path_right,
214- Item :: Diag ( sym:: IpAddr , sym ! ( V4 ) ) ,
215- Item :: Diag ( sym:: IpAddr , sym ! ( V6 ) ) ,
216- "is_ipv4()" ,
217- "is_ipv6()" ,
218- )
219- } )
220- } else {
221- None
222- }
223- } ,
224- ( PatKind :: TupleStruct ( ref path_left, patterns, _) , PatKind :: Path ( ref path_right) )
225- | ( PatKind :: Path ( ref path_left) , PatKind :: TupleStruct ( ref path_right, patterns, _) )
226- if patterns. len ( ) == 1 =>
227- {
228- if let PatKind :: Wild = patterns[ 0 ] . kind {
229- find_good_method_for_match (
230- cx,
231- arms,
232- path_left,
233- path_right,
234- Item :: Lang ( OptionSome ) ,
235- Item :: Lang ( OptionNone ) ,
236- "is_some()" ,
237- "is_none()" ,
238- )
239- . or_else ( || {
240- find_good_method_for_match (
241- cx,
242- arms,
243- path_left,
244- path_right,
245- Item :: Lang ( PollReady ) ,
246- Item :: Lang ( PollPending ) ,
247- "is_ready()" ,
248- "is_pending()" ,
249- )
250- } )
251- } else {
252- None
253- }
254- } ,
255- _ => None ,
256- } ;
257-
258- if let Some ( good_method) = found_good_method {
192+ if let Some ( good_method) = found_good_method ( cx, arms, node_pair) {
259193 let span = expr. span . to ( op. span ) ;
260194 let result_expr = match & op. kind {
261195 ExprKind :: AddrOf ( _, _, borrowed) => borrowed,
@@ -279,6 +213,127 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
279213 }
280214}
281215
216+ fn found_good_method < ' a > (
217+ cx : & LateContext < ' _ > ,
218+ arms : & [ Arm < ' _ > ] ,
219+ node : ( & PatKind < ' _ > , & PatKind < ' _ > ) ,
220+ ) -> Option < & ' a str > {
221+ match node {
222+ (
223+ PatKind :: TupleStruct ( ref path_left, patterns_left, _) ,
224+ PatKind :: TupleStruct ( ref path_right, patterns_right, _) ,
225+ ) if patterns_left. len ( ) == 1 && patterns_right. len ( ) == 1 => {
226+ if let ( PatKind :: Wild , PatKind :: Wild ) = ( & patterns_left[ 0 ] . kind , & patterns_right[ 0 ] . kind ) {
227+ find_good_method_for_match (
228+ cx,
229+ arms,
230+ path_left,
231+ path_right,
232+ Item :: Lang ( ResultOk ) ,
233+ Item :: Lang ( ResultErr ) ,
234+ "is_ok()" ,
235+ "is_err()" ,
236+ )
237+ . or_else ( || {
238+ find_good_method_for_match (
239+ cx,
240+ arms,
241+ path_left,
242+ path_right,
243+ Item :: Diag ( sym:: IpAddr , sym ! ( V4 ) ) ,
244+ Item :: Diag ( sym:: IpAddr , sym ! ( V6 ) ) ,
245+ "is_ipv4()" ,
246+ "is_ipv6()" ,
247+ )
248+ } )
249+ } else {
250+ None
251+ }
252+ } ,
253+ ( PatKind :: TupleStruct ( ref path_left, patterns, _) , PatKind :: Path ( ref path_right) )
254+ | ( PatKind :: Path ( ref path_left) , PatKind :: TupleStruct ( ref path_right, patterns, _) )
255+ if patterns. len ( ) == 1 =>
256+ {
257+ if let PatKind :: Wild = patterns[ 0 ] . kind {
258+ find_good_method_for_match (
259+ cx,
260+ arms,
261+ path_left,
262+ path_right,
263+ Item :: Lang ( OptionSome ) ,
264+ Item :: Lang ( OptionNone ) ,
265+ "is_some()" ,
266+ "is_none()" ,
267+ )
268+ . or_else ( || {
269+ find_good_method_for_match (
270+ cx,
271+ arms,
272+ path_left,
273+ path_right,
274+ Item :: Lang ( PollReady ) ,
275+ Item :: Lang ( PollPending ) ,
276+ "is_ready()" ,
277+ "is_pending()" ,
278+ )
279+ } )
280+ } else {
281+ None
282+ }
283+ } ,
284+ ( PatKind :: TupleStruct ( ref path_left, patterns, _) , PatKind :: Wild ) if patterns. len ( ) == 1 => {
285+ if let PatKind :: Wild = patterns[ 0 ] . kind {
286+ get_good_method ( cx, arms, path_left)
287+ } else {
288+ None
289+ }
290+ } ,
291+ ( PatKind :: Path ( ref path_left) , PatKind :: Wild ) => get_good_method ( cx, arms, path_left) ,
292+ _ => None ,
293+ }
294+ }
295+
296+ fn get_ident ( path : & QPath < ' _ > ) -> Option < rustc_span:: symbol:: Ident > {
297+ match path {
298+ QPath :: Resolved ( _, path) => {
299+ let name = path. segments [ 0 ] . ident ;
300+ Some ( name)
301+ } ,
302+ _ => None ,
303+ }
304+ }
305+
306+ fn get_good_method < ' a > ( cx : & LateContext < ' _ > , arms : & [ Arm < ' _ > ] , path_left : & QPath < ' _ > ) -> Option < & ' a str > {
307+ if let Some ( name) = get_ident ( path_left) {
308+ return match name. as_str ( ) {
309+ "Ok" => {
310+ find_good_method_for_matches_macro ( cx, arms, path_left, Item :: Lang ( ResultOk ) , "is_ok()" , "is_err()" )
311+ } ,
312+ "Err" => {
313+ find_good_method_for_matches_macro ( cx, arms, path_left, Item :: Lang ( ResultErr ) , "is_err()" , "is_ok()" )
314+ } ,
315+ "Some" => find_good_method_for_matches_macro (
316+ cx,
317+ arms,
318+ path_left,
319+ Item :: Lang ( OptionSome ) ,
320+ "is_some()" ,
321+ "is_none()" ,
322+ ) ,
323+ "None" => find_good_method_for_matches_macro (
324+ cx,
325+ arms,
326+ path_left,
327+ Item :: Lang ( OptionNone ) ,
328+ "is_none()" ,
329+ "is_some()" ,
330+ ) ,
331+ _ => None ,
332+ } ;
333+ }
334+ None
335+ }
336+
282337#[ derive( Clone , Copy ) ]
283338enum Item {
284339 Lang ( LangItem ) ,
@@ -345,3 +400,29 @@ fn find_good_method_for_match<'a>(
345400 _ => None ,
346401 }
347402}
403+
404+ fn find_good_method_for_matches_macro < ' a > (
405+ cx : & LateContext < ' _ > ,
406+ arms : & [ Arm < ' _ > ] ,
407+ path_left : & QPath < ' _ > ,
408+ expected_item_left : Item ,
409+ should_be_left : & ' a str ,
410+ should_be_right : & ' a str ,
411+ ) -> Option < & ' a str > {
412+ let first_pat = arms[ 0 ] . pat ;
413+
414+ let body_node_pair = if is_pat_variant ( cx, first_pat, path_left, expected_item_left) {
415+ ( & arms[ 0 ] . body . kind , & arms[ 1 ] . body . kind )
416+ } else {
417+ return None ;
418+ } ;
419+
420+ match body_node_pair {
421+ ( ExprKind :: Lit ( lit_left) , ExprKind :: Lit ( lit_right) ) => match ( & lit_left. node , & lit_right. node ) {
422+ ( LitKind :: Bool ( true ) , LitKind :: Bool ( false ) ) => Some ( should_be_left) ,
423+ ( LitKind :: Bool ( false ) , LitKind :: Bool ( true ) ) => Some ( should_be_right) ,
424+ _ => None ,
425+ } ,
426+ _ => None ,
427+ }
428+ }
0 commit comments