tag_for_variant follow-ups

This commit is contained in:
Ralf Jung
2024-03-23 10:44:28 +01:00
parent c3b05c6e5b
commit 928bd3b4e0
3 changed files with 28 additions and 25 deletions

View File

@@ -3,7 +3,7 @@ use either::{Left, Right};
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo}; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
use rustc_middle::mir::{self, ConstAlloc, ConstValue}; use rustc_middle::mir::{self, ConstAlloc, ConstValue};
use rustc_middle::query::{Key, TyCtxtAt}; use rustc_middle::query::TyCtxtAt;
use rustc_middle::traits::Reveal; use rustc_middle::traits::Reveal;
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -243,24 +243,6 @@ pub(crate) fn turn_into_const_value<'tcx>(
op_to_const(&ecx, &mplace.into(), /* for diagnostics */ false) op_to_const(&ecx, &mplace.into(), /* for diagnostics */ false)
} }
/// Computes the tag (if any) for a given type and variant.
#[instrument(skip(tcx), level = "debug")]
pub fn tag_for_variant_provider<'tcx>(
tcx: TyCtxt<'tcx>,
(ty, variant_index): (Ty<'tcx>, abi::VariantIdx),
) -> Option<ty::ScalarInt> {
assert!(ty.is_enum());
let ecx = InterpCx::new(
tcx,
ty.default_span(tcx),
ty::ParamEnv::reveal_all(),
crate::const_eval::DummyMachine,
);
ecx.tag_for_variant(ty, variant_index).unwrap().map(|(tag, _tag_field)| tag)
}
#[instrument(skip(tcx), level = "debug")] #[instrument(skip(tcx), level = "debug")]
pub fn eval_to_const_value_raw_provider<'tcx>( pub fn eval_to_const_value_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,

View File

@@ -2,10 +2,11 @@
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::mir::interpret::InterpErrorInfo; use rustc_middle::mir::interpret::InterpErrorInfo;
use rustc_middle::query::TyCtxtAt; use rustc_middle::query::{Key, TyCtxtAt};
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_target::abi::VariantIdx;
use crate::interpret::format_interp_error; use crate::interpret::{format_interp_error, InterpCx};
mod dummy_machine; mod dummy_machine;
mod error; mod error;
@@ -77,3 +78,21 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
Some(mir::DestructuredConstant { variant, fields }) Some(mir::DestructuredConstant { variant, fields })
} }
/// Computes the tag (if any) for a given type and variant.
#[instrument(skip(tcx), level = "debug")]
pub fn tag_for_variant_provider<'tcx>(
tcx: TyCtxt<'tcx>,
(ty, variant_index): (Ty<'tcx>, VariantIdx),
) -> Option<ty::ScalarInt> {
assert!(ty.is_enum());
let ecx = InterpCx::new(
tcx,
ty.default_span(tcx),
ty::ParamEnv::reveal_all(),
crate::const_eval::DummyMachine,
);
ecx.tag_for_variant(ty, variant_index).unwrap().map(|(tag, _tag_field)| tag)
}

View File

@@ -38,7 +38,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
None => { None => {
// No need to write the tag here, because an untagged variant is // No need to write the tag here, because an untagged variant is
// implicitly encoded. For `Niche`-optimized enums, it's by // implicitly encoded. For `Niche`-optimized enums, this works by
// simply by having a value that is outside the niche variants. // simply by having a value that is outside the niche variants.
// But what if the data stored here does not actually encode // But what if the data stored here does not actually encode
// this variant? That would be bad! So let's double-check... // this variant? That would be bad! So let's double-check...
@@ -227,8 +227,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(ImmTy::from_scalar(discr_value, discr_layout)) Ok(ImmTy::from_scalar(discr_value, discr_layout))
} }
/// Computes the tag value and its field number (if any) of a given variant /// Computes how to write the tag of a given variant of enum `ty`:
/// of type `ty`. /// - `None` means that nothing needs to be done as the variant is encoded implicitly
/// - `Some((val, field_idx))` means that the given integer value needs to be stored at the
/// given field index.
pub(crate) fn tag_for_variant( pub(crate) fn tag_for_variant(
&self, &self,
ty: Ty<'tcx>, ty: Ty<'tcx>,