Skip to content

Commit 3e1a6df

Browse files
committed
Split thir::PatKind::ExpandedConstant into two distinct kinds
These two kinds of marker node are superficially similar, but are actually very different in practice, and there is no code that actually wants to treat them as the same thing.
1 parent 8a8b464 commit 3e1a6df

File tree

10 files changed

+82
-57
lines changed

10 files changed

+82
-57
lines changed

compiler/rustc_middle/src/thir.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -678,11 +678,14 @@ impl<'tcx> Pat<'tcx> {
678678
| Binding { subpattern: None, .. }
679679
| Constant { .. }
680680
| Error(_) => {}
681+
681682
AscribeUserType { subpattern, .. }
682683
| Binding { subpattern: Some(subpattern), .. }
683684
| Deref { subpattern }
684685
| DerefPattern { subpattern, .. }
685-
| ExpandedConstant { subpattern, .. } => subpattern.walk_(it),
686+
| InlineConstMarker { subpattern, .. }
687+
| NamedConstMarker { subpattern, .. } => subpattern.walk_(it),
688+
686689
Leaf { subpatterns } | Variant { subpatterns, .. } => {
687690
subpatterns.iter().for_each(|field| field.pattern.walk_(it))
688691
}
@@ -825,24 +828,29 @@ pub enum PatKind<'tcx> {
825828
value: mir::Const<'tcx>,
826829
},
827830

