Skip to content

Commit 447b212

Browse files
committed
Unify expanded constants and named constants in PatKind
1 parent f7179b8 commit 447b212

File tree

18 files changed

+216
-58
lines changed

18 files changed

+216
-58
lines changed

compiler/rustc_middle/src/thir.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ impl<'tcx> Pat<'tcx> {
645645
| Binding { subpattern: Some(subpattern), .. }
646646
| Deref { subpattern }
647647
| DerefPattern { subpattern, .. }
648-
| InlineConstant { subpattern, .. } => subpattern.walk_(it),
648+
| ExpandedConstant { subpattern, .. } => subpattern.walk_(it),
649649
Leaf { subpatterns } | Variant { subpatterns, .. } => {
650650
subpatterns.iter().for_each(|field| field.pattern.walk_(it))
651651
}
@@ -786,16 +786,18 @@ pub enum PatKind<'tcx> {
786786
/// * `String`, if `string_deref_patterns` is enabled.
787787
Constant {
788788
value: mir::Const<'tcx>,
789-
/// The `const` item this constant came from, if any.
790-
opt_def: Option<DefId>,
791789
},
792790

793-
/// Inline constant found while lowering a pattern.
794-
InlineConstant {
795-
/// [LocalDefId] of the constant, we need this so that we have a
791+
/// Inline or named constant found while lowering a pattern.
792+
ExpandedConstant {
793+
/// [DefId] of the constant, we need this so that we have a
796794
/// reference that can be used by unsafety checking to visit nested
797-
/// unevaluated constants.
798-
def: LocalDefId,
795+
/// unevaluated constants. If the `DefId` doesn't correspond to a local
796+
/// crate, it points at the `const` item.
797+
def_id: DefId,
798+
/// If `false`, then `def_id` points at a `const` item, otherwise it
799+
/// corresponds to a local inline const.
800+
is_inline: bool,
799801
/// If the inline constant is used in a range pattern, this subpattern
800802
/// represents the range (if both ends are inline constants, there will
801803
/// be multiple InlineConstant wrappers).
@@ -1086,8 +1088,8 @@ mod size_asserts {
10861088
static_assert_size!(Block, 48);
10871089
static_assert_size!(Expr<'_>, 64);
10881090
static_assert_size!(ExprKind<'_>, 40);
1089-
static_assert_size!(Pat<'_>, 72);
1090-
static_assert_size!(PatKind<'_>, 56);
1091+
static_assert_size!(Pat<'_>, 64);
1092+
static_assert_size!(PatKind<'_>, 48);
10911093
static_assert_size!(Stmt<'_>, 48);
10921094
static_assert_size!(StmtKind<'_>, 48);
10931095
// tidy-alphabetical-end

compiler/rustc_middle/src/thir/visit.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,8 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
246246
visitor.visit_pat(&subpattern.pattern);
247247
}
248248
}
249-
Constant { value: _, opt_def: _ } => {}
250-
InlineConstant { def: _, subpattern } => visitor.visit_pat(subpattern),
249+
Constant { value: _ } => {}
250+
ExpandedConstant { def_id: _, is_inline: _, subpattern } => visitor.visit_pat(subpattern),
251251
Range(_) => {}
252252
Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
253253
for subpattern in prefix.iter() {

compiler/rustc_mir_build/src/build/custom/parse/instruction.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
144144
let mut targets = Vec::new();
145145
for arm in rest {
146146
let arm = &self.thir[*arm];
147-
let PatKind::Constant { value, opt_def: _ } = arm.pattern.kind else {
147+
let PatKind::Constant { value } = arm.pattern.kind else {
148148
return Err(ParseError {
149149
span: arm.pattern.span,
150150
item_description: format!("{:?}", arm.pattern.kind),

compiler/rustc_mir_build/src/build/matches/match_pair.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
129129
}
130130
}
131131

132-
PatKind::Constant { value, opt_def: _ } => TestCase::Constant { value },
132+
PatKind::Constant { value } => TestCase::Constant { value },
133133

134134
PatKind::AscribeUserType {
135135
ascription: thir::Ascription { ref annotation, variance },
@@ -162,7 +162,11 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
162162
TestCase::Irrefutable { ascription: None, binding }
163163
}
164164

165-
PatKind::InlineConstant { subpattern: ref pattern, def, .. } => {
165+
PatKind::ExpandedConstant { subpattern: ref pattern, def_id: _, is_inline: false } => {
166+
subpairs.push(MatchPairTree::for_pattern(place_builder, pattern, cx));
167+
default_irrefutable()
168+
}
169+
PatKind::ExpandedConstant { subpattern: ref pattern, def_id, is_inline: true } => {
166170
// Apply a type ascription for the inline constant to the value at `match_pair.place`
167171
let ascription = place.map(|source| {
168172
let span = pattern.span;
@@ -173,7 +177,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
173177
})
174178
.args;
175179
let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf(
176-
def.to_def_id(),
180+
def_id,
177181
ty::UserArgs { args, user_self_ty: None },
178182
));
179183
let annotation = ty::CanonicalUserTypeAnnotation {

compiler/rustc_mir_build/src/build/matches/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
917917
self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
918918
}
919919

920-
PatKind::InlineConstant { ref subpattern, .. } => {
920+
PatKind::ExpandedConstant { ref subpattern, .. } => {
921921
self.visit_primary_bindings(subpattern, pattern_user_ty, f)
922922
}
923923

compiler/rustc_mir_build/src/check_unsafety.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
332332
PatKind::Wild |
333333
// these just wrap other patterns, which we recurse on below.
334334
PatKind::Or { .. } |
335-
PatKind::InlineConstant { .. } |
335+
PatKind::ExpandedConstant { .. } |
336336
PatKind::AscribeUserType { .. } |
337337
PatKind::Error(_) => {}
338338
}
@@ -386,8 +386,12 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
386386
visit::walk_pat(self, pat);
387387
self.inside_adt = old_inside_adt;
388388
}
389-
PatKind::InlineConstant { def, .. } => {
390-
self.visit_inner_body(*def);
389+
PatKind::ExpandedConstant { def_id, is_inline, .. } => {
390+
if let Some(def) = def_id.as_local()
391+
&& *is_inline
392+
{
393+
self.visit_inner_body(def);
394+
}
391395
visit::walk_pat(self, pat);
392396
}
393397
_ => {

compiler/rustc_mir_build/src/errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,7 @@ impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> {
914914
mir_build_interpreted_as_const,
915915
code = "{variable}_var",
916916
applicability = "maybe-incorrect"
917+
// style = "verbose"
917918
)]
918919
pub(crate) struct InterpretedAsConst {
919920
#[primary_span]

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -670,11 +670,13 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
670670
let mut interpreted_as_const = None;
671671
let mut interpreted_as_const_sugg = None;
672672

673-
if let PatKind::Constant { opt_def: Some(def_id), .. }
673+
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. }
674674
| PatKind::AscribeUserType {
675-
subpattern: box Pat { kind: PatKind::Constant { opt_def: Some(def_id), .. }, .. },
675+
subpattern:
676+
box Pat { kind: PatKind::ExpandedConstant { def_id, is_inline: false, .. }, .. },
676677
..
677678
} = pat.kind
679+
&& let DefKind::Const = self.tcx.def_kind(def_id)
678680
{
679681
let span = self.tcx.def_span(def_id);
680682
let variable = self.tcx.item_name(def_id).to_string();
@@ -1145,7 +1147,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
11451147

11461148
for &arm in arms {
11471149
let arm = &thir.arms[arm];
1148-
if let PatKind::Constant { opt_def: Some(def_id), .. } = arm.pattern.kind {
1150+
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = arm.pattern.kind {
11491151
let const_name = cx.tcx.item_name(def_id);
11501152
err.span_label(
11511153
arm.pattern.span,

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

+1-6
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ impl<'tcx> ConstToPat<'tcx> {
248248
// optimization for now.
249249
ty::Str => PatKind::Constant {
250250
value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
251-
opt_def: None,
252251
},
253252
// All other references are converted into deref patterns and then recursively
254253
// convert the dereferenced constant to a pattern that is the sub-pattern of the
@@ -294,17 +293,13 @@ impl<'tcx> ConstToPat<'tcx> {
294293
} else {
295294
PatKind::Constant {
296295
value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
297-
opt_def: None,
298296
}
299297
}
300298
}
301299
ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
302300
// The raw pointers we see here have been "vetted" by valtree construction to be
303301
// just integers, so we simply allow them.
304-
PatKind::Constant {
305-
value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
306-
opt_def: None,
307-
}
302+
PatKind::Constant { value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)) }
308303
}
309304
ty::FnPtr(..) => {
310305
unreachable!(

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

+27-10
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,18 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
149149
None => Ok((None, None, None)),
150150
Some(expr) => {
151151
let (kind, ascr, inline_const) = match self.lower_lit(expr) {
152-
PatKind::InlineConstant { subpattern, def } => {
153-
(subpattern.kind, None, Some(def))
152+
PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => {
153+
(subpattern.kind, None, def_id.as_local())
154+
}
155+
PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => {
156+
(subpattern.kind, None, None)
154157
}
155158
PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => {
156159
(kind, Some(ascription), None)
157160
}
158161
kind => (kind, None, None),
159162
};
160-
let value = if let PatKind::Constant { value, opt_def: _ } = kind {
163+
let value = if let PatKind::Constant { value } = kind {
161164
value
162165
} else {
163166
let msg = format!(
@@ -251,7 +254,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
251254
(RangeEnd::Included, Some(Ordering::Less)) => {}
252255
// `x..=y` where `x == y` and `x` and `y` are finite.
253256
(RangeEnd::Included, Some(Ordering::Equal)) if lo.is_finite() && hi.is_finite() => {
254-
kind = PatKind::Constant { value: lo.as_finite().unwrap(), opt_def: None };
257+
kind = PatKind::Constant { value: lo.as_finite().unwrap() };
255258
}
256259
// `..=x` where `x == ty::MIN`.
257260
(RangeEnd::Included, Some(Ordering::Equal)) if !lo.is_finite() => {}
@@ -288,7 +291,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
288291
};
289292
}
290293
for def in [lo_inline, hi_inline].into_iter().flatten() {
291-
kind = PatKind::InlineConstant { def, subpattern: Box::new(Pat { span, ty, kind }) };
294+
kind = PatKind::ExpandedConstant {
295+
def_id: def.to_def_id(),
296+
is_inline: true,
297+
subpattern: Box::new(Pat { span, ty, kind }),
298+
};
292299
}
293300
Ok(kind)
294301
}
@@ -562,10 +569,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
562569

563570
let args = self.typeck_results.node_args(id);
564571
let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
565-
let mut pattern = self.const_to_pat(c, ty, id, span);
566-
if let PatKind::Constant { value, opt_def: None } = pattern.kind {
567-
pattern.kind = PatKind::Constant { value, opt_def: Some(def_id) };
568-
}
572+
let subpattern = self.const_to_pat(c, ty, id, span);
573+
let pattern = if let hir::QPath::Resolved(None, path) = qpath
574+
&& path.segments.len() == 1
575+
{
576+
// We only want to mark constants when referenced as bare names that could have been
577+
// new bindings if the `const` didn't exist.
578+
Box::new(Pat {
579+
span,
580+
ty,
581+
kind: PatKind::ExpandedConstant { subpattern, def_id, is_inline: false },
582+
})
583+
} else {
584+
subpattern
585+
};
569586

570587
if !is_associated_const {
571588
return pattern;
@@ -640,7 +657,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
640657

641658
let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
642659
let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span);
643-
PatKind::InlineConstant { subpattern, def: def_id }
660+
PatKind::ExpandedConstant { subpattern, def_id: def_id.to_def_id(), is_inline: true }
644661
}
645662

646663
/// Converts literals, paths and negation of literals to patterns.

compiler/rustc_mir_build/src/thir/print.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -702,14 +702,15 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
702702
self.print_pat(subpattern, depth_lvl + 2);
703703
print_indented!(self, "}", depth_lvl + 1);
704704
}
705-
PatKind::Constant { value, opt_def: _ } => {
705+
PatKind::Constant { value } => {
706706
print_indented!(self, "Constant {", depth_lvl + 1);
707707
print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
708708
print_indented!(self, "}", depth_lvl + 1);
709709
}
710-
PatKind::InlineConstant { def, subpattern } => {
711-
print_indented!(self, "InlineConstant {", depth_lvl + 1);
712-
print_indented!(self, format!("def: {:?}", def), depth_lvl + 2);
710+
PatKind::ExpandedConstant { def_id, is_inline, subpattern } => {
711+
print_indented!(self, "ExpandedConstant {", depth_lvl + 1);
712+
print_indented!(self, format!("def_id: {def_id:?}"), depth_lvl + 2);
713+
print_indented!(self, format!("is_inline: {is_inline:?}"), depth_lvl + 2);
713714
print_indented!(self, "subpattern:", depth_lvl + 2);
714715
self.print_pat(subpattern, depth_lvl + 2);
715716
print_indented!(self, "}", depth_lvl + 1);

compiler/rustc_pattern_analysis/src/rustc.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
453453
let fields: Vec<_>;
454454
match &pat.kind {
455455
PatKind::AscribeUserType { subpattern, .. }
456-
| PatKind::InlineConstant { subpattern, .. } => return self.lower_pat(subpattern),
456+
| PatKind::ExpandedConstant { subpattern, .. } => return self.lower_pat(subpattern),
457457
PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
458458
PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
459459
ctor = Wildcard;
@@ -536,7 +536,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
536536
),
537537
}
538538
}
539-
PatKind::Constant { value, opt_def: _ } => {
539+
PatKind::Constant { value } => {
540540
match ty.kind() {
541541
ty::Bool => {
542542
ctor = match value.try_eval_bool(cx.tcx, cx.param_env) {

compiler/rustc_ty_utils/src/consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
370370
}
371371

372372
match pat.kind {
373-
thir::PatKind::Constant { value, opt_def: _ } => value.has_non_region_param(),
373+
thir::PatKind::Constant { value } => value.has_non_region_param(),
374374
thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => {
375375
lo.has_non_region_param() || hi.has_non_region_param()
376376
}

tests/ui/consts/const-pattern-irrefutable.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
mod foo {
22
pub const b: u8 = 2;
33
//~^ missing patterns are not covered because `b` is interpreted as a constant pattern, not a new variable
4-
pub const d: u8 = 2;
4+
pub const d: (u8, u8) = (2, 1);
55
//~^ missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
66
}
77

@@ -11,6 +11,15 @@ use foo::d;
1111
const a: u8 = 2;
1212
//~^ missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
1313

14+
#[derive(PartialEq)]
15+
struct S {
16+
foo: u8,
17+
}
18+
19+
const e: S = S {
20+
foo: 0,
21+
};
22+
1423
fn main() {
1524
let a = 4;
1625
//~^ ERROR refutable pattern in local binding
@@ -20,9 +29,15 @@ fn main() {
2029
//~^ ERROR refutable pattern in local binding
2130
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
2231
//~| HELP introduce a variable instead
23-
let d = 4;
32+
let d = (4, 4);
2433
//~^ ERROR refutable pattern in local binding
25-
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
34+
//~| patterns `(0_u8..=1_u8, _)` and `(3_u8..=u8::MAX, _)` not covered
35+
//~| HELP introduce a variable instead
36+
let e = S {
37+
//~^ ERROR refutable pattern in local binding
38+
//~| pattern `S { foo: 1_u8..=u8::MAX }` not covered
2639
//~| HELP introduce a variable instead
40+
foo: 1,
41+
};
2742
fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
2843
}

0 commit comments

Comments
 (0)