1
- use clippy_utils:: consts:: { constant, constant_full_int, miri_to_const, FullInt } ;
2
1
use clippy_utils:: diagnostics:: {
3
2
multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
4
3
} ;
@@ -19,18 +18,18 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
19
18
use rustc_hir:: LangItem :: { OptionNone , OptionSome } ;
20
19
use rustc_hir:: {
21
20
self as hir, Arm , BindingAnnotation , BorrowKind , Expr , ExprKind , Local , MatchSource , Mutability , Node , Pat ,
22
- PatKind , PathSegment , QPath , RangeEnd , TyKind ,
21
+ PatKind , PathSegment , QPath , TyKind ,
23
22
} ;
24
23
use rustc_lint:: { LateContext , LateLintPass } ;
25
- use rustc_middle:: ty:: { self , Ty , VariantDef } ;
24
+ use rustc_middle:: ty:: { self , VariantDef } ;
26
25
use rustc_semver:: RustcVersion ;
27
26
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
28
- use rustc_span:: { sym, symbol:: kw, Span } ;
29
- use std:: cmp:: Ordering ;
27
+ use rustc_span:: { sym, symbol:: kw} ;
30
28
31
29
mod match_bool;
32
30
mod match_like_matches;
33
31
mod match_same_arms;
32
+ mod overlapping_arms;
34
33
mod redundant_pattern_match;
35
34
mod single_match;
36
35
@@ -632,7 +631,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
632
631
if let ExprKind :: Match ( ex, arms, MatchSource :: Normal ) = expr. kind {
633
632
single_match:: check ( cx, ex, arms, expr) ;
634
633
match_bool:: check ( cx, ex, arms, expr) ;
635
- check_overlapping_arms ( cx, ex, arms) ;
634
+ overlapping_arms :: check ( cx, ex, arms) ;
636
635
check_wild_err_arm ( cx, ex, arms) ;
637
636
check_wild_enum_match ( cx, ex, arms) ;
638
637
check_match_as_ref ( cx, ex, arms, expr) ;
@@ -710,24 +709,6 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
710
709
extract_msrv_attr ! ( LateContext ) ;
711
710
}
712
711
713
- fn check_overlapping_arms < ' tcx > ( cx : & LateContext < ' tcx > , ex : & ' tcx Expr < ' _ > , arms : & ' tcx [ Arm < ' _ > ] ) {
714
- if arms. len ( ) >= 2 && cx. typeck_results ( ) . expr_ty ( ex) . is_integral ( ) {
715
- let ranges = all_ranges ( cx, arms, cx. typeck_results ( ) . expr_ty ( ex) ) ;
716
- if !ranges. is_empty ( ) {
717
- if let Some ( ( start, end) ) = overlapping ( & ranges) {
718
- span_lint_and_note (
719
- cx,
720
- MATCH_OVERLAPPING_ARM ,
721
- start. span ,
722
- "some ranges overlap" ,
723
- Some ( end. span ) ,
724
- "overlaps with this" ,
725
- ) ;
726
- }
727
- }
728
- }
729
- }
730
-
731
712
fn check_wild_err_arm < ' tcx > ( cx : & LateContext < ' tcx > , ex : & Expr < ' tcx > , arms : & [ Arm < ' tcx > ] ) {
732
713
let ex_ty = cx. typeck_results ( ) . expr_ty ( ex) . peel_refs ( ) ;
733
714
if is_type_diagnostic_item ( cx, ex_ty, sym:: Result ) {
@@ -1219,59 +1200,6 @@ fn opt_parent_let<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<&'a Local<'
1219
1200
None
1220
1201
}
1221
1202
1222
- /// Gets the ranges for each range pattern arm. Applies `ty` bounds for open ranges.
1223
- fn all_ranges < ' tcx > ( cx : & LateContext < ' tcx > , arms : & ' tcx [ Arm < ' _ > ] , ty : Ty < ' tcx > ) -> Vec < SpannedRange < FullInt > > {
1224
- arms. iter ( )
1225
- . filter_map ( |arm| {
1226
- if let Arm { pat, guard : None , .. } = * arm {
1227
- if let PatKind :: Range ( ref lhs, ref rhs, range_end) = pat. kind {
1228
- let lhs_const = match lhs {
1229
- Some ( lhs) => constant ( cx, cx. typeck_results ( ) , lhs) ?. 0 ,
1230
- None => miri_to_const ( ty. numeric_min_val ( cx. tcx ) ?) ?,
1231
- } ;
1232
- let rhs_const = match rhs {
1233
- Some ( rhs) => constant ( cx, cx. typeck_results ( ) , rhs) ?. 0 ,
1234
- None => miri_to_const ( ty. numeric_max_val ( cx. tcx ) ?) ?,
1235
- } ;
1236
-
1237
- let lhs_val = lhs_const. int_value ( cx, ty) ?;
1238
- let rhs_val = rhs_const. int_value ( cx, ty) ?;
1239
-
1240
- let rhs_bound = match range_end {
1241
- RangeEnd :: Included => EndBound :: Included ( rhs_val) ,
1242
- RangeEnd :: Excluded => EndBound :: Excluded ( rhs_val) ,
1243
- } ;
1244
- return Some ( SpannedRange {
1245
- span : pat. span ,
1246
- node : ( lhs_val, rhs_bound) ,
1247
- } ) ;
1248
- }
1249
-
1250
- if let PatKind :: Lit ( value) = pat. kind {
1251
- let value = constant_full_int ( cx, cx. typeck_results ( ) , value) ?;
1252
- return Some ( SpannedRange {
1253
- span : pat. span ,
1254
- node : ( value, EndBound :: Included ( value) ) ,
1255
- } ) ;
1256
- }
1257
- }
1258
- None
1259
- } )
1260
- . collect ( )
1261
- }
1262
-
1263
- #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
1264
- pub enum EndBound < T > {
1265
- Included ( T ) ,
1266
- Excluded ( T ) ,
1267
- }
1268
-
1269
- #[ derive( Debug , Eq , PartialEq ) ]
1270
- struct SpannedRange < T > {
1271
- pub span : Span ,
1272
- pub node : ( T , EndBound < T > ) ,
1273
- }
1274
-
1275
1203
// Checks if arm has the form `None => None`
1276
1204
fn is_none_arm ( cx : & LateContext < ' _ > , arm : & Arm < ' _ > ) -> bool {
1277
1205
matches ! ( arm. pat. kind, PatKind :: Path ( ref qpath) if is_lang_ctor( cx, qpath, OptionNone ) )
@@ -1317,104 +1245,3 @@ where
1317
1245
}
1318
1246
ref_count > 1
1319
1247
}
1320
-
1321
- fn overlapping < T > ( ranges : & [ SpannedRange < T > ] ) -> Option < ( & SpannedRange < T > , & SpannedRange < T > ) >
1322
- where
1323
- T : Copy + Ord ,
1324
- {
1325
- #[ derive( Copy , Clone , Debug , Eq , Ord , PartialEq , PartialOrd ) ]
1326
- enum BoundKind {
1327
- EndExcluded ,
1328
- Start ,
1329
- EndIncluded ,
1330
- }
1331
-
1332
- #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
1333
- struct RangeBound < ' a , T > ( T , BoundKind , & ' a SpannedRange < T > ) ;
1334
-
1335
- impl < ' a , T : Copy + Ord > PartialOrd for RangeBound < ' a , T > {
1336
- fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
1337
- Some ( self . cmp ( other) )
1338
- }
1339
- }
1340
-
1341
- impl < ' a , T : Copy + Ord > Ord for RangeBound < ' a , T > {
1342
- fn cmp ( & self , RangeBound ( other_value, other_kind, _) : & Self ) -> Ordering {
1343
- let RangeBound ( self_value, self_kind, _) = * self ;
1344
- ( self_value, self_kind) . cmp ( & ( * other_value, * other_kind) )
1345
- }
1346
- }
1347
-
1348
- let mut values = Vec :: with_capacity ( 2 * ranges. len ( ) ) ;
1349
-
1350
- for r @ SpannedRange { node : ( start, end) , .. } in ranges {
1351
- values. push ( RangeBound ( * start, BoundKind :: Start , r) ) ;
1352
- values. push ( match end {
1353
- EndBound :: Excluded ( val) => RangeBound ( * val, BoundKind :: EndExcluded , r) ,
1354
- EndBound :: Included ( val) => RangeBound ( * val, BoundKind :: EndIncluded , r) ,
1355
- } ) ;
1356
- }
1357
-
1358
- values. sort ( ) ;
1359
-
1360
- let mut started = vec ! [ ] ;
1361
-
1362
- for RangeBound ( _, kind, range) in values {
1363
- match kind {
1364
- BoundKind :: Start => started. push ( range) ,
1365
- BoundKind :: EndExcluded | BoundKind :: EndIncluded => {
1366
- let mut overlap = None ;
1367
-
1368
- while let Some ( last_started) = started. pop ( ) {
1369
- if last_started == range {
1370
- break ;
1371
- }
1372
- overlap = Some ( last_started) ;
1373
- }
1374
-
1375
- if let Some ( first_overlapping) = overlap {
1376
- return Some ( ( range, first_overlapping) ) ;
1377
- }
1378
- } ,
1379
- }
1380
- }
1381
-
1382
- None
1383
- }
1384
-
1385
- #[ test]
1386
- fn test_overlapping ( ) {
1387
- use rustc_span:: source_map:: DUMMY_SP ;
1388
-
1389
- let sp = |s, e| SpannedRange {
1390
- span : DUMMY_SP ,
1391
- node : ( s, e) ,
1392
- } ;
1393
-
1394
- assert_eq ! ( None , overlapping:: <u8 >( & [ ] ) ) ;
1395
- assert_eq ! ( None , overlapping( & [ sp( 1 , EndBound :: Included ( 4 ) ) ] ) ) ;
1396
- assert_eq ! (
1397
- None ,
1398
- overlapping( & [ sp( 1 , EndBound :: Included ( 4 ) ) , sp( 5 , EndBound :: Included ( 6 ) ) ] )
1399
- ) ;
1400
- assert_eq ! (
1401
- None ,
1402
- overlapping( & [
1403
- sp( 1 , EndBound :: Included ( 4 ) ) ,
1404
- sp( 5 , EndBound :: Included ( 6 ) ) ,
1405
- sp( 10 , EndBound :: Included ( 11 ) )
1406
- ] , )
1407
- ) ;
1408
- assert_eq ! (
1409
- Some ( ( & sp( 1 , EndBound :: Included ( 4 ) ) , & sp( 3 , EndBound :: Included ( 6 ) ) ) ) ,
1410
- overlapping( & [ sp( 1 , EndBound :: Included ( 4 ) ) , sp( 3 , EndBound :: Included ( 6 ) ) ] )
1411
- ) ;
1412
- assert_eq ! (
1413
- Some ( ( & sp( 5 , EndBound :: Included ( 6 ) ) , & sp( 6 , EndBound :: Included ( 11 ) ) ) ) ,
1414
- overlapping( & [
1415
- sp( 1 , EndBound :: Included ( 4 ) ) ,
1416
- sp( 5 , EndBound :: Included ( 6 ) ) ,
1417
- sp( 6 , EndBound :: Included ( 11 ) )
1418
- ] , )
1419
- ) ;
1420
- }
0 commit comments