@@ -8,7 +8,7 @@ use rustc_index::{Idx, IndexVec};
8
8
use rustc_middle:: middle:: stability:: EvalResult ;
9
9
use rustc_middle:: mir:: interpret:: Scalar ;
10
10
use rustc_middle:: mir:: { self , Const } ;
11
- use rustc_middle:: thir:: { FieldPat , Pat , PatKind , PatRange , PatRangeBoundary } ;
11
+ use rustc_middle:: thir:: { self , FieldPat , Pat , PatKind , PatRange , PatRangeBoundary } ;
12
12
use rustc_middle:: ty:: layout:: IntegerExt ;
13
13
use rustc_middle:: ty:: { self , FieldDef , OpaqueTypeKey , Ty , TyCtxt , TypeVisitableExt , VariantDef } ;
14
14
use rustc_session:: lint;
@@ -900,6 +900,70 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
900
900
let span = self . whole_match_span . unwrap_or ( self . scrut_span ) ;
901
901
Err ( self . tcx . dcx ( ) . span_err ( span, "reached pattern complexity limit" ) )
902
902
}
903
+
904
+ fn lint_non_contiguous_range_endpoints (
905
+ & self ,
906
+ pat : & crate :: pat:: DeconstructedPat < Self > ,
907
+ gap : IntRange ,
908
+ gapped_with : & [ & crate :: pat:: DeconstructedPat < Self > ] ,
909
+ ) {
910
+ let Some ( & thir_pat) = pat. data ( ) else { return } ;
911
+ let thir:: PatKind :: Range ( range) = & thir_pat. kind else { return } ;
912
+ // Only lint when the left range is an exclusive range.
913
+ if range. end != rustc_hir:: RangeEnd :: Excluded {
914
+ return ;
915
+ }
916
+ // `pat` is an exclusive range like `lo..gap`. `gapped_with` contains ranges that start with
917
+ // `gap+1`.
918
+ let suggested_range: thir:: Pat < ' _ > = {
919
+ // Suggest `lo..=gap` instead.
920
+ let mut suggested_range = thir_pat. clone ( ) ;
921
+ let thir:: PatKind :: Range ( range) = & mut suggested_range. kind else { unreachable ! ( ) } ;
922
+ range. end = rustc_hir:: RangeEnd :: Included ;
923
+ suggested_range
924
+ } ;
925
+ let gap_as_pat = self . hoist_pat_range ( & gap, * pat. ty ( ) ) ;
926
+ if gapped_with. is_empty ( ) {
927
+ // If `gapped_with` is empty, `gap == T::MAX`.
928
+ self . tcx . emit_node_span_lint (
929
+ lint:: builtin:: NON_CONTIGUOUS_RANGE_ENDPOINTS ,
930
+ self . match_lint_level ,
931
+ thir_pat. span ,
932
+ errors:: ExclusiveRangeMissingMax {
933
+ // Point at this range.
934
+ first_range : thir_pat. span ,
935
+ // That's the gap that isn't covered.
936
+ max : gap_as_pat. clone ( ) ,
937
+ // Suggest `lo..=max` instead.
938
+ suggestion : suggested_range. to_string ( ) ,
939
+ } ,
940
+ ) ;
941
+ } else {
942
+ self . tcx . emit_node_span_lint (
943
+ lint:: builtin:: NON_CONTIGUOUS_RANGE_ENDPOINTS ,
944
+ self . match_lint_level ,
945
+ thir_pat. span ,
946
+ errors:: ExclusiveRangeMissingGap {
947
+ // Point at this range.
948
+ first_range : thir_pat. span ,
949
+ // That's the gap that isn't covered.
950
+ gap : gap_as_pat. clone ( ) ,
951
+ // Suggest `lo..=gap` instead.
952
+ suggestion : suggested_range. to_string ( ) ,
953
+ // All these ranges skipped over `gap` which we think is probably a
954
+ // mistake.
955
+ gap_with : gapped_with
956
+ . iter ( )
957
+ . map ( |pat| errors:: GappedRange {
958
+ span : pat. data ( ) . unwrap ( ) . span ,
959
+ gap : gap_as_pat. clone ( ) ,
960
+ first_range : thir_pat. clone ( ) ,
961
+ } )
962
+ . collect ( ) ,
963
+ } ,
964
+ ) ;
965
+ }
966
+ }
903
967
}
904
968
905
969
/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
0 commit comments