828-
/// Pattern obtained by converting a constant (inline or named) to its pattern
829-
/// representation using `const_to_pat`.
830-
ExpandedConstant {
831-
/// [DefId] of the constant, we need this so that we have a
832-
/// reference that can be used by unsafety checking to visit nested
833-
/// unevaluated constants and for diagnostics. If the `DefId` doesn't
834-
/// correspond to a local crate, it points at the `const` item.
831+
/// Marker node that wraps a pattern representing an inline-const block.
832+
///
833+
/// THIR unsafeck uses this marker to discover inline-const blocks that
834+
/// appear in patterns, so that they can be checked together with the rest
835+
/// of their enclosing body.
836+
///
837+
/// Note that if a range pattern has inline-const blocks for both endpoints,
838+
/// the resulting THIR pattern will be an `InlineConstMarker`, containing
839+
/// another `InlineConstMarker`, containing the underlying `Range` pattern.
840+
InlineConstMarker {
841+
/// ID of the inline-const block, for use by THIR unsafeck.
842+
def_id: LocalDefId,
843+
subpattern: Box<Pat<'tcx>>,
844+
},
845+
846+
/// Marker node that wraps a pattern representing a named constant.
847+
/// Enables better diagnostics in some cases, but has no other significance.
848+
///
849+
/// (Even though this is superficially similar to `InlineConstMarker`, they
850+
/// are very different in actual usage, so they should be kept separate.)
851+
NamedConstMarker {
852+
/// ID of the named constant, for use by diagnostics.
835853
def_id: DefId,
836-
/// If `false`, then `def_id` points at a `const` item, otherwise it
837-
/// corresponds to a local inline const.
838-
is_inline: bool,
839-
/// If the inline constant is used in a range pattern, this subpattern
840-
/// represents the range (if both ends are inline constants, there will
841-
/// be multiple InlineConstant wrappers).
842-
///
843-
/// Otherwise, the actual pattern that the constant lowered to. As with
844-
/// other constants, inline constants are matched structurally where
845-
/// possible.
846854
subpattern: Box<Pat<'tcx>>,
847855
},
848856

compiler/rustc_middle/src/thir/visit.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,15 +243,17 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
243243
AscribeUserType { subpattern, ascription: _ }
244244
| Deref { subpattern }
245245
| DerefPattern { subpattern, .. }
246-
| Binding { subpattern: Some(subpattern), .. } => visitor.visit_pat(subpattern),
246+
| Binding { subpattern: Some(subpattern), .. }
247+
| InlineConstMarker { subpattern, .. }
248+
| NamedConstMarker { subpattern, .. } => visitor.visit_pat(subpattern),
249+
247250
Binding { .. } | Wild | Never | Error(_) => {}
248251
Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => {
249252
for subpattern in subpatterns {
250253
visitor.visit_pat(&subpattern.pattern);
251254
}
252255
}
253256
Constant { value: _ } => {}
254-
ExpandedConstant { def_id: _, is_inline: _, subpattern } => visitor.visit_pat(subpattern),
255257
Range(_) => {}
256258
Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
257259
for subpattern in prefix.iter() {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
146146
let arm = &self.thir[*arm];
147147
let value = match arm.pattern.kind {
148148
PatKind::Constant { value } => value,
149-
PatKind::ExpandedConstant { ref subpattern, def_id: _, is_inline: false }
149+
PatKind::NamedConstMarker { ref subpattern, def_id: _ }
150150
if let PatKind::Constant { value } = subpattern.kind =>
151151
{
152152
value

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,11 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
162162
TestCase::Irrefutable { ascription: None, binding }
163163
}
164164

165-
PatKind::ExpandedConstant { subpattern: ref pattern, def_id: _, is_inline: false } => {
165+
PatKind::NamedConstMarker { subpattern: ref pattern, def_id: _ } => {
166166
subpairs.push(MatchPairTree::for_pattern(place_builder, pattern, cx));
167167
default_irrefutable()
168168
}
169-
PatKind::ExpandedConstant { subpattern: ref pattern, def_id, is_inline: true } => {
169+
PatKind::InlineConstMarker { subpattern: ref pattern, def_id } => {
170170
// Apply a type ascription for the inline constant to the value at `match_pair.place`
171171
let ascription = place.map(|source| {
172172
let span = pattern.span;
@@ -177,7 +177,10 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
177177
})
178178
.args;
179179
let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::new(
180-
ty::UserTypeKind::TypeOf(def_id, ty::UserArgs { args, user_self_ty: None }),
180+
ty::UserTypeKind::TypeOf(def_id.to_def_id(), ty::UserArgs {
181+
args,
182+
user_self_ty: None,
183+
}),
181184
));
182185
let annotation = ty::CanonicalUserTypeAnnotation {
183186
inferred_ty: pattern.ty,

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
925925
self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
926926
}
927927

928-
PatKind::ExpandedConstant { ref subpattern, .. } => {
928+
PatKind::InlineConstMarker { ref subpattern, .. }
929+
| PatKind::NamedConstMarker { ref subpattern, .. } => {
929930
self.visit_primary_bindings(subpattern, pattern_user_ty, f)
930931
}
931932

compiler/rustc_mir_build/src/check_unsafety.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,8 @@ 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::ExpandedConstant { .. } |
335+
PatKind::InlineConstMarker { .. } |
336+
PatKind::NamedConstMarker { .. } |
336337
PatKind::AscribeUserType { .. } |
337338
PatKind::Error(_) => {}
338339
}
@@ -400,12 +401,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
400401
visit::walk_pat(self, pat);
401402
self.inside_adt = old_inside_adt;
402403
}
403-
PatKind::ExpandedConstant { def_id, is_inline, .. } => {
404-
if let Some(def) = def_id.as_local()
405-
&& *is_inline
406-
{
407-
self.visit_inner_body(def);
408-
}
404+
PatKind::InlineConstMarker { def_id, .. } => {
405+
// Also visit the inline `const {}` block that this pattern
406+
// represents. (See #116482 for context.)
407+
self.visit_inner_body(*def_id);
409408
visit::walk_pat(self, pat);
410409
}
411410
_ => {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -676,10 +676,10 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
676676
let mut interpreted_as_const = None;
677677
let mut interpreted_as_const_sugg = None;
678678

679-
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. }
679+
if let PatKind::NamedConstMarker { def_id, .. }
680680
| PatKind::AscribeUserType {
681681
subpattern:
682-
box Pat { kind: PatKind::ExpandedConstant { def_id, is_inline: false, .. }, .. },
682+
box Pat { kind: PatKind::NamedConstMarker { def_id, .. }, .. },
683683
..
684684
} = pat.kind
685685
&& let DefKind::Const = self.tcx.def_kind(def_id)
@@ -1309,7 +1309,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
13091309

13101310
for &arm in arms {
13111311
let arm = &thir.arms[arm];
1312-
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = arm.pattern.kind
1312+
if let PatKind::NamedConstMarker { def_id, .. } = arm.pattern.kind
13131313
&& let Ok(snippet) = cx.tcx.sess.source_map().span_to_snippet(arm.pattern.span)
13141314
// We filter out paths with multiple path::segments.
13151315
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')

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

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -165,17 +165,23 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
165165
// deconstructed to obtain the constant value and other data.
166166
let mut kind: PatKind<'tcx> = self.lower_lit(expr);
167167

168-
// Unpeel any ascription or inline-const wrapper nodes.
168+
// Unpeel any wrapper nodes, while preserving marker data that will
169+
// need to be reapplied to the range pattern node.
169170
loop {
170171
match kind {
171172
PatKind::AscribeUserType { ascription, subpattern } => {
172173
ascriptions.push(ascription);
173174
kind = subpattern.kind;
174175
}
175-
PatKind::ExpandedConstant { is_inline, def_id, subpattern } => {
176-
if is_inline {
177-
inline_consts.extend(def_id.as_local());
178-
}
176+
PatKind::InlineConstMarker { def_id, subpattern } => {
177+
// Preserve inline-const markers, so that THIR unsafeck can
178+
// see const blocks that are part of a range pattern.
179+
inline_consts.push(def_id);
180+
kind = subpattern.kind;
181+
}
182+
PatKind::NamedConstMarker { subpattern, .. } => {
183+
// Named-const markers are only used for improved diagnostics that
184+
// aren't relevant to range patterns, so it's OK to discard them.
179185
kind = subpattern.kind;
180186
}
181187
_ => break,
@@ -307,12 +313,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
307313
subpattern: Box::new(Pat { span, ty, kind }),
308314
};
309315
}
310-
for def in inline_consts {
311-
kind = PatKind::ExpandedConstant {
312-
def_id: def.to_def_id(),
313-
is_inline: true,
314-
subpattern: Box::new(Pat { span, ty, kind }),
315-
};
316+
// If one or both endpoints is an inline-const block, reapply the marker
317+
// nodes so that unsafeck can traverse into the corresponding block body.
318+
for def_id in inline_consts {
319+
let subpattern = Box::new(Pat { span, ty, kind });
320+
kind = PatKind::InlineConstMarker { def_id, subpattern };
316321
}
317322
Ok(kind)
318323
}
@@ -593,11 +598,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
593598
let args = self.typeck_results.node_args(id);
594599
let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
595600
let subpattern = self.const_to_pat(c, ty, id, span);
596-
let pattern = Box::new(Pat {
597-
span,
598-
ty,
599-
kind: PatKind::ExpandedConstant { subpattern, def_id, is_inline: false },
600-
});
601+
let pattern =
602+
Box::new(Pat { span, ty, kind: PatKind::NamedConstMarker { subpattern, def_id } });
601603

602604
if !is_associated_const {
603605
return pattern;
@@ -648,7 +650,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
648650

649651
let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
650652
let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span);
651-
PatKind::ExpandedConstant { subpattern, def_id: def_id.to_def_id(), is_inline: true }
653+
PatKind::InlineConstMarker { subpattern, def_id }
652654
}
653655

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

compiler/rustc_mir_build/src/thir/print.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -733,10 +733,16 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
733733
print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
734734
print_indented!(self, "}", depth_lvl + 1);
735735
}
736-
PatKind::ExpandedConstant { def_id, is_inline, subpattern } => {
737-
print_indented!(self, "ExpandedConstant {", depth_lvl + 1);
736+
PatKind::InlineConstMarker { def_id, subpattern } => {
737+
print_indented!(self, "InlineConstMarker {", depth_lvl + 1);
738+
print_indented!(self, format!("def_id: {def_id:?}"), depth_lvl + 2);
739+
print_indented!(self, "subpattern:", depth_lvl + 2);
740+
self.print_pat(subpattern, depth_lvl + 2);
741+
print_indented!(self, "}", depth_lvl + 1);
742+
}
743+
PatKind::NamedConstMarker { def_id, subpattern } => {
744+
print_indented!(self, "NamedConstMarker {", depth_lvl + 1);
738745
print_indented!(self, format!("def_id: {def_id:?}"), depth_lvl + 2);
739-
print_indented!(self, format!("is_inline: {is_inline:?}"), depth_lvl + 2);
740746
print_indented!(self, "subpattern:", depth_lvl + 2);
741747
self.print_pat(subpattern, depth_lvl + 2);
742748
print_indented!(self, "}", depth_lvl + 1);

compiler/rustc_pattern_analysis/src/rustc.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
456456
let fields: Vec<_>;
457457
match &pat.kind {
458458
PatKind::AscribeUserType { subpattern, .. }
459-
| PatKind::ExpandedConstant { subpattern, .. } => return self.lower_pat(subpattern),
460-
PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
459+
| PatKind::InlineConstMarker { subpattern, .. }
460+
| PatKind::NamedConstMarker { subpattern, .. }
461+
| PatKind::Binding { subpattern: Some(subpattern), .. } => {
462+
return self.lower_pat(subpattern);
463+
}
464+
461465
PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
462466
ctor = Wildcard;
463467
fields = vec![];

0 commit comments

Comments
 (0)