Skip to content

Commit ebe74a2

Browse files
committed
PatKind: store constants as valtrees
1 parent 65b6cdb commit ebe74a2

File tree

11 files changed

+68
-78
lines changed

11 files changed

+68
-78
lines changed

compiler/rustc_middle/src/thir.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -832,15 +832,18 @@ pub enum PatKind<'tcx> {
832832
},
833833

834834
/// One of the following:
835-
/// * `&str` (represented as a valtree), which will be handled as a string pattern and thus
835+
/// * `&str`, which will be handled as a string pattern and thus
836836
/// exhaustiveness checking will detect if you use the same string twice in different
837837
/// patterns.
838-
/// * integer, bool, char or float (represented as a valtree), which will be handled by
838+
/// * integer, bool, char or float, which will be handled by
839839
/// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are
840840
/// much simpler.
841841
/// * `String`, if `string_deref_patterns` is enabled.
842842
Constant {
843-
value: mir::Const<'tcx>,
843+
// Not using `ty::Value` since this is conceptually not a type-level constant. In
844+
// particular, it can have raw pointers.
845+
ty: Ty<'tcx>,
846+
value: ty::ValTree<'tcx>,
844847
},
845848

846849
/// Pattern obtained by converting a constant (inline or named) to its pattern

compiler/rustc_middle/src/thir/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>(
265265
PatKind::Missing
266266
| PatKind::Wild
267267
| PatKind::Binding { subpattern: None, .. }
268-
| PatKind::Constant { value: _ }
268+
| PatKind::Constant { .. }
269269
| PatKind::Range(_)
270270
| PatKind::Never
271271
| PatKind::Error(_) => {}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
146146
for arm in rest {
147147
let arm = &self.thir[*arm];
148148
let value = match arm.pattern.kind {
149-
PatKind::Constant { value } => value,
149+
PatKind::Constant { value, .. } => value,
150150
PatKind::ExpandedConstant { ref subpattern, def_id: _ }
151-
if let PatKind::Constant { value } = subpattern.kind =>
151+
if let PatKind::Constant { value, .. } = subpattern.kind =>
152152
{
153153
value
154154
}
@@ -160,7 +160,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
160160
});
161161
}
162162
};
163-
values.push(value.eval_bits(self.tcx, self.typing_env));
163+
values.push(value.unwrap_leaf().to_bits_unchecked());
164164
targets.push(self.parse_block(arm.body)?);
165165
}
166166

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,11 @@ impl<'tcx> MatchPairTree<'tcx> {
136136
}
137137
}
138138

139-
PatKind::Constant { value } => Some(TestCase::Constant { value }),
139+
PatKind::Constant { ty: value_ty, value } => {
140+
// FIXME: `TestCase::Constant` should probably represent that it is always a `ValTree`.
141+
let value = Const::Ty(value_ty, ty::Const::new_value(cx.tcx, value, value_ty));
142+
Some(TestCase::Constant { value })
143+
}
140144

