Skip to content

Commit dce1f73

Browse files
authored
Unrolled build for rust-lang#139108
Rollup merge of rust-lang#139108 - Nadrieril:simplify-expandedconstant, r=oli-obk Simplify `thir::PatKind::ExpandedConstant` I made it a bit less ad-hoc. In particular, I removed `is_inline: bool` that was just caching the output of `tcx.def_kind(def_id)`. This makes inline consts a tiny bit less special in patterns. r? `@oli-obk` cc `@Zalathar`
2 parents 8fb32ab + d912c03 commit dce1f73

File tree

8 files changed

+95
-124
lines changed

8 files changed

+95
-124
lines changed

compiler/rustc_middle/src/thir.rs

+8-14
Original file line numberDiff line numberDiff line change
@@ -812,23 +812,17 @@ pub enum PatKind<'tcx> {
812812
},
813813

814814
/// Pattern obtained by converting a constant (inline or named) to its pattern
815-
/// representation using `const_to_pat`.
815+
/// representation using `const_to_pat`. This is used for unsafety checking.
816816
ExpandedConstant {
817-
/// [DefId] of the constant, we need this so that we have a
818-
/// reference that can be used by unsafety checking to visit nested
819-
/// unevaluated constants and for diagnostics. If the `DefId` doesn't
820-
/// correspond to a local crate, it points at the `const` item.
817+
/// [DefId] of the constant item.
821818
def_id: DefId,
822-
/// If `false`, then `def_id` points at a `const` item, otherwise it
823-
/// corresponds to a local inline const.
824-
is_inline: bool,
825-
/// If the inline constant is used in a range pattern, this subpattern
826-
/// represents the range (if both ends are inline constants, there will
827-
/// be multiple InlineConstant wrappers).
819+
/// The pattern that the constant lowered to.
828820
///
829-
/// Otherwise, the actual pattern that the constant lowered to. As with
830-
/// other constants, inline constants are matched structurally where
831-
/// possible.
821+
/// HACK: we need to keep the `DefId` of inline constants around for unsafety checking;
822+
/// therefore when a range pattern contains inline constants, we re-wrap the range pattern
823+
/// with the `ExpandedConstant` nodes that correspond to the range endpoints. Hence
824+
/// `subpattern` may actually be a range pattern, and `def_id` be the constant for one of
825+
/// its endpoints.
832826
subpattern: Box<Pat<'tcx>>,
833827
},
834828

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
145145
let arm = &self.thir[*arm];
146146
let value = match arm.pattern.kind {
147147
PatKind::Constant { value } => value,
148-
PatKind::ExpandedConstant { ref subpattern, def_id: _, is_inline: false }
148+
PatKind::ExpandedConstant { ref subpattern, def_id: _ }
149149
if let PatKind::Constant { value } = subpattern.kind =>
150150
{
151151
value

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

+1-30
Original file line numberDiff line numberDiff line change
@@ -201,39 +201,10 @@ impl<'tcx> MatchPairTree<'tcx> {
201201
None
202202
}
203203

204-
PatKind::ExpandedConstant { subpattern: ref pattern, def_id: _, is_inline: false } => {
204+
PatKind::ExpandedConstant { subpattern: ref pattern, .. } => {
205205
MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data);
206206
None
207207
}
208-
PatKind::ExpandedConstant { subpattern: ref pattern, def_id, is_inline: true } => {
209-
MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data);
210-
211-
// Apply a type ascription for the inline constant to the value at `match_pair.place`
212-
if let Some(source) = place {
213-
let span = pattern.span;
214-
let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id());
215-
let args = ty::InlineConstArgs::new(
216-
cx.tcx,
217-
ty::InlineConstArgsParts {
218-
parent_args: ty::GenericArgs::identity_for_item(cx.tcx, parent_id),
219-
ty: cx.infcx.next_ty_var(span),
220-
},
221-
)
222-
.args;
223-
let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::new(
224-
ty::UserTypeKind::TypeOf(def_id, ty::UserArgs { args, user_self_ty: None }),
225-
));
226-
let annotation = ty::CanonicalUserTypeAnnotation {
227-
inferred_ty: pattern.ty,
228-
span,
229-
user_ty: Box::new(user_ty),
230-
};
231-
let variance = ty::Contravariant;
232-
extra_data.ascriptions.push(super::Ascription { annotation, source, variance });
233-
}
234-
235-
None
236-
}
237208

