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