Skip to content

Commit 248b9a8

Browse files
committed
refactor valtree logic
1 parent cf9eea8 commit 248b9a8

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

Lines changed: 47 additions & 39 deletions
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::{
@@ -2904,6 +2905,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
29042905
None
29052906
}
29062907

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

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

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

0 commit comments

Comments
 (0)