238209
PatKind::Array { ref prefix, ref slice, ref suffix } => {
239210
cx.prefix_slice_suffix(

compiler/rustc_mir_build/src/check_unsafety.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -403,9 +403,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
403403
visit::walk_pat(self, pat);
404404
self.inside_adt = old_inside_adt;
405405
}
406-
PatKind::ExpandedConstant { def_id, is_inline, .. } => {
406+
PatKind::ExpandedConstant { def_id, .. } => {
407407
if let Some(def) = def_id.as_local()
408-
&& *is_inline
408+
&& matches!(self.tcx.def_kind(def_id), DefKind::InlineConst)
409409
{
410410
self.visit_inner_body(def);
411411
}

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
676676
unpeeled_pat = subpattern;
677677
}
678678

679-
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = unpeeled_pat.kind
679+
if let PatKind::ExpandedConstant { def_id, .. } = unpeeled_pat.kind
680680
&& let DefKind::Const = self.tcx.def_kind(def_id)
681681
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
682682
// We filter out paths with multiple path::segments.
@@ -1296,7 +1296,8 @@ fn report_non_exhaustive_match<'p, 'tcx>(
12961296

12971297
for &arm in arms {
12981298
let arm = &thir.arms[arm];
1299-
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = arm.pattern.kind
1299+
if let PatKind::ExpandedConstant { def_id, .. } = arm.pattern.kind
1300+
&& !matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst)
13001301
&& let Ok(snippet) = cx.tcx.sess.source_map().span_to_snippet(arm.pattern.span)
13011302
// We filter out paths with multiple path::segments.
13021303
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,10 @@ impl<'tcx> ConstToPat<'tcx> {
182182
}
183183
}
184184

185-
inlined_const_as_pat
185+
// Wrap the pattern in a marker node to indicate that it is the result of lowering a
186+
// constant. This is used for diagnostics, and for unsafety checking of inline const blocks.
187+
let kind = PatKind::ExpandedConstant { subpattern: inlined_const_as_pat, def_id: uv.def };
188+
Box::new(Pat { kind, ty, span: self.span })
186189
}
187190

188191
fn field_pats(

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

+75-72
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
1313
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
1414
use rustc_hir::{self as hir, LangItem, RangeEnd};
1515
use rustc_index::Idx;
16+
use rustc_infer::infer::TyCtxtInferExt;
1617
use rustc_middle::mir::interpret::LitToConstInput;
1718
use rustc_middle::thir::{
1819
Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
1920
};
2021
use rustc_middle::ty::layout::IntegerExt;
21-
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt};
22+
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode};
2223
use rustc_middle::{bug, span_bug};
23-
use rustc_span::def_id::LocalDefId;
24+
use rustc_span::def_id::DefId;
2425
use rustc_span::{ErrorGuaranteed, Span};
2526
use tracing::{debug, instrument};
2627

@@ -124,7 +125,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
124125
expr: Option<&'tcx hir::PatExpr<'tcx>>,
125126
// Out-parameters collecting extra data to be reapplied by the caller
126127
ascriptions: &mut Vec<Ascription<'tcx>>,
127-
inline_consts: &mut Vec<LocalDefId>,
128+
expanded_consts: &mut Vec<DefId>,
128129
) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
129130
let Some(expr) = expr else { return Ok(None) };
130131

