Move try_to_raw_bytes from ty::Valtree to ty::Value

Signed-off-by: FedericoBruzzone <federico.bruzzone.i@gmail.com>
This commit is contained in:
FedericoBruzzone 2025-02-03 18:33:27 +01:00
parent 6e0dfc813c
commit 00c61a81a0
3 changed files with 36 additions and 38 deletions

View file

@ -78,30 +78,6 @@ impl<'tcx> ValTree<'tcx> {
Self::Branch(_) => None,
}
}
/// Get the values inside the ValTree as a slice of bytes. This only works for
/// constants with types &str, &[u8], or [u8; _].
pub fn try_to_raw_bytes(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx [u8]> {
match ty.kind() {
ty::Ref(_, inner_ty, _) => match inner_ty.kind() {
// `&str` can be interpreted as raw bytes
ty::Str => {}
// `&[u8]` can be interpreted as raw bytes
ty::Slice(slice_ty) if *slice_ty == tcx.types.u8 => {}
// other `&_` can't be interpreted as raw bytes
_ => return None,
},
// `[u8; N]` can be interpreted as raw bytes
ty::Array(array_ty, _) if *array_ty == tcx.types.u8 => {}
// Otherwise, type cannot be interpreted as raw bytes
_ => return None,
}
Some(
tcx.arena
.alloc_from_iter(self.unwrap_branch().into_iter().map(|v| v.unwrap_leaf().to_u8())),
)
}
}
/// A type-level constant value.
@ -143,6 +119,29 @@ impl<'tcx> Value<'tcx> {
}
self.valtree.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
}
/// Get the values inside the ValTree as a slice of bytes. This only works for
/// constants with types &str, &[u8], or [u8; _].
pub fn try_to_raw_bytes(self, tcx: TyCtxt<'tcx>) -> Option<&'tcx [u8]> {
match self.ty.kind() {
ty::Ref(_, inner_ty, _) => match inner_ty.kind() {
// `&str` can be interpreted as raw bytes
ty::Str => {}
// `&[u8]` can be interpreted as raw bytes
ty::Slice(slice_ty) if *slice_ty == tcx.types.u8 => {}
// other `&_` can't be interpreted as raw bytes
_ => return None,
},
// `[u8; N]` can be interpreted as raw bytes
ty::Array(array_ty, _) if *array_ty == tcx.types.u8 => {}
// Otherwise, type cannot be interpreted as raw bytes
_ => return None,
}
Some(tcx.arena.alloc_from_iter(
self.valtree.unwrap_branch().into_iter().map(|v| v.unwrap_leaf().to_u8()),
))
}
}
impl<'tcx> rustc_type_ir::inherent::ValueConst<TyCtxt<'tcx>> for Value<'tcx> {

View file

@ -1801,8 +1801,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
match (cv.valtree, cv.ty.kind()) {
(ty::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) => match inner_ty.kind() {
ty::Slice(t) if *t == u8_type => {
let bytes =
cv.valtree.try_to_raw_bytes(self.tcx(), cv.ty).unwrap_or_else(|| {
let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
bug!(
"expected to convert valtree {:?} to raw bytes for type {:?}",
cv.valtree,
@ -1812,8 +1811,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
return self.pretty_print_byte_str(bytes);
}
ty::Str => {
let bytes =
cv.valtree.try_to_raw_bytes(self.tcx(), cv.ty).unwrap_or_else(|| {
let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
bug!("expected to convert valtree to raw bytes for type {:?}", cv.ty)
});
p!(write("{:?}", String::from_utf8_lossy(bytes)));
@ -1827,7 +1825,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
}
},
(ty::ValTree::Branch(_), ty::Array(t, _)) if *t == u8_type => {
let bytes = cv.valtree.try_to_raw_bytes(self.tcx(), cv.ty).unwrap_or_else(|| {
let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
bug!("expected to convert valtree to raw bytes for type {:?}", t)
});
p!("*");

View file

@ -649,7 +649,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
// HACK(jaic1): hide the `str` type behind a reference
// for the following transformation from valtree to raw bytes
let ref_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, ct_ty);
let slice = valtree.try_to_raw_bytes(tcx, ref_ty).unwrap_or_else(|| {
let cv = ty::Value { ty: ref_ty, valtree };
let slice = cv.try_to_raw_bytes(tcx).unwrap_or_else(|| {
bug!("expected to get raw bytes from valtree {:?} for type {:}", valtree, ct_ty)
});
let s = std::str::from_utf8(slice).expect("non utf8 str from MIR interpreter");