|
1 |
| -use smallvec::SmallVec; |
2 |
| - |
3 |
| -use rustc_data_structures::captures::Captures; |
4 |
| -use rustc_middle::ty::{self, Ty}; |
| 1 | +use rustc_middle::ty::Ty; |
5 | 2 | use rustc_session::lint;
|
6 | 3 | use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
7 |
| -use rustc_span::Span; |
8 | 4 |
|
9 |
| -use crate::constructor::{IntRange, MaybeInfiniteInt}; |
10 | 5 | use crate::errors::{
|
11 | 6 | NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Overlap,
|
12 | 7 | OverlappingRangeEndpoints, Uncovered,
|
13 | 8 | };
|
14 | 9 | use crate::rustc::{
|
15 |
| - Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RustcMatchCheckCtxt, |
| 10 | + self, Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RustcMatchCheckCtxt, |
16 | 11 | SplitConstructorSet, WitnessPat,
|
17 | 12 | };
|
18 | 13 | use crate::TypeCx;
|
@@ -64,10 +59,6 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
|
64 | 59 | pcx.ctors_for_ty().split(pcx, column_ctors)
|
65 | 60 | }
|
66 | 61 |
|
67 |
| - fn iter(&self) -> impl Iterator<Item = &'p DeconstructedPat<'p, 'tcx>> + Captures<'_> { |
68 |
| - self.patterns.iter().copied() |
69 |
| - } |
70 |
| - |
71 | 62 | /// Does specialization: given a constructor, this takes the patterns from the column that match
|
72 | 63 | /// the constructor, and outputs their fields.
|
73 | 64 | /// This returns one column per field of the constructor. They usually all have the same length
|
@@ -212,77 +203,25 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
|
212 | 203 | }
|
213 | 204 | }
|
214 | 205 |
|
215 |
| -/// Traverse the patterns to warn the user about ranges that overlap on their endpoints. |
216 |
| -#[instrument(level = "debug", skip(cx))] |
217 | 206 | pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
|
218 | 207 | cx: MatchCtxt<'a, 'p, 'tcx>,
|
219 |
| - column: &PatternColumn<'p, 'tcx>, |
| 208 | + overlapping_range_endpoints: &[rustc::OverlappingRanges<'p, 'tcx>], |
220 | 209 | ) {
|
221 |
| - let Some(ty) = column.head_ty(cx) else { |
222 |
| - return; |
223 |
| - }; |
224 |
| - let pcx = &PlaceCtxt::new_dummy(cx, ty); |
225 |
| - let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx; |
226 |
| - |
227 |
| - let set = column.analyze_ctors(pcx); |
228 |
| - |
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 |
| - // If two ranges overlapped, the split set will contain their intersection as a singleton. |
246 |
| - let split_int_ranges = set.present.iter().filter_map(|c| c.as_int_range()); |
247 |
| - for overlap_range in split_int_ranges.clone() { |
248 |
| - if overlap_range.is_singleton() { |
249 |
| - let overlap: MaybeInfiniteInt = overlap_range.lo; |
250 |
| - // Ranges that look like `lo..=overlap`. |
251 |
| - let mut prefixes: SmallVec<[_; 1]> = Default::default(); |
252 |
| - // Ranges that look like `overlap..=hi`. |
253 |
| - let mut suffixes: SmallVec<[_; 1]> = Default::default(); |
254 |
| - // Iterate on patterns that contained `overlap`. |
255 |
| - for pat in column.iter() { |
256 |
| - let Constructor::IntRange(this_range) = pat.ctor() else { continue }; |
257 |
| - let this_span = pat.data().unwrap().span; |
258 |
| - if this_range.is_singleton() { |
259 |
| - // Don't lint when one of the ranges is a singleton. |
260 |
| - continue; |
261 |
| - } |
262 |
| - if this_range.lo == overlap { |
263 |
| - // `this_range` looks like `overlap..=this_range.hi`; it overlaps with any |
264 |
| - // ranges that look like `lo..=overlap`. |
265 |
| - if !prefixes.is_empty() { |
266 |
| - emit_lint(overlap_range, this_span, &prefixes); |
267 |
| - } |
268 |
| - suffixes.push(this_span) |
269 |
| - } else if this_range.hi == overlap.plus_one() { |
270 |
| - // `this_range` looks like `this_range.lo..=overlap`; it overlaps with any |
271 |
| - // ranges that look like `overlap..=hi`. |
272 |
| - if !suffixes.is_empty() { |
273 |
| - emit_lint(overlap_range, this_span, &suffixes); |
274 |
| - } |
275 |
| - prefixes.push(this_span) |
276 |
| - } |
277 |
| - } |
278 |
| - } |
279 |
| - } |
280 |
| - } else { |
281 |
| - // Recurse into the fields. |
282 |
| - for ctor in set.present { |
283 |
| - for col in column.specialize(pcx, &ctor) { |
284 |
| - lint_overlapping_range_endpoints(cx, &col); |
285 |
| - } |
286 |
| - } |
| 210 | + let rcx = cx.tycx; |
| 211 | + for overlap in overlapping_range_endpoints { |
| 212 | + let overlap_as_pat = rcx.hoist_pat_range(&overlap.overlaps_on, overlap.pat.ty()); |
| 213 | + let overlaps: Vec<_> = overlap |
| 214 | + .overlaps_with |
| 215 | + .iter() |
| 216 | + .map(|pat| pat.data().unwrap().span) |
| 217 | + .map(|span| Overlap { range: overlap_as_pat.clone(), span }) |
| 218 | + .collect(); |
| 219 | + let pat_span = overlap.pat.data().unwrap().span; |
| 220 | + rcx.tcx.emit_spanned_lint( |
| 221 | + lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, |
| 222 | + rcx.match_lint_level, |
| 223 | + pat_span, |
| 224 | + OverlappingRangeEndpoints { overlap: overlaps, range: pat_span }, |
| 225 | + ); |
287 | 226 | }
|
288 | 227 | }
|
0 commit comments