@@ -139,10 +140,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
139140
ascriptions.push(ascription);
140141
kind = subpattern.kind;
141142
}
142-
PatKind::ExpandedConstant { is_inline, def_id, subpattern } => {
143-
if is_inline {
144-
inline_consts.extend(def_id.as_local());
145-
}
143+
PatKind::ExpandedConstant { def_id, subpattern } => {
144+
expanded_consts.push(def_id);
146145
kind = subpattern.kind;
147146
}
148147
_ => break,
@@ -221,10 +220,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
221220

222221
// Collect extra data while lowering the endpoints, to be reapplied later.
223222
let mut ascriptions = vec![];
224-
let mut inline_consts = vec![];
223+
let mut expanded_consts = vec![];
225224

226225
let mut lower_endpoint =
227-
|expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut inline_consts);
226+
|expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut expanded_consts);
228227

229228
let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
230229
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
@@ -269,17 +268,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
269268
// `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
270269
// constants somewhere. Have them on the range pattern.
271270
for ascription in ascriptions {
272-
kind = PatKind::AscribeUserType {
273-
ascription,
274-
subpattern: Box::new(Pat { span, ty, kind }),
275-
};
271+
let subpattern = Box::new(Pat { span, ty, kind });
272+
kind = PatKind::AscribeUserType { ascription, subpattern };
276273
}
277-
for def in inline_consts {
278-
kind = PatKind::ExpandedConstant {
279-
def_id: def.to_def_id(),
280-
is_inline: true,
281-
subpattern: Box::new(Pat { span, ty, kind }),
282-
};
274+
for def_id in expanded_consts {
275+
let subpattern = Box::new(Pat { span, ty, kind });
276+
kind = PatKind::ExpandedConstant { def_id, subpattern };
283277
}
284278
Ok(kind)
285279
}
@@ -567,15 +561,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
567561
// Lower the named constant to a THIR pattern.
568562
let args = self.typeck_results.node_args(id);
569563
let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
570-
let subpattern = self.const_to_pat(c, ty, id, span);
571-
572-
// Wrap the pattern in a marker node to indicate that it is the result
573-
// of lowering a named constant. This marker is used for improved
574-
// diagnostics in some situations, but has no effect at runtime.
575-
let mut pattern = {
576-
let kind = PatKind::ExpandedConstant { subpattern, def_id, is_inline: false };
577-
Box::new(Pat { span, ty, kind })
578-
};
564+
let mut pattern = self.const_to_pat(c, ty, id, span);
579565

580566
// If this is an associated constant with an explicit user-written
581567
// type, add an ascription node (e.g. `<Foo<'a> as MyTrait>::CONST`).
@@ -612,18 +598,37 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
612598
let ty = tcx.typeck(def_id).node_type(block.hir_id);
613599

614600
let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
615-
let parent_args =
616-
tcx.erase_regions(ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id));
601+
let parent_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
617602
let args = ty::InlineConstArgs::new(tcx, ty::InlineConstArgsParts { parent_args, ty }).args;
618603

619-
debug_assert!(!args.has_free_regions());
620-
621604
let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
622-
let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span);
623-
624-
// Wrap the pattern in a marker node to indicate that it is the result
625-
// of lowering an inline const block.
626-
PatKind::ExpandedConstant { subpattern, def_id: def_id.to_def_id(), is_inline: true }
605+
let c = ty::Const::new_unevaluated(self.tcx, ct);
606+
let pattern = self.const_to_pat(c, ty, id, span);
607+
608+
// Apply a type ascription for the inline constant.
609+
let annotation = {
610+
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
611+
let args = ty::InlineConstArgs::new(
612+
tcx,
613+
ty::InlineConstArgsParts { parent_args, ty: infcx.next_ty_var(span) },
614+
)
615+
.args;
616+
infcx.canonicalize_user_type_annotation(ty::UserType::new(ty::UserTypeKind::TypeOf(
617+
def_id.to_def_id(),
618+
ty::UserArgs { args, user_self_ty: None },
619+
)))
620+
};
621+
let annotation =
622+
CanonicalUserTypeAnnotation { user_ty: Box::new(annotation), span, inferred_ty: ty };
623+
PatKind::AscribeUserType {
624+
subpattern: pattern,
625+
ascription: Ascription {
626+
annotation,
627+
// Note that we use `Contravariant` here. See the `variance` field documentation
628+
// for details.
629+
variance: ty::Contravariant,
630+
},
631+
}
627632
}
628633

