@@ -4,17 +4,16 @@ use rustc_data_structures::captures::Captures;
44use rustc_middle:: ty:: { self , Ty } ;
55use rustc_session:: lint;
66use rustc_session:: lint:: builtin:: NON_EXHAUSTIVE_OMITTED_PATTERNS ;
7- use rustc_span:: Span ;
87
9- use crate :: constructor:: { IntRange , MaybeInfiniteInt } ;
8+ use crate :: constructor:: MaybeInfiniteInt ;
109use crate :: errors:: {
11- NonExhaustiveOmittedPattern , NonExhaustiveOmittedPatternLintOnArm , Overlap ,
12- OverlappingRangeEndpoints , Uncovered ,
10+ self , NonExhaustiveOmittedPattern , NonExhaustiveOmittedPatternLintOnArm , Uncovered ,
1311} ;
1412use crate :: rustc:: {
15- Constructor , DeconstructedPat , MatchArm , MatchCtxt , PlaceCtxt , RustcMatchCheckCtxt ,
13+ self , Constructor , DeconstructedPat , MatchArm , MatchCtxt , PlaceCtxt , RustcMatchCheckCtxt ,
1614 SplitConstructorSet , WitnessPat ,
1715} ;
16+ use crate :: usefulness:: OverlappingRanges ;
1817use crate :: TypeCx ;
1918
2019/// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
@@ -214,34 +213,19 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
214213
215214/// Traverse the patterns to warn the user about ranges that overlap on their endpoints.
216215#[ instrument( level = "debug" , skip( cx) ) ]
217- pub ( crate ) fn lint_overlapping_range_endpoints < ' a , ' p , ' tcx > (
216+ pub ( crate ) fn collect_overlapping_range_endpoints < ' a , ' p , ' tcx > (
218217 cx : MatchCtxt < ' a , ' p , ' tcx > ,
219218 column : & PatternColumn < ' p , ' tcx > ,
219+ overlapping_range_endpoints : & mut Vec < rustc:: OverlappingRanges < ' p , ' tcx > > ,
220220) {
221221 let Some ( ty) = column. head_ty ( cx) else {
222222 return ;
223223 } ;
224224 let pcx = & PlaceCtxt :: new_dummy ( cx, ty) ;
225- let rcx: & RustcMatchCheckCtxt < ' _ , ' _ > = cx. tycx ;
226225
227226 let set = column. analyze_ctors ( pcx) ;
228227
229228 if matches ! ( ty. kind( ) , ty:: Char | ty:: Int ( _) | ty:: Uint ( _) ) {
230- let emit_lint = |overlap : & IntRange , this_span : Span , overlapped_spans : & [ Span ] | {
231- let overlap_as_pat = rcx. hoist_pat_range ( overlap, ty) ;
232- let overlaps: Vec < _ > = overlapped_spans
233- . iter ( )
234- . copied ( )
235- . map ( |span| Overlap { range : overlap_as_pat. clone ( ) , span } )
236- . collect ( ) ;
237- rcx. tcx . emit_spanned_lint (
238- lint:: builtin:: OVERLAPPING_RANGE_ENDPOINTS ,
239- rcx. match_lint_level ,
240- this_span,
241- OverlappingRangeEndpoints { overlap : overlaps, range : this_span } ,
242- ) ;
243- } ;
244-
245229 // If two ranges overlapped, the split set will contain their intersection as a singleton.
246230 let split_int_ranges = set. present . iter ( ) . filter_map ( |c| c. as_int_range ( ) ) ;
247231 for overlap_range in split_int_ranges. clone ( ) {
@@ -254,7 +238,6 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
254238 // Iterate on patterns that contained `overlap`.
255239 for pat in column. iter ( ) {
256240 let Constructor :: IntRange ( this_range) = pat. ctor ( ) else { continue } ;
257- let this_span = pat. data ( ) . unwrap ( ) . span ;
258241 if this_range. is_singleton ( ) {
259242 // Don't lint when one of the ranges is a singleton.
260243 continue ;
@@ -263,16 +246,24 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
263246 // `this_range` looks like `overlap..=this_range.hi`; it overlaps with any
264247 // ranges that look like `lo..=overlap`.
265248 if !prefixes. is_empty ( ) {
266- emit_lint ( overlap_range, this_span, & prefixes) ;
249+ overlapping_range_endpoints. push ( OverlappingRanges {
250+ pat,
251+ overlaps_on : * overlap_range,
252+ overlaps_with : prefixes. as_slice ( ) . to_vec ( ) ,
253+ } ) ;
267254 }
268- suffixes. push ( this_span )
255+ suffixes. push ( pat )
269256 } else if this_range. hi == overlap. plus_one ( ) {
270257 // `this_range` looks like `this_range.lo..=overlap`; it overlaps with any
271258 // ranges that look like `overlap..=hi`.
272259 if !suffixes. is_empty ( ) {
273- emit_lint ( overlap_range, this_span, & suffixes) ;
260+ overlapping_range_endpoints. push ( OverlappingRanges {
261+ pat,
262+ overlaps_on : * overlap_range,
263+ overlaps_with : suffixes. as_slice ( ) . to_vec ( ) ,
264+ } ) ;
274265 }
275- prefixes. push ( this_span )
266+ prefixes. push ( pat )
276267 }
277268 }
278269 }
@@ -281,8 +272,35 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
281272 // Recurse into the fields.
282273 for ctor in set. present {
283274 for col in column. specialize ( pcx, & ctor) {
284- lint_overlapping_range_endpoints ( cx, & col) ;
275+ collect_overlapping_range_endpoints ( cx, & col, overlapping_range_endpoints ) ;
285276 }
286277 }
287278 }
288279}
280+
281+ #[ instrument( level = "debug" , skip( cx) ) ]
282+ pub ( crate ) fn lint_overlapping_range_endpoints < ' a , ' p , ' tcx > (
283+ cx : MatchCtxt < ' a , ' p , ' tcx > ,
284+ column : & PatternColumn < ' p , ' tcx > ,
285+ ) {
286+ let mut overlapping_range_endpoints = Vec :: new ( ) ;
287+ collect_overlapping_range_endpoints ( cx, column, & mut overlapping_range_endpoints) ;
288+
289+ let rcx = cx. tycx ;
290+ for overlap in overlapping_range_endpoints {
291+ let overlap_as_pat = rcx. hoist_pat_range ( & overlap. overlaps_on , overlap. pat . ty ( ) ) ;
292+ let overlaps: Vec < _ > = overlap
293+ . overlaps_with
294+ . iter ( )
295+ . map ( |pat| pat. data ( ) . unwrap ( ) . span )
296+ . map ( |span| errors:: Overlap { range : overlap_as_pat. clone ( ) , span } )
297+ . collect ( ) ;
298+ let pat_span = overlap. pat . data ( ) . unwrap ( ) . span ;
299+ rcx. tcx . emit_spanned_lint (
300+ lint:: builtin:: OVERLAPPING_RANGE_ENDPOINTS ,
301+ rcx. match_lint_level ,
302+ pat_span,
303+ errors:: OverlappingRangeEndpoints { overlap : overlaps, range : pat_span } ,
304+ ) ;
305+ }
306+ }
0 commit comments