Skip to content

Commit 0bb9c46

Browse files
committed
refactor valtree logic
1 parent ec788c6 commit 0bb9c46

File tree

1 file changed

+47
-39
lines changed
  • compiler/rustc_mir_build/src/builder/matches

1 file changed

+47
-39
lines changed

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

+47-39
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use tracing::{debug, instrument};
2727

2828
use crate::builder::ForGuard::{self, OutsideGuard, RefWithinGuard};
2929
use crate::builder::expr::as_place::PlaceBuilder;
30+
use crate::builder::interpret::ErrorHandled;
3031
use crate::builder::matches::user_ty::ProjectedUserTypesNode;
3132
use crate::builder::scope::DropKind;
3233
use crate::builder::{
@@ -2903,6 +2904,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
29032904
None
29042905
}
29052906

2907+
/// Based on `FunctionCx::eval_unevaluated_mir_constant_to_valtree`.
2908+
fn eval_unevaluated_mir_constant_to_valtree(
2909+
&self,
2910+
constant: ConstOperand<'tcx>,
2911+
) -> Result<(ty::ValTree<'tcx>, Ty<'tcx>), ErrorHandled> {
2912+
assert!(!constant.const_.ty().has_param());
2913+
let (uv, ty) = match constant.const_ {
2914+
mir::Const::Unevaluated(uv, ty) => (uv.shrink(), ty),
2915+
mir::Const::Ty(_, c) => match c.kind() {
2916+
// A constant that came from a const generic but was then used as an argument to
2917+
// old-style simd_shuffle (passing as argument instead of as a generic param).
2918+
ty::ConstKind::Value(cv) => return Ok((cv.valtree, cv.ty)),
2919+
other => span_bug!(constant.span, "{other:#?}"),
2920+
},
2921+
mir::Const::Val(mir::ConstValue::Scalar(mir::interpret::Scalar::Int(val)), ty) => {
2922+
return Ok((ValTree::from_scalar_int(self.tcx, val), ty));
2923+
}
2924+
// We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate
2925+
// a constant and write that value back into `Operand`s. This could happen, but is
2926+
// unlikely. Also: all users of `simd_shuffle` are on unstable and already need to take
2927+
// a lot of care around intrinsics. For an issue to happen here, it would require a
2928+
// macro expanding to a `simd_shuffle` call without wrapping the constant argument in a
2929+
// `const {}` block, but the user pass through arbitrary expressions.
2930+
// FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a
2931+
// real const generic, and get rid of this entire function.
2932+
other => span_bug!(constant.span, "{other:#?}"),
2933+
};
2934+
2935+
match self.tcx.const_eval_resolve_for_typeck(self.typing_env(), uv, constant.span)? {
2936+
Ok(valtree) => Ok((valtree, ty)),
2937+
Err(ty) => bug!("could not convert {ty:?} to a valtree"),
2938+
}
2939+
}
2940+
29062941
fn static_pattern_match_help(
29072942
&self,
29082943
constant: ConstOperand<'tcx>,
@@ -2911,48 +2946,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
29112946
use rustc_pattern_analysis::constructor::{IntRange, MaybeInfiniteInt};
29122947
use rustc_pattern_analysis::rustc::Constructor;
29132948

2914-
// Based on eval_unevaluated_mir_constant_to_valtree
2915-
let (valtree, ty) = 'a: {
2916-
assert!(!constant.const_.ty().has_param());
2917-
let (uv, ty) = match constant.const_ {
2918-
mir::Const::Unevaluated(uv, ty) => (uv.shrink(), ty),
2919-
mir::Const::Ty(_, c) => match c.kind() {
2920-
// A constant that came from a const generic but was then used as an argument to
2921-
// old-style simd_shuffle (passing as argument instead of as a generic param).
2922-
ty::ConstKind::Value(cv) => break 'a (cv.valtree, cv.ty),
2923-
other => span_bug!(constant.span, "{other:#?}"),
2924-
},
2925-
mir::Const::Val(mir::ConstValue::Scalar(mir::interpret::Scalar::Int(val)), ty) => {
2926-
break 'a (ValTree::from_scalar_int(self.tcx, val), ty);
2927-
}
2928-
// We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate
2929-
// a constant and write that value back into `Operand`s. This could happen, but is
2930-
// unlikely. Also: all users of `simd_shuffle` are on unstable and already need to take
2931-
// a lot of care around intrinsics. For an issue to happen here, it would require a
2932-
// macro expanding to a `simd_shuffle` call without wrapping the constant argument in a
2933-
// `const {}` block, but the user pass through arbitrary expressions.
2934-
// FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a
2935-
// real const generic, and get rid of this entire function.
2936-
other => span_bug!(constant.span, "{other:#?}"),
2937-
};
2938-
(
2939-
self.tcx
2940-
.const_eval_resolve_for_typeck(self.typing_env(), uv, constant.span)
2941-
.unwrap()
2942-
.unwrap(),
2943-
ty,
2944-
)
2945-
};
2949+
let (valtree, ty) = self.eval_unevaluated_mir_constant_to_valtree(constant).unwrap();
29462950
assert!(!ty.has_param());
29472951

29482952
match pat.ctor() {
2949-
Constructor::Variant(variant_index) => match *valtree {
2950-
ValTreeKind::Branch(box [actual_variant_idx]) => {
2951-
*variant_index
2952-
== VariantIdx::from_u32(actual_variant_idx.unwrap_leaf().to_u32())
2953-
}
2954-
other => todo!("{other:?}"),
2955-
},
2953+
Constructor::Variant(variant_index) => {
2954+
let ValTreeKind::Branch(box [actual_variant_idx]) = *valtree else {
2955+
bug!("malformed valtree for an enum")
2956+
};
2957+
2958+
let ValTreeKind::Leaf(actual_variant_idx) = ***actual_variant_idx else {
2959+
bug!("malformed valtree for an enum")
2960+
};
2961+
2962+
*variant_index == VariantIdx::from_u32(actual_variant_idx.to_u32())
2963+
}
29562964
Constructor::IntRange(int_range) => {
29572965
let size = pat.ty().primitive_size(self.tcx);
29582966
let actual_int = valtree.unwrap_leaf().to_bits(size);

0 commit comments

Comments
 (0)