1- use clippy_utils:: consts:: { constant, constant_full_int, miri_to_const, FullInt } ;
21use clippy_utils:: diagnostics:: {
32 multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
43} ;
@@ -19,18 +18,18 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
1918use rustc_hir:: LangItem :: { OptionNone , OptionSome } ;
2019use rustc_hir:: {
2120 self as hir, Arm , BindingAnnotation , BorrowKind , Expr , ExprKind , Local , MatchSource , Mutability , Node , Pat ,
22- PatKind , PathSegment , QPath , RangeEnd , TyKind ,
21+ PatKind , PathSegment , QPath , TyKind ,
2322} ;
2423use rustc_lint:: { LateContext , LateLintPass } ;
25- use rustc_middle:: ty:: { self , Ty , VariantDef } ;
24+ use rustc_middle:: ty:: { self , VariantDef } ;
2625use rustc_semver:: RustcVersion ;
2726use 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} ;
3028
3129mod match_bool;
3230mod match_like_matches;
3331mod match_same_arms;
32+ mod overlapping_arms;
3433mod redundant_pattern_match;
3534mod single_match;
3635
@@ -632,7 +631,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
632631 if let ExprKind :: Match ( ex, arms, MatchSource :: Normal ) = expr. kind {
633632 single_match:: check ( cx, ex, arms, expr) ;
634633 match_bool:: check ( cx, ex, arms, expr) ;
635- check_overlapping_arms ( cx, ex, arms) ;
634+ overlapping_arms :: check ( cx, ex, arms) ;
636635 check_wild_err_arm ( cx, ex, arms) ;
637636 check_wild_enum_match ( cx, ex, arms) ;
638637 check_match_as_ref ( cx, ex, arms, expr) ;
@@ -710,24 +709,6 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
710709 extract_msrv_attr ! ( LateContext ) ;
711710}
712711
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-
731712fn check_wild_err_arm < ' tcx > ( cx : & LateContext < ' tcx > , ex : & Expr < ' tcx > , arms : & [ Arm < ' tcx > ] ) {
732713 let ex_ty = cx. typeck_results ( ) . expr_ty ( ex) . peel_refs ( ) ;
733714 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<'
12191200 None
12201201}
12211202
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-
12751203// Checks if arm has the form `None => None`
12761204fn is_none_arm ( cx : & LateContext < ' _ > , arm : & Arm < ' _ > ) -> bool {
12771205 matches ! ( arm. pat. kind, PatKind :: Path ( ref qpath) if is_lang_ctor( cx, qpath, OptionNone ) )
@@ -1317,104 +1245,3 @@ where
13171245 }
13181246 ref_count > 1
13191247}
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