@@ -4,17 +4,17 @@ use rustc_data_structures::captures::Captures;
4
4
use rustc_middle:: ty:: { self , Ty } ;
5
5
use rustc_session:: lint;
6
6
use rustc_session:: lint:: builtin:: NON_EXHAUSTIVE_OMITTED_PATTERNS ;
7
- use rustc_span:: Span ;
8
7
9
- use crate :: constructor:: { IntRange , MaybeInfiniteInt } ;
8
+ use crate :: constructor:: MaybeInfiniteInt ;
10
9
use crate :: errors:: {
11
10
NonExhaustiveOmittedPattern , NonExhaustiveOmittedPatternLintOnArm , Overlap ,
12
11
OverlappingRangeEndpoints , Uncovered ,
13
12
} ;
14
13
use crate :: rustc:: {
15
- Constructor , DeconstructedPat , MatchArm , MatchCtxt , PlaceCtxt , RustcMatchCheckCtxt ,
14
+ self , Constructor , DeconstructedPat , MatchArm , MatchCtxt , PlaceCtxt , RustcMatchCheckCtxt ,
16
15
SplitConstructorSet , WitnessPat ,
17
16
} ;
17
+ use crate :: usefulness:: OverlappingRanges ;
18
18
use crate :: TypeCx ;
19
19
20
20
/// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
@@ -214,34 +214,19 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
214
214
215
215
/// Traverse the patterns to warn the user about ranges that overlap on their endpoints.
216
216
#[ instrument( level = "debug" , skip( cx) ) ]
217
- pub ( crate ) fn lint_overlapping_range_endpoints < ' a , ' p , ' tcx > (
217
+ pub ( crate ) fn collect_overlapping_range_endpoints < ' a , ' p , ' tcx > (
218
218
cx : MatchCtxt < ' a , ' p , ' tcx > ,
219
219
column : & PatternColumn < ' p , ' tcx > ,
220
+ overlapping_range_endpoints : & mut Vec < rustc:: OverlappingRanges < ' p , ' tcx > > ,
220
221
) {
221
222
let Some ( ty) = column. head_ty ( cx) else {
222
223
return ;
223
224
} ;
224
225
let pcx = & PlaceCtxt :: new_dummy ( cx, ty) ;
225
- let rcx: & RustcMatchCheckCtxt < ' _ , ' _ > = cx. tycx ;
226
226
227
227
let set = column. analyze_ctors ( pcx) ;
228
228
229
229
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
-
245
230
// If two ranges overlapped, the split set will contain their intersection as a singleton.
246
231
let split_int_ranges = set. present . iter ( ) . filter_map ( |c| c. as_int_range ( ) ) ;
247
232
for overlap_range in split_int_ranges. clone ( ) {
@@ -254,7 +239,6 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
254
239
// Iterate on patterns that contained `overlap`.
255
240
for pat in column. iter ( ) {
256
241
let Constructor :: IntRange ( this_range) = pat. ctor ( ) else { continue } ;
257
- let this_span = pat. data ( ) . unwrap ( ) . span ;
258
242
if this_range. is_singleton ( ) {
259
243
// Don't lint when one of the ranges is a singleton.
260
244
continue ;
@@ -263,16 +247,24 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
263
247
// `this_range` looks like `overlap..=this_range.hi`; it overlaps with any
264
248
// ranges that look like `lo..=overlap`.
265
249
if !prefixes. is_empty ( ) {
266
- emit_lint ( overlap_range, this_span, & prefixes) ;
250
+ overlapping_range_endpoints. push ( OverlappingRanges {
251
+ pat,
252
+ overlaps_on : * overlap_range,
253
+ overlaps_with : prefixes. as_slice ( ) . to_vec ( ) ,
254
+ } ) ;
267
255
}
268
- suffixes. push ( this_span )
256
+ suffixes. push ( pat )
269
257
} else if this_range. hi == overlap. plus_one ( ) {
270
258
// `this_range` looks like `this_range.lo..=overlap`; it overlaps with any
271
259
// ranges that look like `overlap..=hi`.
272
260
if !suffixes. is_empty ( ) {
273
- emit_lint ( overlap_range, this_span, & suffixes) ;
261
+ overlapping_range_endpoints. push ( OverlappingRanges {
262
+ pat,
263
+ overlaps_on : * overlap_range,
264
+ overlaps_with : suffixes. as_slice ( ) . to_vec ( ) ,
265
+ } ) ;
274
266
}
275
- prefixes. push ( this_span )
267
+ prefixes. push ( pat )
276
268
}
277
269
}
278
270
}
@@ -281,8 +273,35 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
281
273
// Recurse into the fields.
282
274
for ctor in set. present {
283
275
for col in column. specialize ( pcx, & ctor) {
284
- lint_overlapping_range_endpoints ( cx, & col) ;
276
+ collect_overlapping_range_endpoints ( cx, & col, overlapping_range_endpoints ) ;
285
277
}
286
278
}
287
279
}
288
280
}
281
+
282
+ #[ instrument( level = "debug" , skip( cx) ) ]
283
+ pub ( crate ) fn lint_overlapping_range_endpoints < ' a , ' p , ' tcx > (
284
+ cx : MatchCtxt < ' a , ' p , ' tcx > ,
285
+ column : & PatternColumn < ' p , ' tcx > ,
286
+ ) {
287
+ let mut overlapping_range_endpoints = Vec :: new ( ) ;
288
+ collect_overlapping_range_endpoints ( cx, column, & mut overlapping_range_endpoints) ;
289
+
290
+ let rcx = cx. tycx ;
291
+ for overlap in overlapping_range_endpoints {
292
+ let overlap_as_pat = rcx. hoist_pat_range ( & overlap. overlaps_on , overlap. pat . ty ( ) ) ;
293
+ let overlaps: Vec < _ > = overlap
294
+ . overlaps_with
295
+ . iter ( )
296
+ . map ( |pat| pat. data ( ) . unwrap ( ) . span )
297
+ . map ( |span| Overlap { range : overlap_as_pat. clone ( ) , span } )
298
+ . collect ( ) ;
299
+ let pat_span = overlap. pat . data ( ) . unwrap ( ) . span ;
300
+ rcx. tcx . emit_spanned_lint (
301
+ lint:: builtin:: OVERLAPPING_RANGE_ENDPOINTS ,
302
+ rcx. match_lint_level ,
303
+ pat_span,
304
+ OverlappingRangeEndpoints { overlap : overlaps, range : pat_span } ,
305
+ ) ;
306
+ }
307
+ }
0 commit comments