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