1use rustc_abi::Size;
2use rustc_ast::{self as ast, UintTy};
3use rustc_hir::LangItem;
4use rustc_middle::bug;
5use rustc_middle::ty::{self, LitToConstInput, ScalarInt, Ty, TyCtxt, TypeVisitableExt as _};
6use tracing::trace;
7
8use crate::builder::parse_float_into_scalar;
9
10pub(crate) fn lit_to_const<'tcx>(
11 tcx: TyCtxt<'tcx>,
12 lit_input: LitToConstInput<'tcx>,
13) -> Option<ty::Value<'tcx>> {
14 let LitToConstInput { lit, ty: expected_ty, neg } = lit_input;
15
16 if expected_ty.error_reported().is_err() {
17 return None;
18 }
19
20 let trunc = |n, width: ty::UintTy| {
21 let width = width
22 .normalize(tcx.data_layout.pointer_size().bits().try_into().unwrap())
23 .bit_width()
24 .unwrap();
25 let width = Size::from_bits(width);
26 {
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:26",
"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(26u32),
::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());
27 let result = width.truncate(n);
28 {
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:28",
"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(28u32),
::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);
29
30 ScalarInt::try_from_uint(result, width)
31 .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))
32 };
33
34 let (valtree, valtree_ty) = match (lit, expected_ty.kind()) {
35 (ast::LitKind::Str(s, _), _) => {
36 let str_bytes = s.as_str().as_bytes();
37 let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_);
38 (ty::ValTree::from_raw_bytes(tcx, str_bytes), valtree_ty)
39 }
40 (ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _))
41 if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind()
42 && let ty::Uint(UintTy::U8) = ty.kind() =>
43 {
44 (ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty)
45 }
46 (ast::LitKind::ByteStr(byte_sym, _), ty::Slice(inner_ty) | ty::Array(inner_ty, _))
47 if tcx.features().deref_patterns()
48 && let ty::Uint(UintTy::U8) = inner_ty.kind() =>
49 {
50 (ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty)
53 }
54 (ast::LitKind::ByteStr(byte_sym, _), _) => {
55 let valtree = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str());
56 let valtree_ty = Ty::new_array(tcx, tcx.types.u8, byte_sym.as_byte_str().len() as u64);
57 (valtree, valtree_ty)
58 }
59 (ast::LitKind::Byte(n), _) => (ty::ValTree::from_scalar_int(tcx, n.into()), tcx.types.u8),
60 (ast::LitKind::CStr(byte_sym, _), _)
61 if let Some(cstr_def_id) = tcx.lang_items().get(LangItem::CStr) =>
62 {
63 let cstr_ty = tcx.type_of(cstr_def_id).skip_binder();
66 let bytes = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str());
67 let valtree =
68 ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, bytes, cstr_ty)]);
69 let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, cstr_ty);
70 (valtree, valtree_ty)
71 }
72 (ast::LitKind::Int(n, ast::LitIntType::Unsigned(ui)), _) if !neg => {
73 let scalar_int = trunc(n.get(), ui);
74 (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, ui))
75 }
76 (ast::LitKind::Int(_, ast::LitIntType::Unsigned(_)), _) if neg => return None,
77 (ast::LitKind::Int(n, ast::LitIntType::Signed(i)), _) => {
78 let scalar_int =
79 trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned());
80 (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, i))
81 }
82 (ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Uint(ui)) if !neg => {
83 let scalar_int = trunc(n.get(), *ui);
84 (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, *ui))
85 }
86 (ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Int(i)) => {
87 let scalar_int =
90 trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned());
91 (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, *i))
92 }
93 (ast::LitKind::Bool(b), _) => (ty::ValTree::from_scalar_int(tcx, b.into()), tcx.types.bool),
94 (ast::LitKind::Float(n, ast::LitFloatType::Suffixed(fty)), _) => {
95 let fty = match fty {
96 ast::FloatTy::F16 => ty::FloatTy::F16,
97 ast::FloatTy::F32 => ty::FloatTy::F32,
98 ast::FloatTy::F64 => ty::FloatTy::F64,
99 ast::FloatTy::F128 => ty::FloatTy::F128,
100 };
101 let bits = parse_float_into_scalar(n, fty, neg)?;
102 (ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, fty))
103 }
104 (ast::LitKind::Float(n, ast::LitFloatType::Unsuffixed), ty::Float(fty)) => {
105 let bits = parse_float_into_scalar(n, *fty, neg)?;
106 (ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, *fty))
107 }
108 (ast::LitKind::Char(c), _) => (ty::ValTree::from_scalar_int(tcx, c.into()), tcx.types.char),
109 (ast::LitKind::Err(_), _) => return None,
110 _ => return None,
111 };
112
113 Some(ty::Value { ty: valtree_ty, valtree })
114}