Skip to content

Commit bdd2bdb

Browse files
committed
Don't store ty and span in IntRange
We prefer to grab `ty` and `span` from `pcx`. This makes it consistent with other constructors.
1 parent d898365 commit bdd2bdb

File tree

2 files changed

+56
-66
lines changed

2 files changed

+56
-66
lines changed

compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

+46-64
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,12 @@ use std::ops::RangeInclusive;
3737
///
3838
/// `IntRange` is never used to encode an empty range or a "range" that wraps
3939
/// around the (offset) space: i.e., `range.lo <= range.hi`.
40-
#[derive(Clone, Debug)]
41-
pub(super) struct IntRange<'tcx> {
40+
#[derive(Clone, Debug, PartialEq, Eq)]
41+
pub(super) struct IntRange {
4242
range: RangeInclusive<u128>,
43-
ty: Ty<'tcx>,
44-
span: Span,
4543
}
4644

47-
impl<'tcx> IntRange<'tcx> {
45+
impl IntRange {
4846
#[inline]
4947
fn is_integral(ty: Ty<'_>) -> bool {
5048
matches!(ty.kind(), ty::Char | ty::Int(_) | ty::Uint(_) | ty::Bool)
@@ -59,7 +57,7 @@ impl<'tcx> IntRange<'tcx> {
5957
}
6058

6159
#[inline]
62-
fn integral_size_and_signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'_>) -> Option<(Size, u128)> {
60+
fn integral_size_and_signed_bias(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Size, u128)> {
6361
match *ty.kind() {
6462
ty::Bool => Some((Size::from_bytes(1), 0)),
6563
ty::Char => Some((Size::from_bytes(4), 0)),
@@ -73,12 +71,11 @@ impl<'tcx> IntRange<'tcx> {
7371
}
7472

7573
#[inline]
76-
fn from_const(
74+
fn from_const<'tcx>(
7775
tcx: TyCtxt<'tcx>,
7876
param_env: ty::ParamEnv<'tcx>,
7977
value: &Const<'tcx>,
80-
span: Span,
81-
) -> Option<IntRange<'tcx>> {
78+
) -> Option<IntRange> {
8279
if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, value.ty) {
8380
let ty = value.ty;
8481
let val = (|| {
@@ -95,21 +92,20 @@ impl<'tcx> IntRange<'tcx> {
9592
value.try_eval_bits(tcx, param_env, ty)
9693
})()?;
9794
let val = val ^ bias;
98-
Some(IntRange { range: val..=val, ty, span })
95+
Some(IntRange { range: val..=val })
9996
} else {
10097
None
10198
}
10299
}
103100

104101
#[inline]
105-
fn from_range(
102+
fn from_range<'tcx>(
106103
tcx: TyCtxt<'tcx>,
107104
lo: u128,
108105
hi: u128,
109106
ty: Ty<'tcx>,
110107
end: &RangeEnd,
111-
span: Span,
112-
) -> Option<IntRange<'tcx>> {
108+
) -> Option<IntRange> {
113109
if Self::is_integral(ty) {
114110
// Perform a shift if the underlying types are signed,
115111
// which makes the interval arithmetic simpler.
@@ -120,14 +116,14 @@ impl<'tcx> IntRange<'tcx> {
120116
// This should have been caught earlier by E0030.
121117
bug!("malformed range pattern: {}..={}", lo, (hi - offset));
122118
}
123-
Some(IntRange { range: lo..=(hi - offset), ty, span })
119+
Some(IntRange { range: lo..=(hi - offset) })
124120
} else {
125121
None
126122
}
127123
}
128124

129125
// The return value of `signed_bias` should be XORed with an endpoint to encode/decode it.
130-
fn signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u128 {
126+
fn signed_bias(tcx: TyCtxt<'_>, ty: Ty<'_>) -> u128 {
131127
match *ty.kind() {
132128
ty::Int(ity) => {
133129
let bits = Integer::from_attr(&tcx, SignedInt(ity)).size().bits() as u128;
@@ -142,12 +138,10 @@ impl<'tcx> IntRange<'tcx> {
142138
}
143139

144140
fn intersection(&self, other: &Self) -> Option<Self> {
145-
let ty = self.ty;
146141
let (lo, hi) = self.boundaries();
147142
let (other_lo, other_hi) = other.boundaries();
148143
if lo <= other_hi && other_lo <= hi {
149-
let span = other.span;
150-
Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span })
144+
Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi) })
151145
} else {
152146
None
153147
}
@@ -170,24 +164,23 @@ impl<'tcx> IntRange<'tcx> {
170164
lo == other_hi || hi == other_lo
171165
}
172166

173-
fn to_pat(&self, tcx: TyCtxt<'tcx>) -> Pat<'tcx> {
167+
fn to_pat<'tcx>(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Pat<'tcx> {
174168
let (lo, hi) = self.boundaries();
175169

176-
let bias = IntRange::signed_bias(tcx, self.ty);
170+
let bias = IntRange::signed_bias(tcx, ty);
177171
let (lo, hi) = (lo ^ bias, hi ^ bias);
178172

179-
let ty = ty::ParamEnv::empty().and(self.ty);
180-
let lo_const = ty::Const::from_bits(tcx, lo, ty);
181-
let hi_const = ty::Const::from_bits(tcx, hi, ty);
173+
let env = ty::ParamEnv::empty().and(ty);
174+
let lo_const = ty::Const::from_bits(tcx, lo, env);
175+
let hi_const = ty::Const::from_bits(tcx, hi, env);
182176

183177
let kind = if lo == hi {
184178
PatKind::Constant { value: lo_const }
185179
} else {
186180
PatKind::Range(PatRange { lo: lo_const, hi: hi_const, end: RangeEnd::Included })
187181
};
188182

189-
// This is a brand new pattern, so we don't reuse `self.span`.
190-
Pat { ty: self.ty, span: DUMMY_SP, kind: Box::new(kind) }
183+
Pat { ty, span: DUMMY_SP, kind: Box::new(kind) }
191184
}
192185

193186
/// For exhaustive integer matching, some constructors are grouped within other constructors
@@ -222,13 +215,11 @@ impl<'tcx> IntRange<'tcx> {
222215
/// boundaries for each interval range, sort them, then create constructors for each new interval
223216
/// between every pair of boundary points. (This essentially sums up to performing the intuitive
224217
/// merging operation depicted above.)
225-
fn split<'p>(
218+
fn split<'p, 'tcx>(
226219
&self,
227220
pcx: PatCtxt<'_, 'p, 'tcx>,
228221
hir_id: Option<HirId>,
229222
) -> SmallVec<[Constructor<'tcx>; 1]> {
230-
let ty = pcx.ty;
231-
232223
/// Represents a border between 2 integers. Because the intervals spanning borders
233224
/// must be able to cover every integer, we need to be able to represent
234225
/// 2^128 + 1 such borders.
@@ -239,7 +230,7 @@ impl<'tcx> IntRange<'tcx> {
239230
}
240231

241232
// A function for extracting the borders of an integer interval.
242-
fn range_borders(r: IntRange<'_>) -> impl Iterator<Item = Border> {
233+
fn range_borders(r: IntRange) -> impl Iterator<Item = Border> {
243234
let (lo, hi) = r.range.into_inner();
244235
let from = Border::JustBefore(lo);
245236
let to = match hi.checked_add(1) {
@@ -257,21 +248,23 @@ impl<'tcx> IntRange<'tcx> {
257248
// class lies between 2 borders.
258249
let row_borders = pcx
259250
.matrix
260-
.head_ctors(pcx.cx)
261-
.filter_map(|ctor| ctor.as_int_range())
262-
.filter_map(|range| {
251+
.head_ctors_and_spans(pcx.cx)
252+
.filter_map(|(ctor, span)| Some((ctor.as_int_range()?, span)))
253+
.filter_map(|(range, span)| {
263254
let intersection = self.intersection(&range);
264255
let should_lint = self.suspicious_intersection(&range);
265256
if let (Some(range), 1, true) = (&intersection, row_len, should_lint) {
266257
// FIXME: for now, only check for overlapping ranges on simple range
267258
// patterns. Otherwise with the current logic the following is detected
268259
// as overlapping:
269-
// match (10u8, true) {
270-
// (0 ..= 125, false) => {}
271-
// (126 ..= 255, false) => {}
272-
// (0 ..= 255, true) => {}
273-
// }
274-
overlaps.push(range.clone());
260+
// ```
261+
// match (0u8, true) {
262+
// (0 ..= 125, false) => {}
263+
// (125 ..= 255, true) => {}
264+
// _ => {}
265+
// }
266+
// ```
267+
overlaps.push((range.clone(), span));
275268
}
276269
intersection
277270
})
@@ -280,7 +273,7 @@ impl<'tcx> IntRange<'tcx> {
280273
let mut borders: Vec<_> = row_borders.chain(self_borders).collect();
281274
borders.sort_unstable();
282275

283-
self.lint_overlapping_patterns(pcx.cx.tcx, hir_id, ty, overlaps);
276+
self.lint_overlapping_patterns(pcx, hir_id, overlaps);
284277

285278
// We're going to iterate through every adjacent pair of borders, making sure that
286279
// each represents an interval of nonnegative length, and convert each such
@@ -298,33 +291,32 @@ impl<'tcx> IntRange<'tcx> {
298291
[Border::JustBefore(n), Border::AfterMax] => Some(n..=u128::MAX),
299292
[Border::AfterMax, _] => None,
300293
})
301-
.map(|range| IntRange { range, ty, span: pcx.span })
294+
.map(|range| IntRange { range })
302295
.map(IntRange)
303296
.collect()
304297
}
305298

306299
fn lint_overlapping_patterns(
307300
&self,
308-
tcx: TyCtxt<'tcx>,
301+
pcx: PatCtxt<'_, '_, '_>,
309302
hir_id: Option<HirId>,
310-
ty: Ty<'tcx>,
311-
overlaps: Vec<IntRange<'tcx>>,
303+
overlaps: Vec<(IntRange, Span)>,
312304
) {
313305
if let (true, Some(hir_id)) = (!overlaps.is_empty(), hir_id) {
314-
tcx.struct_span_lint_hir(
306+
pcx.cx.tcx.struct_span_lint_hir(
315307
lint::builtin::OVERLAPPING_PATTERNS,
316308
hir_id,
317-
self.span,
309+
pcx.span,
318310
|lint| {
319311
let mut err = lint.build("multiple patterns covering the same range");
320-
err.span_label(self.span, "overlapping patterns");
321-
for int_range in overlaps {
312+
err.span_label(pcx.span, "overlapping patterns");
313+
for (int_range, span) in overlaps {
322314
// Use the real type for user display of the ranges:
323315
err.span_label(
324-
int_range.span,
316+
span,
325317
&format!(
326318
"this range overlaps on `{}`",
327-
IntRange { range: int_range.range, ty, span: DUMMY_SP }.to_pat(tcx),
319+
int_range.to_pat(pcx.cx.tcx, pcx.ty),
328320
),
329321
);
330322
}
@@ -347,13 +339,6 @@ impl<'tcx> IntRange<'tcx> {
347339
}
348340
}
349341

350-
/// Ignore spans when comparing, they don't carry semantic information as they are only for lints.
351-
impl<'tcx> std::cmp::PartialEq for IntRange<'tcx> {
352-
fn eq(&self, other: &Self) -> bool {
353-
self.range == other.range && self.ty == other.ty
354-
}
355-
}
356-
357342
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
358343
enum SliceKind {
359344
/// Patterns of length `n` (`[x, y]`).
@@ -547,7 +532,7 @@ pub(super) enum Constructor<'tcx> {
547532
/// Enum variants.
548533
Variant(DefId),
549534
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
550-
IntRange(IntRange<'tcx>),
535+
IntRange(IntRange),
551536
/// Ranges of floating-point literal values (`2.0..=5.2`).
552537
FloatRange(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>, RangeEnd),
553538
/// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
@@ -570,7 +555,7 @@ impl<'tcx> Constructor<'tcx> {
570555
matches!(self, Wildcard)
571556
}
572557

573-
fn as_int_range(&self) -> Option<&IntRange<'tcx>> {
558+
fn as_int_range(&self) -> Option<&IntRange> {
574559
match self {
575560
IntRange(range) => Some(range),
576561
_ => None,
@@ -605,8 +590,7 @@ impl<'tcx> Constructor<'tcx> {
605590
Variant(adt_def.variants[variant_index].def_id)
606591
}
607592
PatKind::Constant { value } => {
608-
if let Some(int_range) = IntRange::from_const(cx.tcx, cx.param_env, value, pat.span)
609-
{
593+
if let Some(int_range) = IntRange::from_const(cx.tcx, cx.param_env, value) {
610594
IntRange(int_range)
611595
} else {
612596
match pat.ty.kind() {
@@ -630,7 +614,6 @@ impl<'tcx> Constructor<'tcx> {
630614
hi.eval_bits(cx.tcx, cx.param_env, hi.ty),
631615
ty,
632616
&end,
633-
pat.span,
634617
) {
635618
IntRange(int_range)
636619
} else {
@@ -815,8 +798,7 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
815798
let make_range = |start, end| {
816799
IntRange(
817800
// `unwrap()` is ok because we know the type is an integer.
818-
IntRange::from_range(cx.tcx, start, end, pcx.ty, &RangeEnd::Included, pcx.span)
819-
.unwrap(),
801+
IntRange::from_range(cx.tcx, start, end, pcx.ty, &RangeEnd::Included).unwrap(),
820802
)
821803
};
822804
match pcx.ty.kind() {
@@ -1221,7 +1203,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12211203
},
12221204
&Str(value) => PatKind::Constant { value },
12231205
&FloatRange(lo, hi, end) => PatKind::Range(PatRange { lo, hi, end }),
1224-
IntRange(range) => return range.to_pat(pcx.cx.tcx),
1206+
IntRange(range) => return range.to_pat(pcx.cx.tcx, pcx.ty),
12251207
NonExhaustive => PatKind::Wild,
12261208
Opaque => bug!("we should not try to apply an opaque constructor"),
12271209
Wildcard => bug!(

compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -535,14 +535,22 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
535535
self.patterns.iter().map(|r| r.head())
536536
}
537537

538-
/// Iterate over the first constructor of each row
538+
/// Iterate over the first constructor of each row.
539539
pub(super) fn head_ctors<'a>(
540540
&'a self,
541541
cx: &'a MatchCheckCtxt<'p, 'tcx>,
542-
) -> impl Iterator<Item = &'a Constructor<'tcx>> + Captures<'a> + Captures<'p> {
542+
) -> impl Iterator<Item = &'a Constructor<'tcx>> + Captures<'p> {
543543
self.patterns.iter().map(move |r| r.head_ctor(cx))
544544
}
545545

546+
/// Iterate over the first constructor and the corresponding span of each row.
547+
pub(super) fn head_ctors_and_spans<'a>(
548+
&'a self,
549+
cx: &'a MatchCheckCtxt<'p, 'tcx>,
550+
) -> impl Iterator<Item = (&'a Constructor<'tcx>, Span)> + Captures<'p> {
551+
self.patterns.iter().map(move |r| (r.head_ctor(cx), r.head().span))
552+
}
553+
546554
/// This computes `S(constructor, self)`. See top of the file for explanations.
547555
fn specialize_constructor(
548556
&self,

0 commit comments

Comments
 (0)