629634
/// Lowers the kinds of "expression" that can appear in a HIR pattern:
@@ -635,43 +640,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
635640
expr: &'tcx hir::PatExpr<'tcx>,
636641
pat_ty: Option<Ty<'tcx>>,
637642
) -> PatKind<'tcx> {
638-
let (lit, neg) = match &expr.kind {
639-
hir::PatExprKind::Path(qpath) => {
640-
return self.lower_path(qpath, expr.hir_id, expr.span).kind;
641-
}
643+
match &expr.kind {
644+
hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
642645
hir::PatExprKind::ConstBlock(anon_const) => {
643-
return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
646+
self.lower_inline_const(anon_const, expr.hir_id, expr.span)
644647
}
645-
hir::PatExprKind::Lit { lit, negated } => (lit, *negated),
646-
};
647-
648-
// We handle byte string literal patterns by using the pattern's type instead of the
649-
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
650-
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
651-
// pattern's type means we'll properly translate it to a slice reference pattern. This works
652-
// because slices and arrays have the same valtree representation.
653-
// HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if
654-
// `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR.
655-
// FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is
656-
// superseded by a more general implementation of deref patterns.
657-
let ct_ty = match pat_ty {
658-
Some(pat_ty)
659-
if let ty::Adt(def, _) = *pat_ty.kind()
660-
&& self.tcx.is_lang_item(def.did(), LangItem::String) =>
661-
{
662-
if !self.tcx.features().string_deref_patterns() {
663-
span_bug!(
664-
expr.span,
665-
"matching on `String` went through without enabling string_deref_patterns"
666-
);
667-
}
668-
self.typeck_results.node_type(expr.hir_id)
648+
hir::PatExprKind::Lit { lit, negated } => {
649+
// We handle byte string literal patterns by using the pattern's type instead of the
650+
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
651+
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
652+
// pattern's type means we'll properly translate it to a slice reference pattern. This works
653+
// because slices and arrays have the same valtree representation.
654+
// HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if
655+
// `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR.
656+
// FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is
657+
// superseded by a more general implementation of deref patterns.
658+
let ct_ty = match pat_ty {
659+
Some(pat_ty)
660+
if let ty::Adt(def, _) = *pat_ty.kind()
661+
&& self.tcx.is_lang_item(def.did(), LangItem::String) =>
662+
{
663+
if !self.tcx.features().string_deref_patterns() {
664+
span_bug!(
665+
expr.span,
666+
"matching on `String` went through without enabling string_deref_patterns"
667+
);
668+
}
669+
self.typeck_results.node_type(expr.hir_id)
670+
}
671+
Some(pat_ty) => pat_ty,
672+
None => self.typeck_results.node_type(expr.hir_id),
673+
};
674+
let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg: *negated };
675+
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
676+
self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind
669677
}
670-
Some(pat_ty) => pat_ty,
671-
None => self.typeck_results.node_type(expr.hir_id),
672-
};
673-
let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
674-
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
675-
self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind
678+
}
676679
}
677680
}

compiler/rustc_mir_build/src/thir/print.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -740,10 +740,9 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
740740
print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
741741
print_indented!(self, "}", depth_lvl + 1);
742742
}
743-
PatKind::ExpandedConstant { def_id, is_inline, subpattern } => {
743+
PatKind::ExpandedConstant { def_id, subpattern } => {
744744
print_indented!(self, "ExpandedConstant {", depth_lvl + 1);
745745
print_indented!(self, format!("def_id: {def_id:?}"), depth_lvl + 2);
746-
print_indented!(self, format!("is_inline: {is_inline:?}"), depth_lvl + 2);
747746
print_indented!(self, "subpattern:", depth_lvl + 2);
748747
self.print_pat(subpattern, depth_lvl + 2);
749748
print_indented!(self, "}", depth_lvl + 1);

0 commit comments

Comments
 (0)