1use std::fmt::{self, Debug, Display, Formatter};
2
3use rustc_abi::{HasDataLayout, Size};
4use rustc_hir::def_id::DefId;
5use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
6use rustc_span::{DUMMY_SP, RemapPathScopeComponents, Span, Symbol};
7use rustc_type_ir::TypeVisitableExt;
8
9use super::interpret::ReportedErrorInfo;
10use crate::mir::interpret::{AllocId, AllocRange, ErrorHandled, GlobalAlloc, Scalar, alloc_range};
11use crate::mir::{Promoted, pretty_print_const_value};
12use crate::ty::print::{pretty_print_const, with_no_trimmed_paths};
13use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt};
14
15#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for ConstAlloc<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for ConstAlloc<'tcx> {
#[inline]
fn clone(&self) -> ConstAlloc<'tcx> {
let _: ::core::clone::AssertParamIsClone<AllocId>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
*self
}
}Clone, const _: () =
{
impl<'tcx, '__ctx>
::rustc_data_structures::stable_hasher::HashStable<::rustc_query_system::ich::StableHashingContext<'__ctx>>
for ConstAlloc<'tcx> {
#[inline]
fn hash_stable(&self,
__hcx:
&mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
match *self {
ConstAlloc { alloc_id: ref __binding_0, ty: ref __binding_1
} => {
{ __binding_0.hash_stable(__hcx, __hasher); }
{ __binding_1.hash_stable(__hcx, __hasher); }
}
}
}
}
};HashStable, const _: () =
{
impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
::rustc_serialize::Encodable<__E> for ConstAlloc<'tcx> {
fn encode(&self, __encoder: &mut __E) {
match *self {
ConstAlloc { alloc_id: ref __binding_0, ty: ref __binding_1
} => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
}
}
}
};TyEncodable, const _: () =
{
impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
::rustc_serialize::Decodable<__D> for ConstAlloc<'tcx> {
fn decode(__decoder: &mut __D) -> Self {
ConstAlloc {
alloc_id: ::rustc_serialize::Decodable::decode(__decoder),
ty: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};TyDecodable, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for ConstAlloc<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "ConstAlloc",
"alloc_id", &self.alloc_id, "ty", &&self.ty)
}
}Debug, #[automatically_derived]
impl<'tcx> ::core::hash::Hash for ConstAlloc<'tcx> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.alloc_id, state);
::core::hash::Hash::hash(&self.ty, state)
}
}Hash, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for ConstAlloc<'tcx> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<AllocId>;
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
}
}Eq, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for ConstAlloc<'tcx> {
#[inline]
fn eq(&self, other: &ConstAlloc<'tcx>) -> bool {
self.alloc_id == other.alloc_id && self.ty == other.ty
}
}PartialEq)]
22pub struct ConstAlloc<'tcx> {
23 pub alloc_id: AllocId,
26 pub ty: Ty<'tcx>,
27}
28
29#[derive(#[automatically_derived]
impl ::core::marker::Copy for ConstValue { }Copy, #[automatically_derived]
impl ::core::clone::Clone for ConstValue {
#[inline]
fn clone(&self) -> ConstValue {
let _: ::core::clone::AssertParamIsClone<Scalar>;
let _: ::core::clone::AssertParamIsClone<AllocId>;
let _: ::core::clone::AssertParamIsClone<u64>;
let _: ::core::clone::AssertParamIsClone<Size>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for ConstValue {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
ConstValue::Scalar(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Scalar",
&__self_0),
ConstValue::ZeroSized =>
::core::fmt::Formatter::write_str(f, "ZeroSized"),
ConstValue::Slice { alloc_id: __self_0, meta: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f, "Slice",
"alloc_id", __self_0, "meta", &__self_1),
ConstValue::Indirect { alloc_id: __self_0, offset: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Indirect", "alloc_id", __self_0, "offset", &__self_1),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::Eq for ConstValue {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Scalar>;
let _: ::core::cmp::AssertParamIsEq<AllocId>;
let _: ::core::cmp::AssertParamIsEq<u64>;
let _: ::core::cmp::AssertParamIsEq<Size>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for ConstValue {
#[inline]
fn eq(&self, other: &ConstValue) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(ConstValue::Scalar(__self_0), ConstValue::Scalar(__arg1_0))
=> __self_0 == __arg1_0,
(ConstValue::Slice { alloc_id: __self_0, meta: __self_1 },
ConstValue::Slice { alloc_id: __arg1_0, meta: __arg1_1 }) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
(ConstValue::Indirect { alloc_id: __self_0, offset: __self_1
}, ConstValue::Indirect {
alloc_id: __arg1_0, offset: __arg1_1 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
_ => true,
}
}
}PartialEq, const _: () =
{
impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
::rustc_serialize::Encodable<__E> for ConstValue {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
ConstValue::Scalar(ref __binding_0) => { 0usize }
ConstValue::ZeroSized => { 1usize }
ConstValue::Slice {
alloc_id: ref __binding_0, meta: ref __binding_1 } => {
2usize
}
ConstValue::Indirect {
alloc_id: ref __binding_0, offset: ref __binding_1 } => {
3usize
}
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
ConstValue::Scalar(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
ConstValue::ZeroSized => {}
ConstValue::Slice {
alloc_id: ref __binding_0, meta: ref __binding_1 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
ConstValue::Indirect {
alloc_id: ref __binding_0, offset: ref __binding_1 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
}
}
}
};TyEncodable, const _: () =
{
impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
::rustc_serialize::Decodable<__D> for ConstValue {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => {
ConstValue::Scalar(::rustc_serialize::Decodable::decode(__decoder))
}
1usize => { ConstValue::ZeroSized }
2usize => {
ConstValue::Slice {
alloc_id: ::rustc_serialize::Decodable::decode(__decoder),
meta: ::rustc_serialize::Decodable::decode(__decoder),
}
}
3usize => {
ConstValue::Indirect {
alloc_id: ::rustc_serialize::Decodable::decode(__decoder),
offset: ::rustc_serialize::Decodable::decode(__decoder),
}
}
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `ConstValue`, expected 0..4, actual {0}",
n));
}
}
}
}
};TyDecodable, #[automatically_derived]
impl ::core::hash::Hash for ConstValue {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
ConstValue::Scalar(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
ConstValue::Slice { alloc_id: __self_0, meta: __self_1 } => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
ConstValue::Indirect { alloc_id: __self_0, offset: __self_1 } => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
_ => {}
}
}
}Hash)]
32#[derive(const _: () =
{
impl<'__ctx>
::rustc_data_structures::stable_hasher::HashStable<::rustc_query_system::ich::StableHashingContext<'__ctx>>
for ConstValue {
#[inline]
fn hash_stable(&self,
__hcx:
&mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
match *self {
ConstValue::Scalar(ref __binding_0) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
ConstValue::ZeroSized => {}
ConstValue::Slice {
alloc_id: ref __binding_0, meta: ref __binding_1 } => {
{ __binding_0.hash_stable(__hcx, __hasher); }
{ __binding_1.hash_stable(__hcx, __hasher); }
}
ConstValue::Indirect {
alloc_id: ref __binding_0, offset: ref __binding_1 } => {
{ __binding_0.hash_stable(__hcx, __hasher); }
{ __binding_1.hash_stable(__hcx, __hasher); }
}
}
}
}
};HashStable)]
33pub enum ConstValue {
34 Scalar(Scalar),
38
39 ZeroSized,
41
42 Slice {
49 alloc_id: AllocId,
52 meta: u64,
55 },
56
57 Indirect {
61 alloc_id: AllocId,
68 offset: Size,
70 },
71}
72
73#[cfg(target_pointer_width = "64")]
74const _: [(); 24] = [(); ::std::mem::size_of::<ConstValue>()];rustc_data_structures::static_assert_size!(ConstValue, 24);
75
76impl ConstValue {
77 #[inline]
78 pub fn try_to_scalar(&self) -> Option<Scalar> {
79 match *self {
80 ConstValue::Indirect { .. } | ConstValue::Slice { .. } | ConstValue::ZeroSized => None,
81 ConstValue::Scalar(val) => Some(val),
82 }
83 }
84
85 pub fn try_to_scalar_int(&self) -> Option<ScalarInt> {
86 self.try_to_scalar()?.try_to_scalar_int().ok()
87 }
88
89 pub fn try_to_bits(&self, size: Size) -> Option<u128> {
90 Some(self.try_to_scalar_int()?.to_bits(size))
91 }
92
93 pub fn try_to_bool(&self) -> Option<bool> {
94 self.try_to_scalar_int()?.try_into().ok()
95 }
96
97 pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Option<u64> {
98 Some(self.try_to_scalar_int()?.to_target_usize(tcx))
99 }
100
101 pub fn try_to_bits_for_ty<'tcx>(
102 &self,
103 tcx: TyCtxt<'tcx>,
104 typing_env: ty::TypingEnv<'tcx>,
105 ty: Ty<'tcx>,
106 ) -> Option<u128> {
107 let size = tcx
108 .layout_of(typing_env.with_post_analysis_normalized(tcx).as_query_input(ty))
109 .ok()?
110 .size;
111 self.try_to_bits(size)
112 }
113
114 pub fn from_bool(b: bool) -> Self {
115 ConstValue::Scalar(Scalar::from_bool(b))
116 }
117
118 pub fn from_u64(i: u64) -> Self {
119 ConstValue::Scalar(Scalar::from_u64(i))
120 }
121
122 pub fn from_u128(i: u128) -> Self {
123 ConstValue::Scalar(Scalar::from_u128(i))
124 }
125
126 pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
127 ConstValue::Scalar(Scalar::from_target_usize(i, cx))
128 }
129
130 pub fn try_get_slice_bytes_for_diagnostics<'tcx>(
132 &self,
133 tcx: TyCtxt<'tcx>,
134 ) -> Option<&'tcx [u8]> {
135 let (alloc_id, start, len) = match self {
136 ConstValue::Scalar(_) | ConstValue::ZeroSized => {
137 crate::util::bug::bug_fmt(format_args!("`try_get_slice_bytes` on non-slice constant"))bug!("`try_get_slice_bytes` on non-slice constant")
138 }
139 &ConstValue::Slice { alloc_id, meta } => (alloc_id, 0, meta),
140 &ConstValue::Indirect { alloc_id, offset } => {
141 let a = tcx.global_alloc(alloc_id).unwrap_memory().inner();
144 let ptr_size = tcx.data_layout.pointer_size();
145 if a.size() < offset + 2 * ptr_size {
146 return None;
148 }
149 let ptr = a
151 .read_scalar(
152 &tcx,
153 alloc_range(offset, ptr_size),
154 true,
155 )
156 .ok()?;
157 let ptr = ptr.to_pointer(&tcx).discard_err()?;
158 let len = a
159 .read_scalar(
160 &tcx,
161 alloc_range(offset + ptr_size, ptr_size),
162 false,
163 )
164 .ok()?;
165 let len = len.to_target_usize(&tcx).discard_err()?;
166 if len == 0 {
167 return Some(&[]);
168 }
169 let (inner_prov, offset) =
171 ptr.into_pointer_or_addr().ok()?.prov_and_relative_offset();
172 (inner_prov.alloc_id(), offset.bytes(), len)
173 }
174 };
175
176 let data = tcx.global_alloc(alloc_id).unwrap_memory();
177
178 let start = start.try_into().unwrap();
180 let end = start + usize::try_from(len).unwrap();
181 Some(data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end))
182 }
183
184 pub fn may_have_provenance(&self, tcx: TyCtxt<'_>, size: Size) -> bool {
187 match *self {
188 ConstValue::ZeroSized | ConstValue::Scalar(Scalar::Int(_)) => return false,
189 ConstValue::Scalar(Scalar::Ptr(..)) => return true,
190 ConstValue::Slice { alloc_id, meta: _ } => {
193 !tcx.global_alloc(alloc_id).unwrap_memory().inner().provenance().ptrs().is_empty()
194 }
195 ConstValue::Indirect { alloc_id, offset } => !tcx
196 .global_alloc(alloc_id)
197 .unwrap_memory()
198 .inner()
199 .provenance()
200 .range_empty(AllocRange::from(offset..offset + size), &tcx),
201 }
202 }
203
204 pub fn all_bytes_uninit(&self, tcx: TyCtxt<'_>) -> bool {
206 let ConstValue::Indirect { alloc_id, .. } = self else {
207 return false;
208 };
209 let alloc = tcx.global_alloc(*alloc_id);
210 let GlobalAlloc::Memory(alloc) = alloc else {
211 return false;
212 };
213 let init_mask = alloc.0.init_mask();
214 let init_range = init_mask.is_range_initialized(AllocRange {
215 start: Size::ZERO,
216 size: Size::from_bytes(alloc.0.len()),
217 });
218 if let Err(range) = init_range {
219 if range.size == alloc.0.size() {
220 return true;
221 }
222 }
223 false
224 }
225}
226
227#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for Const<'tcx> {
#[inline]
fn clone(&self) -> Const<'tcx> {
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<ty::Const<'tcx>>;
let _: ::core::clone::AssertParamIsClone<UnevaluatedConst<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<ConstValue>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for Const<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for Const<'tcx> {
#[inline]
fn eq(&self, other: &Const<'tcx>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Const::Ty(__self_0, __self_1), Const::Ty(__arg1_0, __arg1_1))
=> __self_0 == __arg1_0 && __self_1 == __arg1_1,
(Const::Unevaluated(__self_0, __self_1),
Const::Unevaluated(__arg1_0, __arg1_1)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(Const::Val(__self_0, __self_1),
Const::Val(__arg1_0, __arg1_1)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for Const<'tcx> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<ty::Const<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<UnevaluatedConst<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<ConstValue>;
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
}
}Eq, const _: () =
{
impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
::rustc_serialize::Encodable<__E> for Const<'tcx> {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Const::Ty(ref __binding_0, ref __binding_1) => { 0usize }
Const::Unevaluated(ref __binding_0, ref __binding_1) => {
1usize
}
Const::Val(ref __binding_0, ref __binding_1) => { 2usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
Const::Ty(ref __binding_0, ref __binding_1) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
Const::Unevaluated(ref __binding_0, ref __binding_1) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
Const::Val(ref __binding_0, ref __binding_1) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
}
}
}
};TyEncodable, const _: () =
{
impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
::rustc_serialize::Decodable<__D> for Const<'tcx> {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => {
Const::Ty(::rustc_serialize::Decodable::decode(__decoder),
::rustc_serialize::Decodable::decode(__decoder))
}
1usize => {
Const::Unevaluated(::rustc_serialize::Decodable::decode(__decoder),
::rustc_serialize::Decodable::decode(__decoder))
}
2usize => {
Const::Val(::rustc_serialize::Decodable::decode(__decoder),
::rustc_serialize::Decodable::decode(__decoder))
}
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Const`, expected 0..3, actual {0}",
n));
}
}
}
}
};TyDecodable, #[automatically_derived]
impl<'tcx> ::core::hash::Hash for Const<'tcx> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
Const::Ty(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Const::Unevaluated(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Const::Val(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
}
}
}Hash, const _: () =
{
impl<'tcx, '__ctx>
::rustc_data_structures::stable_hasher::HashStable<::rustc_query_system::ich::StableHashingContext<'__ctx>>
for Const<'tcx> {
#[inline]
fn hash_stable(&self,
__hcx:
&mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
match *self {
Const::Ty(ref __binding_0, ref __binding_1) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
{ __binding_1.hash_stable(__hcx, __hasher); }
}
Const::Unevaluated(ref __binding_0, ref __binding_1) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
{ __binding_1.hash_stable(__hcx, __hasher); }
}
Const::Val(ref __binding_0, ref __binding_1) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
{ __binding_1.hash_stable(__hcx, __hasher); }
}
}
}
}
};HashStable, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for Const<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Const::Ty(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f, "Ty",
__self_0, &__self_1),
Const::Unevaluated(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f,
"Unevaluated", __self_0, &__self_1),
Const::Val(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f, "Val",
__self_0, &__self_1),
}
}
}Debug)]
231#[derive(const _: () =
{
impl<'tcx>
::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>
for Const<'tcx> {
fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
__folder: &mut __F) -> Result<Self, __F::Error> {
Ok(match self {
Const::Ty(__binding_0, __binding_1) => {
Const::Ty(::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_0,
__folder)?,
::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_1,
__folder)?)
}
Const::Unevaluated(__binding_0, __binding_1) => {
Const::Unevaluated(::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_0,
__folder)?,
::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_1,
__folder)?)
}
Const::Val(__binding_0, __binding_1) => {
Const::Val(::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_0,
__folder)?,
::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_1,
__folder)?)
}
})
}
fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
__folder: &mut __F) -> Self {
match self {
Const::Ty(__binding_0, __binding_1) => {
Const::Ty(::rustc_middle::ty::TypeFoldable::fold_with(__binding_0,
__folder),
::rustc_middle::ty::TypeFoldable::fold_with(__binding_1,
__folder))
}
Const::Unevaluated(__binding_0, __binding_1) => {
Const::Unevaluated(::rustc_middle::ty::TypeFoldable::fold_with(__binding_0,
__folder),
::rustc_middle::ty::TypeFoldable::fold_with(__binding_1,
__folder))
}
Const::Val(__binding_0, __binding_1) => {
Const::Val(::rustc_middle::ty::TypeFoldable::fold_with(__binding_0,
__folder),
::rustc_middle::ty::TypeFoldable::fold_with(__binding_1,
__folder))
}
}
}
}
};TypeFoldable, const _: () =
{
impl<'tcx>
::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>
for Const<'tcx> {
fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(&self,
__visitor: &mut __V) -> __V::Result {
match *self {
Const::Ty(ref __binding_0, ref __binding_1) => {
{
match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_middle::ty::VisitorResult::from_residual(r);
}
}
}
{
match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_1,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_middle::ty::VisitorResult::from_residual(r);
}
}
}
}
Const::Unevaluated(ref __binding_0, ref __binding_1) => {
{
match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_middle::ty::VisitorResult::from_residual(r);
}
}
}
{
match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_1,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_middle::ty::VisitorResult::from_residual(r);
}
}
}
}
Const::Val(ref __binding_0, ref __binding_1) => {
{
match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_middle::ty::VisitorResult::from_residual(r);
}
}
}
{
match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_1,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_middle::ty::VisitorResult::from_residual(r);
}
}
}
}
}
<__V::Result as ::rustc_middle::ty::VisitorResult>::output()
}
}
};TypeVisitable, const _: () =
{
impl<'tcx, '__lifted>
::rustc_middle::ty::Lift<::rustc_middle::ty::TyCtxt<'__lifted>>
for Const<'tcx> {
type Lifted = Const<'__lifted>;
fn lift_to_interner(self,
__tcx: ::rustc_middle::ty::TyCtxt<'__lifted>)
-> Option<Const<'__lifted>> {
Some(match self {
Const::Ty(__binding_0, __binding_1) => {
Const::Ty(__tcx.lift(__binding_0)?,
__tcx.lift(__binding_1)?)
}
Const::Unevaluated(__binding_0, __binding_1) => {
Const::Unevaluated(__tcx.lift(__binding_0)?,
__tcx.lift(__binding_1)?)
}
Const::Val(__binding_0, __binding_1) => {
Const::Val(__tcx.lift(__binding_0)?,
__tcx.lift(__binding_1)?)
}
})
}
}
};Lift)]
232pub enum Const<'tcx> {
233 Ty(Ty<'tcx>, ty::Const<'tcx>),
241
242 Unevaluated(UnevaluatedConst<'tcx>, Ty<'tcx>),
249
250 Val(ConstValue, Ty<'tcx>),
253}
254
255impl<'tcx> Const<'tcx> {
256 pub fn from_unevaluated(
259 tcx: TyCtxt<'tcx>,
260 def_id: DefId,
261 ) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
262 ty::EarlyBinder::bind(Const::Unevaluated(
263 UnevaluatedConst {
264 def: def_id,
265 args: ty::GenericArgs::identity_for_item(tcx, def_id),
266 promoted: None,
267 },
268 tcx.type_of(def_id).skip_binder(),
269 ))
270 }
271
272 #[inline(always)]
273 pub fn ty(&self) -> Ty<'tcx> {
274 match self {
275 Const::Ty(ty, ct) => {
276 match ct.kind() {
277 ty::ConstKind::Value(cv) => cv.ty,
281 _ => *ty,
282 }
283 }
284 Const::Val(_, ty) | Const::Unevaluated(_, ty) => *ty,
285 }
286 }
287
288 #[inline]
291 pub fn is_required_const(&self) -> bool {
292 match self {
293 Const::Ty(_, c) => match c.kind() {
294 ty::ConstKind::Value(_) => false, _ => true,
296 },
297 Const::Val(..) => false, Const::Unevaluated(..) => true,
299 }
300 }
301
302 #[inline]
303 pub fn try_to_scalar(self) -> Option<Scalar> {
304 match self {
305 Const::Ty(_, c) => c.try_to_scalar(),
306 Const::Val(val, _) => val.try_to_scalar(),
307 Const::Unevaluated(..) => None,
308 }
309 }
310
311 #[inline]
312 pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
313 match self {
315 Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
316 Const::Ty(_, c) => c.try_to_leaf(),
317 _ => None,
318 }
319 }
320
321 #[inline]
322 pub fn try_to_bits(self, size: Size) -> Option<u128> {
323 Some(self.try_to_scalar_int()?.to_bits(size))
324 }
325
326 #[inline]
327 pub fn try_to_bool(self) -> Option<bool> {
328 self.try_to_scalar_int()?.try_into().ok()
329 }
330
331 #[inline]
332 pub fn eval(
333 self,
334 tcx: TyCtxt<'tcx>,
335 typing_env: ty::TypingEnv<'tcx>,
336 span: Span,
337 ) -> Result<ConstValue, ErrorHandled> {
338 match self {
339 Const::Ty(_, c) => {
340 if c.has_non_region_param() {
341 return Err(ErrorHandled::TooGeneric(span));
342 }
343
344 match c.kind() {
345 ConstKind::Value(cv) => Ok(tcx.valtree_to_const_val(cv)),
346 ConstKind::Expr(_) => {
347 crate::util::bug::bug_fmt(format_args!("Normalization of `ty::ConstKind::Expr` is unimplemented"))bug!("Normalization of `ty::ConstKind::Expr` is unimplemented")
348 }
349 _ => Err(ReportedErrorInfo::non_const_eval_error(
350 tcx.dcx().delayed_bug("Unevaluated `ty::Const` in MIR body"),
351 )
352 .into()),
353 }
354 }
355 Const::Unevaluated(uneval, _) => {
356 tcx.const_eval_resolve(typing_env, uneval, span)
358 }
359 Const::Val(val, _) => Ok(val),
360 }
361 }
362
363 #[inline]
364 pub fn try_eval_scalar(
365 self,
366 tcx: TyCtxt<'tcx>,
367 typing_env: ty::TypingEnv<'tcx>,
368 ) -> Option<Scalar> {
369 if let Const::Ty(_, c) = self {
370 c.try_to_scalar()
373 } else {
374 self.eval(tcx, typing_env, DUMMY_SP).ok()?.try_to_scalar()
375 }
376 }
377
378 #[inline]
379 pub fn try_eval_scalar_int(
380 self,
381 tcx: TyCtxt<'tcx>,
382 typing_env: ty::TypingEnv<'tcx>,
383 ) -> Option<ScalarInt> {
384 self.try_eval_scalar(tcx, typing_env)?.try_to_scalar_int().ok()
385 }
386
387 #[inline]
388 pub fn try_eval_bits(
389 &self,
390 tcx: TyCtxt<'tcx>,
391 typing_env: ty::TypingEnv<'tcx>,
392 ) -> Option<u128> {
393 let int = self.try_eval_scalar_int(tcx, typing_env)?;
394 let size = tcx
395 .layout_of(typing_env.with_post_analysis_normalized(tcx).as_query_input(self.ty()))
396 .ok()?
397 .size;
398 Some(int.to_bits(size))
399 }
400
401 #[inline]
403 pub fn eval_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u128 {
404 self.try_eval_bits(tcx, typing_env)
405 .unwrap_or_else(|| crate::util::bug::bug_fmt(format_args!("expected bits of {0:#?}, got {1:#?}",
self.ty(), self))bug!("expected bits of {:#?}, got {:#?}", self.ty(), self))
406 }
407
408 #[inline]
409 pub fn try_eval_target_usize(
410 self,
411 tcx: TyCtxt<'tcx>,
412 typing_env: ty::TypingEnv<'tcx>,
413 ) -> Option<u64> {
414 Some(self.try_eval_scalar_int(tcx, typing_env)?.to_target_usize(tcx))
415 }
416
417 #[inline]
418 pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u64 {
420 self.try_eval_target_usize(tcx, typing_env)
421 .unwrap_or_else(|| crate::util::bug::bug_fmt(format_args!("expected usize, got {0:#?}", self))bug!("expected usize, got {:#?}", self))
422 }
423
424 #[inline]
425 pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<bool> {
426 self.try_eval_scalar_int(tcx, typing_env)?.try_into().ok()
427 }
428
429 #[inline]
430 pub fn from_value(val: ConstValue, ty: Ty<'tcx>) -> Self {
431 Self::Val(val, ty)
432 }
433
434 #[inline]
435 pub fn from_ty_value(tcx: TyCtxt<'tcx>, val: ty::Value<'tcx>) -> Self {
436 Self::Ty(val.ty, ty::Const::new_value(tcx, val.valtree, val.ty))
437 }
438
439 pub fn from_bits(
440 tcx: TyCtxt<'tcx>,
441 bits: u128,
442 typing_env: ty::TypingEnv<'tcx>,
443 ty: Ty<'tcx>,
444 ) -> Self {
445 let size = tcx
446 .layout_of(typing_env.as_query_input(ty))
447 .unwrap_or_else(|e| crate::util::bug::bug_fmt(format_args!("could not compute layout for {0:?}: {1:?}",
ty, e))bug!("could not compute layout for {ty:?}: {e:?}"))
448 .size;
449 let cv = ConstValue::Scalar(Scalar::from_uint(bits, size));
450
451 Self::Val(cv, ty)
452 }
453
454 #[inline]
455 pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
456 let cv = ConstValue::from_bool(v);
457 Self::Val(cv, tcx.types.bool)
458 }
459
460 #[inline]
461 pub fn zero_sized(ty: Ty<'tcx>) -> Self {
462 let cv = ConstValue::ZeroSized;
463 Self::Val(cv, ty)
464 }
465
466 pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
467 let ty = tcx.types.usize;
468 let typing_env = ty::TypingEnv::fully_monomorphized();
469 Self::from_bits(tcx, n as u128, typing_env, ty)
470 }
471
472 #[inline]
473 pub fn from_scalar(_tcx: TyCtxt<'tcx>, s: Scalar, ty: Ty<'tcx>) -> Self {
474 let val = ConstValue::Scalar(s);
475 Self::Val(val, ty)
476 }
477
478 pub fn is_deterministic(&self) -> bool {
481 match self {
485 Const::Ty(_, c) => match c.kind() {
486 ty::ConstKind::Param(..) => true,
487 ty::ConstKind::Value(cv) => cv.ty.is_primitive(),
491 ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false,
492 ty::ConstKind::Error(..) => false,
495 ty::ConstKind::Infer(..)
497 | ty::ConstKind::Bound(..)
498 | ty::ConstKind::Placeholder(..) => crate::util::bug::bug_fmt(format_args!("impossible case reached"))bug!(),
499 },
500 Const::Unevaluated(..) => false,
501 Const::Val(
502 ConstValue::Slice { .. }
503 | ConstValue::ZeroSized
504 | ConstValue::Scalar(_)
505 | ConstValue::Indirect { .. },
506 _,
507 ) => true,
508 }
509 }
510}
511
512#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for UnevaluatedConst<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for UnevaluatedConst<'tcx> {
#[inline]
fn clone(&self) -> UnevaluatedConst<'tcx> {
let _: ::core::clone::AssertParamIsClone<DefId>;
let _: ::core::clone::AssertParamIsClone<GenericArgsRef<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Option<Promoted>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for UnevaluatedConst<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"UnevaluatedConst", "def", &self.def, "args", &self.args,
"promoted", &&self.promoted)
}
}Debug, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for UnevaluatedConst<'tcx> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<DefId>;
let _: ::core::cmp::AssertParamIsEq<GenericArgsRef<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<Option<Promoted>>;
}
}Eq, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for UnevaluatedConst<'tcx> {
#[inline]
fn eq(&self, other: &UnevaluatedConst<'tcx>) -> bool {
self.def == other.def && self.args == other.args &&
self.promoted == other.promoted
}
}PartialEq, const _: () =
{
impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
::rustc_serialize::Encodable<__E> for UnevaluatedConst<'tcx> {
fn encode(&self, __encoder: &mut __E) {
match *self {
UnevaluatedConst {
def: ref __binding_0,
args: ref __binding_1,
promoted: ref __binding_2 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_2,
__encoder);
}
}
}
}
};TyEncodable, const _: () =
{
impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
::rustc_serialize::Decodable<__D> for UnevaluatedConst<'tcx> {
fn decode(__decoder: &mut __D) -> Self {
UnevaluatedConst {
def: ::rustc_serialize::Decodable::decode(__decoder),
args: ::rustc_serialize::Decodable::decode(__decoder),
promoted: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};TyDecodable)]
514#[derive(#[automatically_derived]
impl<'tcx> ::core::hash::Hash for UnevaluatedConst<'tcx> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.def, state);
::core::hash::Hash::hash(&self.args, state);
::core::hash::Hash::hash(&self.promoted, state)
}
}Hash, const _: () =
{
impl<'tcx, '__ctx>
::rustc_data_structures::stable_hasher::HashStable<::rustc_query_system::ich::StableHashingContext<'__ctx>>
for UnevaluatedConst<'tcx> {
#[inline]
fn hash_stable(&self,
__hcx:
&mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
match *self {
UnevaluatedConst {
def: ref __binding_0,
args: ref __binding_1,
promoted: ref __binding_2 } => {
{ __binding_0.hash_stable(__hcx, __hasher); }
{ __binding_1.hash_stable(__hcx, __hasher); }
{ __binding_2.hash_stable(__hcx, __hasher); }
}
}
}
}
};HashStable, const _: () =
{
impl<'tcx>
::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>
for UnevaluatedConst<'tcx> {
fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
__folder: &mut __F) -> Result<Self, __F::Error> {
Ok(match self {
UnevaluatedConst {
def: __binding_0, args: __binding_1, promoted: __binding_2 }
=> {
UnevaluatedConst {
def: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_0,
__folder)?,
args: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_1,
__folder)?,
promoted: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_2,
__folder)?,
}
}
})
}
fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
__folder: &mut __F) -> Self {
match self {
UnevaluatedConst {
def: __binding_0, args: __binding_1, promoted: __binding_2 }
=> {
UnevaluatedConst {
def: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_0,
__folder),
args: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_1,
__folder),
promoted: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_2,
__folder),
}
}
}
}
}
};TypeFoldable, const _: () =
{
impl<'tcx>
::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>
for UnevaluatedConst<'tcx> {
fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(&self,
__visitor: &mut __V) -> __V::Result {
match *self {
UnevaluatedConst {
def: ref __binding_0,
args: ref __binding_1,
promoted: ref __binding_2 } => {
{
match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_middle::ty::VisitorResult::from_residual(r);
}
}
}
{
match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_1,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_middle::ty::VisitorResult::from_residual(r);
}
}
}
{
match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_2,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_middle::ty::VisitorResult::from_residual(r);
}
}
}
}
}
<__V::Result as ::rustc_middle::ty::VisitorResult>::output()
}
}
};TypeVisitable, const _: () =
{
impl<'tcx, '__lifted>
::rustc_middle::ty::Lift<::rustc_middle::ty::TyCtxt<'__lifted>>
for UnevaluatedConst<'tcx> {
type Lifted = UnevaluatedConst<'__lifted>;
fn lift_to_interner(self,
__tcx: ::rustc_middle::ty::TyCtxt<'__lifted>)
-> Option<UnevaluatedConst<'__lifted>> {
Some(match self {
UnevaluatedConst {
def: __binding_0, args: __binding_1, promoted: __binding_2 }
=> {
UnevaluatedConst {
def: __tcx.lift(__binding_0)?,
args: __tcx.lift(__binding_1)?,
promoted: __tcx.lift(__binding_2)?,
}
}
})
}
}
};Lift)]
515pub struct UnevaluatedConst<'tcx> {
516 pub def: DefId,
517 pub args: GenericArgsRef<'tcx>,
518 pub promoted: Option<Promoted>,
519}
520
521impl<'tcx> UnevaluatedConst<'tcx> {
522 #[inline]
523 pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> {
524 match (&self.promoted, &None) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(self.promoted, None);
525 ty::UnevaluatedConst { def: self.def, args: self.args }
526 }
527}
528
529impl<'tcx> UnevaluatedConst<'tcx> {
530 #[inline]
531 pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> {
532 UnevaluatedConst { def, args, promoted: Default::default() }
533 }
534
535 #[inline]
536 pub fn from_instance(instance: ty::Instance<'tcx>) -> Self {
537 UnevaluatedConst::new(instance.def_id(), instance.args)
538 }
539}
540
541impl<'tcx> Display for Const<'tcx> {
542 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
543 match *self {
544 Const::Ty(_, c) => pretty_print_const(c, fmt, true),
545 Const::Val(val, ty) => pretty_print_const_value(val, ty, fmt),
546 Const::Unevaluated(c, _ty) => {
548 ty::tls::with(move |tcx| {
549 let c = tcx.lift(c).unwrap();
550 let instance =
552 {
let _guard = NoTrimmedGuard::new();
tcx.def_path_str_with_args(c.def, c.args)
}with_no_trimmed_paths!(tcx.def_path_str_with_args(c.def, c.args));
553 fmt.write_fmt(format_args!("{0}", instance))write!(fmt, "{instance}")?;
554 if let Some(promoted) = c.promoted {
555 fmt.write_fmt(format_args!("::{0:?}", promoted))write!(fmt, "::{promoted:?}")?;
556 }
557 Ok(())
558 })
559 }
560 }
561 }
562}
563
564impl<'tcx> TyCtxt<'tcx> {
568 pub fn span_as_caller_location(self, span: Span) -> ConstValue {
569 let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
570 let caller = self.sess.source_map().lookup_char_pos(topmost.lo());
571 self.const_caller_location(
572 Symbol::intern(
573 &caller.file.name.display(RemapPathScopeComponents::MACRO).to_string_lossy(),
574 ),
575 caller.line as u32,
576 caller.col_display as u32 + 1,
577 )
578 }
579}