1use rustc_abi::Size;
2use rustc_ast::{self as ast, UintTy};
3use rustc_attr_ir::lang_items::LangItem;
4use rustc_middle::ty::consts::ConstExt;
5use rustc_middle::ty::{self, LitToConstInput, ScalarInt, Ty, TyCtxt, TypeVisitableExt as _};
6use rustc_span::bug;
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) -> Option<ty::Value<'tcx>> {
15 let LitToConstInput { lit, ty: expected_ty, neg } = lit_input;
16
17 if expected_ty.error_reported().is_err() {
18 return None;
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 /rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/constant.rs:27",
"rustc_mir_build::thir::constant", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("trunc {0} with size {1} and shift {2}",
n, width.bits(), 128 - width.bits()) as
&dyn ::tracing::field::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 /rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/constant.rs:29",
"rustc_mir_build::thir::constant", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("trunc result: {0}",
result) as &dyn ::tracing::field::Value))])
});
} else { ; }
};trace!("trunc result: {}", result);
30
31 ScalarInt::try_from_uint(result, width)
32 .unwrap_or_else(|| ::rustc_span::macros::bug_impl(None,
format_args!("expected to create ScalarInt from uint {0:?}", result),
Location::caller())bug!("expected to create ScalarInt from uint {:?}", result))
33 };
34
35 let (valtree, valtree_ty) = match (lit, expected_ty.map(|ty| ty.kind())) {
36 (ast::LitKind::Str(s, _), _) => {
37 let str_bytes = s.as_str().as_bytes();
38 let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_);
39 (ty::ValTree::from_raw_bytes(tcx, str_bytes), valtree_ty)
40 }
41 (ast::LitKind::ByteStr(byte_sym, _), Some(ty::Ref(_, inner_ty, _)))
42 if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind()
43 && let ty::Uint(UintTy::U8) = ty.kind() =>
44 {
45 (ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty.unwrap())
46 }
47 (
48 ast::LitKind::ByteStr(byte_sym, _),
49 Some(ty::Slice(inner_ty) | ty::Array(inner_ty, _)),
50 ) if tcx.features().deref_patterns()
51 && let ty::Uint(UintTy::U8) = inner_ty.kind() =>
52 {
53 (ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty.unwrap())
56 }
57 (ast::LitKind::ByteStr(byte_sym, _), _) => {
58 let valtree = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str());
59 let valtree_ty = Ty::new_array(tcx, tcx.types.u8, byte_sym.as_byte_str().len() as u64);
60 (valtree, valtree_ty)
61 }
62 (ast::LitKind::Byte(n), _) => (ty::ValTree::from_scalar_int(tcx, n.into()), tcx.types.u8),
63 (ast::LitKind::CStr(byte_sym, _), _)
64 if let Some(cstr_def_id) = tcx.lang_items().get(LangItem::CStr) =>
65 {
66 let cstr_ty = tcx.type_of(cstr_def_id).skip_binder();
69 let bytes = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str());
70 let valtree =
71 ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, bytes, cstr_ty)]);
72 let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, cstr_ty);
73 (valtree, valtree_ty)
74 }
75 (ast::LitKind::Int(n, ast::LitIntType::Unsigned(ui)), _) if !neg => {
76 let scalar_int = trunc(n.get(), ui);
77 (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, ui))
78 }
79 (ast::LitKind::Int(_, ast::LitIntType::Unsigned(_)), _) if neg => return None,
80 (ast::LitKind::Int(n, ast::LitIntType::Signed(i)), _) => {
81 let scalar_int =
82 trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned());
83 (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, i))
84 }
85 (ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), Some(ty::Uint(ui))) if !neg => {
86 let scalar_int = trunc(n.get(), *ui);
87 (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, *ui))
88 }
89 (ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), Some(ty::Int(i))) => {
90 let scalar_int =
93 trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned());
94 (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, *i))
95 }
96 (ast::LitKind::Bool(b), _) => (ty::ValTree::from_scalar_int(tcx, b.into()), tcx.types.bool),
97 (ast::LitKind::Float(n, ast::LitFloatType::Suffixed(fty)), _) => {
98 let fty = match fty {
99 ast::FloatTy::F16 => ty::FloatTy::F16,
100 ast::FloatTy::F32 => ty::FloatTy::F32,
101 ast::FloatTy::F64 => ty::FloatTy::F64,
102 ast::FloatTy::F128 => ty::FloatTy::F128,
103 };
104 let bits = parse_float_into_scalar(n, fty, neg)?;
105 (ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, fty))
106 }
107 (ast::LitKind::Float(n, ast::LitFloatType::Unsuffixed), Some(ty::Float(fty))) => {
108 let bits = parse_float_into_scalar(n, *fty, neg)?;
109 (ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, *fty))
110 }
111 (ast::LitKind::Char(c), _) => (ty::ValTree::from_scalar_int(tcx, c.into()), tcx.types.char),
112 (ast::LitKind::Err(_), _) => return None,
113 _ => return None,
114 };
115
116 Some(ty::Value { ty: valtree_ty, valtree })
117}