Rollup merge of #122933 - RalfJung:tag_for_variant, r=oli-obk

tag_for_variant follow-ups

Follow-up to https://github.com/rust-lang/rust/pull/122784, mostly to clarify the doc comment.
This commit is contained in:
Matthias Krüger 2024-03-23 15:00:21 +01:00 committed by GitHub
commit fce80392d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 28 additions and 25 deletions

View File

@ -3,7 +3,7 @@
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 @@ pub fn write_discriminant(
} }
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 @@ pub fn discriminant_for_variant(
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>,