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