1use rustc_abi::Size;
2use rustc_ast::{self as ast, UintTy};
3use rustc_hir::LangItem;
4use rustc_middle::bug;
5use rustc_middle::mir::interpret::LitToConstInput;
6use rustc_middle::ty::{self, ScalarInt, TyCtxt, TypeVisitableExt as _};
7use tracing::trace;
8
9use crate::builder::parse_float_into_scalar;
10
11pub(crate) fn lit_to_const<'tcx>(
12 tcx: TyCtxt<'tcx>,
13 lit_input: LitToConstInput<'tcx>,
14) -> ty::Const<'tcx> {
15 let LitToConstInput { lit, ty, neg } = lit_input;
16
17 if let Err(guar) = ty.error_reported() {
18 return ty::Const::new_error(tcx, guar);
19 }
20
21 let trunc = |n, width: ty::UintTy| {
22 let width = width
23 .normalize(tcx.data_layout.pointer_size().bits().try_into().unwrap())
24 .bit_width()
25 .unwrap();
26 let width = Size::from_bits(width);
27 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/constant.rs:27",
"rustc_mir_build::thir::constant", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/constant.rs"),
::tracing_core::__macro_support::Option::Some(27u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::constant"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("trunc {0} with size {1} and shift {2}",
n, width.bits(), 128 - width.bits()) as &dyn Value))])
});
} else { ; }
};trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
28 let result = width.truncate(n);
29 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/constant.rs:29",
"rustc_mir_build::thir::constant", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/constant.rs"),
::tracing_core::__macro_support::Option::Some(29u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::constant"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("trunc result: {0}",
result) as &dyn Value))])
});
} else { ; }
};trace!("trunc result: {}", result);
30
31 ScalarInt::try_from_uint(result, width)
32 .unwrap_or_else(|| ::rustc_middle::util::bug::bug_fmt(format_args!("expected to create ScalarInt from uint {0:?}",
result))bug!("expected to create ScalarInt from uint {:?}", result))
33 };
34
35 let valtree = match (lit, ty.kind()) {
36 (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
37 let str_bytes = s.as_str().as_bytes();
38 ty::ValTree::from_raw_bytes(tcx, str_bytes)
39 }
40 (ast::LitKind::Str(s, _), ty::Str) if tcx.features().deref_patterns() => {
41 let str_bytes = s.as_str().as_bytes();
44 ty::ValTree::from_raw_bytes(tcx, str_bytes)
45 }
46 (ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _))
47 if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind()
48 && let ty::Uint(UintTy::U8) = ty.kind() =>
49 {
50 ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str())
51 }
52 (ast::LitKind::ByteStr(byte_sym, _), ty::Slice(inner_ty) | ty::Array(inner_ty, _))
53 if tcx.features().deref_patterns()
54 && let ty::Uint(UintTy::U8) = inner_ty.kind() =>
55 {
56 ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str())
59 }
60 (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
61 ty::ValTree::from_scalar_int(tcx, n.into())
62 }
63 (ast::LitKind::CStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if #[allow(non_exhaustive_omitted_patterns)] match inner_ty.kind() {
ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr) => true,
_ => false,
}matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
64 {
65 let bytes = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str());
68 ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, bytes, *inner_ty)])
69 }
70 (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => {
71 let scalar_int = trunc(n.get(), *ui);
72 ty::ValTree::from_scalar_int(tcx, scalar_int)
73 }
74 (ast::LitKind::Int(n, _), ty::Int(i)) => {
75 let scalar_int = trunc(
76 if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() },
77 i.to_unsigned(),
78 );
79 ty::ValTree::from_scalar_int(tcx, scalar_int)
80 }
81 (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int(tcx, b.into()),
82 (ast::LitKind::Float(n, _), ty::Float(fty)) => {
83 let bits = parse_float_into_scalar(n, *fty, neg).unwrap_or_else(|| {
84 tcx.dcx().bug(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("couldn\'t parse float literal: {0:?}",
lit_input.lit))
})format!("couldn't parse float literal: {:?}", lit_input.lit))
85 });
86 ty::ValTree::from_scalar_int(tcx, bits)
87 }
88 (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int(tcx, c.into()),
89 (ast::LitKind::Err(guar), _) => return ty::Const::new_error(tcx, guar),
90 _ => return ty::Const::new_misc_error(tcx),
91 };
92
93 ty::Const::new_value(tcx, valtree, ty)
94}