|
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