141145
PatKind::AscribeUserType {
142146
ascription: Ascription { ref annotation, variance },

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1336,7 +1336,7 @@ enum TestKind<'tcx> {
13361336
value: Const<'tcx>,
13371337
// Integer types are handled by `SwitchInt`, and constants with ADT
13381338
// types and `&[T]` types are converted back into patterns, so this can
1339-
// only be `&str`, `f32` or `f64`.
1339+
// only be `&str` or `f*`.
13401340
ty: Ty<'tcx>,
13411341
},
13421342

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

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ use rustc_index::Idx;
1010
use rustc_infer::infer::TyCtxtInferExt;
1111
use rustc_infer::traits::Obligation;
1212
use rustc_middle::mir::interpret::ErrorHandled;
13+
use rustc_middle::span_bug;
1314
use rustc_middle::thir::{FieldPat, Pat, PatKind};
1415
use rustc_middle::ty::{
1516
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitableExt, TypeVisitor, ValTree,
1617
};
17-
use rustc_middle::{mir, span_bug};
1818
use rustc_span::def_id::DefId;
1919
use rustc_span::{DUMMY_SP, Span};
2020
use rustc_trait_selection::traits::ObligationCause;
@@ -287,16 +287,12 @@ impl<'tcx> ConstToPat<'tcx> {
287287
// when lowering to MIR in `Builder::perform_test`, treat the constant as a `&str`.
288288
// This works because `str` and `&str` have the same valtree representation.
289289
let ref_str_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty);
290-
PatKind::Constant {
291-
value: mir::Const::Ty(ref_str_ty, ty::Const::new_value(tcx, cv, ref_str_ty)),
292-
}
290+
PatKind::Constant { ty: ref_str_ty, value: cv }
293291
}
294292
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
295293
// `&str` is represented as a valtree, let's keep using this
296294
// optimization for now.
297-
ty::Str => PatKind::Constant {
298-
value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
299-
},
295+
ty::Str => PatKind::Constant { ty, value: cv },
300296
// All other references are converted into deref patterns and then recursively
301297
// convert the dereferenced constant to a pattern that is the sub-pattern of the
302298
// deref pattern.
@@ -325,15 +321,13 @@ impl<'tcx> ConstToPat<'tcx> {
325321
// Also see <https://github.com/rust-lang/rfcs/pull/3535>.
326322
return self.mk_err(tcx.dcx().create_err(NaNPattern { span }), ty);
327323
} else {
328-
PatKind::Constant {
329-
value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
330-
}
324+
PatKind::Constant { ty, value: cv }
331325
}
332326
}
333327
ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
334328
// The raw pointers we see here have been "vetted" by valtree construction to be
335329
// just integers, so we simply allow them.
336-
PatKind::Constant { value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)) }
330+
PatKind::Constant { ty, value: cv }
337331
}
338332
ty::FnPtr(..) => {
339333
unreachable!(

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_middle::thir::{
2121
use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2222
use rustc_middle::ty::layout::IntegerExt;
2323
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode};
24-
use rustc_middle::{bug, span_bug};
24+
use rustc_middle::{bug, mir, span_bug};
2525
use rustc_span::def_id::DefId;
2626
use rustc_span::{ErrorGuaranteed, Span};
2727
use tracing::{debug, instrument};
@@ -156,12 +156,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
156156
}
157157

158158
// The unpeeled kind should now be a constant, giving us the endpoint value.
159-
let PatKind::Constant { value } = kind else {
159+
let PatKind::Constant { ty, value } = kind else {
160160
let msg =
161161
format!("found bad range pattern endpoint `{expr:?}` outside of error recovery");
162162
return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
163163
};
164-
164+
// FIXME: `Finite` should probably take a `ValTree` or even a `ScalarInt`
165+
// (but it should also be the same type as what `TestCase::Constant` uses, or at least
166+
// easy to convert).
167+
let value = mir::Const::Ty(ty, ty::Const::new_value(self.tcx, value, ty));
165168
Ok(Some(PatRangeBoundary::Finite(value)))
166169
}
167170

@@ -244,7 +247,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
244247
(RangeEnd::Included, Some(Ordering::Less)) => {}
245248
// `x..=y` where `x == y` and `x` and `y` are finite.
246249
(RangeEnd::Included, Some(Ordering::Equal)) if lo.is_finite() && hi.is_finite() => {
247-
kind = PatKind::Constant { value: lo.as_finite().unwrap() };
250+
// FIXME: silly conversion because not all pattern stuff uses valtrees yet.
251+
let mir::Const::Ty(ty, val) = lo.as_finite().unwrap() else { unreachable!() };
252+
kind = PatKind::Constant { ty, value: val.to_value().valtree };
248253
}
249254
// `..=x` where `x == ty::MIN`.
250255
(RangeEnd::Included, Some(Ordering::Equal)) if !lo.is_finite() => {}

compiler/rustc_mir_build/src/thir/print.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
761761
self.print_pat(subpattern, depth_lvl + 2);
762762
print_indented!(self, "}", depth_lvl + 1);
763763
}
764-
PatKind::Constant { value } => {
764+
PatKind::Constant { value, ty: _ } => {
765765
print_indented!(self, "Constant {", depth_lvl + 1);
766766
print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
767767
print_indented!(self, "}", depth_lvl + 1);

compiler/rustc_pattern_analysis/src/rustc.rs

Lines changed: 34 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -517,78 +517,57 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
517517
),
518518
}
519519
}
520-
PatKind::Constant { value } => {
520+
PatKind::Constant { ty: value_ty, value } => {
521521
match ty.kind() {
522522
ty::Bool => {
523-
ctor = match value.try_eval_bool(cx.tcx, cx.typing_env) {
524-
Some(b) => Bool(b),
525-
None => Opaque(OpaqueId::new()),
526-
};
523+
ctor = Bool(value.unwrap_leaf().try_to_bool().unwrap());
527524
fields = vec![];
528525
arity = 0;
529526
}
530527
ty::Char | ty::Int(_) | ty::Uint(_) => {
531-
ctor = match value.try_eval_bits(cx.tcx, cx.typing_env) {
532-
Some(bits) => {
533-
let x = match *ty.kind() {
534-
ty::Int(ity) => {
535-
let size = Integer::from_int_ty(&cx.tcx, ity).size().bits();
536-
MaybeInfiniteInt::new_finite_int(bits, size)
537-
}
538-
_ => MaybeInfiniteInt::new_finite_uint(bits),
539-
};
540-
IntRange(IntRange::from_singleton(x))
541-
}
542-
None => Opaque(OpaqueId::new()),
528+
ctor = {
529+
let bits = value.unwrap_leaf().to_bits_unchecked();
530+
let x = match *ty.kind() {
531+
ty::Int(ity) => {
532+
let size = Integer::from_int_ty(&cx.tcx, ity).size().bits();
533+
MaybeInfiniteInt::new_finite_int(bits, size)
534+
}
535+
_ => MaybeInfiniteInt::new_finite_uint(bits),
536+
};
537+
IntRange(IntRange::from_singleton(x))
543538
};
544539
fields = vec![];
545540
arity = 0;
546541
}
547542
ty::Float(ty::FloatTy::F16) => {
548-
ctor = match value.try_eval_bits(cx.tcx, cx.typing_env) {
549-
Some(bits) => {
550-
use rustc_apfloat::Float;
551-
let value = rustc_apfloat::ieee::Half::from_bits(bits);
552-
F16Range(value, value, RangeEnd::Included)
553-
}
554-
None => Opaque(OpaqueId::new()),
555-
};
543+
use rustc_apfloat::Float;
544+
let bits = value.unwrap_leaf().to_u16();
545+
let value = rustc_apfloat::ieee::Half::from_bits(bits.into());
546+
ctor = F16Range(value, value, RangeEnd::Included);
556547
fields = vec![];
557548
arity = 0;
558549
}
559550
ty::Float(ty::FloatTy::F32) => {
560-
ctor = match value.try_eval_bits(cx.tcx, cx.typing_env) {
561-
Some(bits) => {
562-
use rustc_apfloat::Float;
563-
let value = rustc_apfloat::ieee::Single::from_bits(bits);
564-
F32Range(value, value, RangeEnd::Included)
565-
}
566-
None => Opaque(OpaqueId::new()),
567-
};
551+
use rustc_apfloat::Float;
552+
let bits = value.unwrap_leaf().to_u32();
553+
let value = rustc_apfloat::ieee::Single::from_bits(bits.into());
554+
ctor = F32Range(value, value, RangeEnd::Included);
568555
fields = vec![];
569556
arity = 0;
570557
}
571558
ty::Float(ty::FloatTy::F64) => {
572-
ctor = match value.try_eval_bits(cx.tcx, cx.typing_env) {
573-
Some(bits) => {
574-
use rustc_apfloat::Float;
575-
let value = rustc_apfloat::ieee::Double::from_bits(bits);
576-
F64Range(value, value, RangeEnd::Included)
577-
}
578-
None => Opaque(OpaqueId::new()),
579-
};
559+
use rustc_apfloat::Float;
560+
let bits = value.unwrap_leaf().to_u64();
561+
let value = rustc_apfloat::ieee::Double::from_bits(bits.into());
562+
ctor = F64Range(value, value, RangeEnd::Included);
580563
fields = vec![];
581564
arity = 0;
582565
}
583566
ty::Float(ty::FloatTy::F128) => {
584-
ctor = match value.try_eval_bits(cx.tcx, cx.typing_env) {
585-
Some(bits) => {
586-
use rustc_apfloat::Float;
587-
let value = rustc_apfloat::ieee::Quad::from_bits(bits);
588-
F128Range(value, value, RangeEnd::Included)
589-
}
590-
None => Opaque(OpaqueId::new()),
591-
};
567+
use rustc_apfloat::Float;
568+
let bits = value.unwrap_leaf().to_u128();
569+
let value = rustc_apfloat::ieee::Quad::from_bits(bits);
570+
ctor = F128Range(value, value, RangeEnd::Included);
592571
fields = vec![];
593572
arity = 0;
594573
}
@@ -601,7 +580,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
601580
// subfields.
602581
// Note: `t` is `str`, not `&str`.
603582
let ty = self.reveal_opaque_ty(*t);
604-
let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), 0, ty, pat);
583+
// FIXME: why does `Str` need a `mir::Value`?
584+
let val = mir::Const::Ty(
585+
*value_ty,
586+
ty::Const::new_value(self.tcx, *value, *value_ty),
587+
);
588+
let subpattern = DeconstructedPat::new(Str(val), Vec::new(), 0, ty, pat);
605589
ctor = Ref;
606590
fields = vec![subpattern.at_index(0)];
607591
arity = 1;

compiler/rustc_ty_utils/src/consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
375375
}
376376

377377
match pat.kind {
378-
thir::PatKind::Constant { value } => value.has_non_region_param(),
378+
thir::PatKind::Constant { value, .. } => value.has_non_region_param(),
379379
thir::PatKind::Range(ref range) => {
380380
let &thir::PatRange { lo, hi, .. } = range.as_ref();
381381
lo.has_non_region_param() || hi.has_non_region_param()

0 commit comments

Comments
 (0)