1use std::{cmp, fmt};
2
3use rustc_abi as abi;
4use rustc_abi::{
5 AddressSpace, Align, ExternAbi, FieldIdx, FieldsShape, HasDataLayout, LayoutData, PointeeInfo,
6 PointerKind, Primitive, ReprFlags, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout,
7 TyAbiInterface, VariantIdx, Variants,
8};
9use rustc_attr_ir::lang_items::LangItem;
10use rustc_errors::{Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, IntoDiagArg, Level};
11use rustc_hir as hir;
12use rustc_hir::def_id::DefId;
13use rustc_macros::{StableHash, TyDecodable, TyEncodable, extension};
14use rustc_session::config::OptLevel;
15use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Spanned, Symbol, bug, span_bug, sym};
16use rustc_structures::Limit;
17use rustc_target::callconv::FnAbi;
18use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi};
19use tracing::debug;
20
21use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
22use crate::query::TyCtxtAt;
23use crate::traits::ObligationCause;
24use crate::ty::normalize_erasing_regions::NormalizationError;
25use crate::ty::{self, CoroutineArgsExt, Ty, TyCtxt, TypeVisitableExt, Unnormalized};
26
27pub trait IntegerExt {
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool)
-> Ty<'tcx>;
fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy)
-> abi::Integer;
fn from_uint_ty<C: HasDataLayout>(cx: &C, ity: ty::UintTy)
-> abi::Integer;
#[doc =
" Finds the appropriate Integer type and signedness for the given"]
#[doc = " discriminant range and `#[repr]` attribute."]
#[doc = ""]
#[doc =
" To represent the way the values were written in the rust source, min and max"]
#[doc =
" are in different types. It\'s thus possible to pass in an unrepresentable range,"]
#[doc = " and the method will panic in those cases."]
#[doc = ""]
#[doc =
" This is the basis for computing the type of the *tag* of an enum (which can be smaller than"]
#[doc =
" the type of the *discriminant*, which is determined by [`ReprOptions::discr_type`])."]
fn discr_range_of_repr<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>,
repr: &ReprOptions, min_negative: i128, max_positive: u128)
-> (abi::Integer, bool);
}
impl IntegerExt for abi::Integer {
#[inline]
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx> {
use abi::Integer::{I8, I16, I32, I64, I128};
match (*self, signed) {
(I8, false) => tcx.types.u8,
(I16, false) => tcx.types.u16,
(I32, false) => tcx.types.u32,
(I64, false) => tcx.types.u64,
(I128, false) => tcx.types.u128,
(I8, true) => tcx.types.i8,
(I16, true) => tcx.types.i16,
(I32, true) => tcx.types.i32,
(I64, true) => tcx.types.i64,
(I128, true) => tcx.types.i128,
}
}
fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> abi::Integer {
use abi::Integer::{I8, I16, I32, I64, I128};
match ity {
ty::IntTy::I8 => I8,
ty::IntTy::I16 => I16,
ty::IntTy::I32 => I32,
ty::IntTy::I64 => I64,
ty::IntTy::I128 => I128,
ty::IntTy::Isize => cx.data_layout().ptr_sized_integer(),
}
}
fn from_uint_ty<C: HasDataLayout>(cx: &C, ity: ty::UintTy)
-> abi::Integer {
use abi::Integer::{I8, I16, I32, I64, I128};
match ity {
ty::UintTy::U8 => I8,
ty::UintTy::U16 => I16,
ty::UintTy::U32 => I32,
ty::UintTy::U64 => I64,
ty::UintTy::U128 => I128,
ty::UintTy::Usize => cx.data_layout().ptr_sized_integer(),
}
}
#[doc =
" Finds the appropriate Integer type and signedness for the given"]
#[doc = " discriminant range and `#[repr]` attribute."]
#[doc = ""]
#[doc =
" To represent the way the values were written in the rust source, min and max"]
#[doc =
" are in different types. It\'s thus possible to pass in an unrepresentable range,"]
#[doc = " and the method will panic in those cases."]
#[doc = ""]
#[doc =
" This is the basis for computing the type of the *tag* of an enum (which can be smaller than"]
#[doc =
" the type of the *discriminant*, which is determined by [`ReprOptions::discr_type`])."]
fn discr_range_of_repr<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>,
repr: &ReprOptions, min_negative: i128, max_positive: u128)
-> (abi::Integer, bool) {
if !(min_negative >= 0 || max_positive <= i128::MAX.cast_unsigned()) {
{
::core::panicking::panic_fmt(format_args!("No type can represent the full range of {0}..={1}",
min_negative, max_positive));
}
};
let unsigned_fit =
abi::Integer::fit_unsigned(cmp::max(min_negative.cast_unsigned(),
max_positive));
let signed_fit =
cmp::max(abi::Integer::fit_signed(min_negative),
abi::Integer::fit_signed(max_positive.cast_signed()));
if let Some(ity) = repr.int {
let discr = abi::Integer::from_attr(&tcx, ity);
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
if discr < fit {
::rustc_span::macros::bug_impl(None,
format_args!("Integer::repr_discr: `#[repr]` hint too small for discriminant range of enum `{0}`",
ty), Location::caller())
}
return (discr, ity.is_signed());
}
let at_least =
if repr.c() {
tcx.data_layout().c_enum_min_size
} else { abi::Integer::I8 };
if unsigned_fit <= signed_fit {
(cmp::max(unsigned_fit, at_least), false)
} else { (cmp::max(signed_fit, at_least), true) }
}
}#[extension(pub trait IntegerExt)]
28impl abi::Integer {
29 #[inline]
30 fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx> {
31 use abi::Integer::{I8, I16, I32, I64, I128};
32 match (*self, signed) {
33 (I8, false) => tcx.types.u8,
34 (I16, false) => tcx.types.u16,
35 (I32, false) => tcx.types.u32,
36 (I64, false) => tcx.types.u64,
37 (I128, false) => tcx.types.u128,
38 (I8, true) => tcx.types.i8,
39 (I16, true) => tcx.types.i16,
40 (I32, true) => tcx.types.i32,
41 (I64, true) => tcx.types.i64,
42 (I128, true) => tcx.types.i128,
43 }
44 }
45
46 fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> abi::Integer {
47 use abi::Integer::{I8, I16, I32, I64, I128};
48 match ity {
49 ty::IntTy::I8 => I8,
50 ty::IntTy::I16 => I16,
51 ty::IntTy::I32 => I32,
52 ty::IntTy::I64 => I64,
53 ty::IntTy::I128 => I128,
54 ty::IntTy::Isize => cx.data_layout().ptr_sized_integer(),
55 }
56 }
57 fn from_uint_ty<C: HasDataLayout>(cx: &C, ity: ty::UintTy) -> abi::Integer {
58 use abi::Integer::{I8, I16, I32, I64, I128};
59 match ity {
60 ty::UintTy::U8 => I8,
61 ty::UintTy::U16 => I16,
62 ty::UintTy::U32 => I32,
63 ty::UintTy::U64 => I64,
64 ty::UintTy::U128 => I128,
65 ty::UintTy::Usize => cx.data_layout().ptr_sized_integer(),
66 }
67 }
68
69 fn discr_range_of_repr<'tcx>(
79 tcx: TyCtxt<'tcx>,
80 ty: Ty<'tcx>,
81 repr: &ReprOptions,
82 min_negative: i128,
83 max_positive: u128,
84 ) -> (abi::Integer, bool) {
85 assert!(
86 min_negative >= 0 || max_positive <= i128::MAX.cast_unsigned(),
87 "No type can represent the full range of {min_negative}..={max_positive}",
88 );
89
90 let unsigned_fit =
95 abi::Integer::fit_unsigned(cmp::max(min_negative.cast_unsigned(), max_positive));
96 let signed_fit = cmp::max(
97 abi::Integer::fit_signed(min_negative),
98 abi::Integer::fit_signed(max_positive.cast_signed()),
99 );
100
101 if let Some(ity) = repr.int {
102 let discr = abi::Integer::from_attr(&tcx, ity);
103 let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
104 if discr < fit {
105 bug!(
106 "Integer::repr_discr: `#[repr]` hint too small for \
107 discriminant range of enum `{}`",
108 ty
109 )
110 }
111 return (discr, ity.is_signed());
112 }
113
114 let at_least = if repr.c() {
115 tcx.data_layout().c_enum_min_size
118 } else {
119 abi::Integer::I8
121 };
122
123 if unsigned_fit <= signed_fit {
126 (cmp::max(unsigned_fit, at_least), false)
127 } else {
128 (cmp::max(signed_fit, at_least), true)
129 }
130 }
131}
132
133pub trait FloatExt {
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>)
-> Ty<'tcx>;
fn from_float_ty(fty: ty::FloatTy)
-> Self;
}
impl FloatExt for abi::Float {
#[inline]
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
use abi::Float::*;
match *self {
F16 => tcx.types.f16,
F16B =>
Ty::new_adt(tcx,
tcx.adt_def(tcx.require_lang_item(LangItem::F16B,
DUMMY_SP)), ty::List::empty()),
F32 => tcx.types.f32,
F64 => tcx.types.f64,
F128 => tcx.types.f128,
PpcF128 =>
Ty::new_adt(tcx,
tcx.adt_def(tcx.require_lang_item(LangItem::PpcF128,
DUMMY_SP)), ty::List::empty()),
}
}
fn from_float_ty(fty: ty::FloatTy) -> Self {
use abi::Float::*;
match fty {
ty::FloatTy::F16 => F16,
ty::FloatTy::F32 => F32,
ty::FloatTy::F64 => F64,
ty::FloatTy::F128 => F128,
}
}
}#[extension(pub trait FloatExt)]
134impl abi::Float {
135 #[inline]
136 fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
137 use abi::Float::*;
138 match *self {
139 F16 => tcx.types.f16,
140 F16B => Ty::new_adt(
141 tcx,
142 tcx.adt_def(tcx.require_lang_item(LangItem::F16B, DUMMY_SP)),
143 ty::List::empty(),
144 ),
145 F32 => tcx.types.f32,
146 F64 => tcx.types.f64,
147 F128 => tcx.types.f128,
148 PpcF128 => Ty::new_adt(
149 tcx,
150 tcx.adt_def(tcx.require_lang_item(LangItem::PpcF128, DUMMY_SP)),
151 ty::List::empty(),
152 ),
153 }
154 }
155
156 fn from_float_ty(fty: ty::FloatTy) -> Self {
157 use abi::Float::*;
158 match fty {
159 ty::FloatTy::F16 => F16,
160 ty::FloatTy::F32 => F32,
161 ty::FloatTy::F64 => F64,
162 ty::FloatTy::F128 => F128,
163 }
164 }
165}
166
167pub trait PrimitiveExt {
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>)
-> Ty<'tcx>;
#[doc = " Return an *integer* type matching this primitive."]
#[doc = " Useful in particular when dealing with enum discriminants."]
fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>)
-> Ty<'tcx>;
}
impl PrimitiveExt for Primitive {
#[inline]
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match *self {
Primitive::Int(i, signed) => i.to_ty(tcx, signed),
Primitive::Float(f) => f.to_ty(tcx),
Primitive::Pointer(_) => Ty::new_mut_ptr(tcx, tcx.types.unit),
}
}
#[doc = " Return an *integer* type matching this primitive."]
#[doc = " Useful in particular when dealing with enum discriminants."]
#[inline]
fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match *self {
Primitive::Int(i, signed) => i.to_ty(tcx, signed),
Primitive::Pointer(_) => {
let signed = false;
tcx.data_layout().ptr_sized_integer().to_ty(tcx, signed)
}
Primitive::Float(_) =>
::rustc_span::macros::bug_impl(None,
format_args!("floats do not have an int type"),
Location::caller()),
}
}
}#[extension(pub trait PrimitiveExt)]
168impl Primitive {
169 #[inline]
170 fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
171 match *self {
172 Primitive::Int(i, signed) => i.to_ty(tcx, signed),
173 Primitive::Float(f) => f.to_ty(tcx),
174 Primitive::Pointer(_) => Ty::new_mut_ptr(tcx, tcx.types.unit),
176 }
177 }
178
179 #[inline]
182 fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
183 match *self {
184 Primitive::Int(i, signed) => i.to_ty(tcx, signed),
185 Primitive::Pointer(_) => {
187 let signed = false;
188 tcx.data_layout().ptr_sized_integer().to_ty(tcx, signed)
189 }
190 Primitive::Float(_) => bug!("floats do not have an int type"),
191 }
192 }
193}
194
195pub const WIDE_PTR_ADDR: usize = 0;
200
201pub const WIDE_PTR_EXTRA: usize = 1;
206
207#[derive(#[automatically_derived]
impl ::core::marker::Copy for ValidityRequirement { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ValidityRequirement { }
#[automatically_derived]
impl ::core::clone::Clone for ValidityRequirement {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for ValidityRequirement {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
ValidityRequirement::Inhabited => "Inhabited",
ValidityRequirement::Zero => "Zero",
ValidityRequirement::UninitMitigated0x01Fill =>
"UninitMitigated0x01Fill",
ValidityRequirement::Uninit => "Uninit",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for ValidityRequirement { }
#[automatically_derived]
impl ::core::cmp::PartialEq for ValidityRequirement {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ValidityRequirement { }Eq, #[automatically_derived]
impl ::core::hash::Hash for ValidityRequirement {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state)
}
}Hash, const _: () =
{
impl ::rustc_data_structures::stable_hash::StableHash for
ValidityRequirement {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
match *self {
ValidityRequirement::Inhabited => {}
ValidityRequirement::Zero => {}
ValidityRequirement::UninitMitigated0x01Fill => {}
ValidityRequirement::Uninit => {}
}
}
}
};StableHash)]
210pub enum ValidityRequirement {
211 Inhabited,
212 Zero,
213 UninitMitigated0x01Fill,
216 Uninit,
218}
219
220impl ValidityRequirement {
221 pub fn from_intrinsic(intrinsic: Symbol) -> Option<Self> {
222 match intrinsic {
223 sym::assert_inhabited => Some(Self::Inhabited),
224 sym::assert_zero_valid => Some(Self::Zero),
225 sym::assert_mem_uninitialized_valid => Some(Self::UninitMitigated0x01Fill),
226 _ => None,
227 }
228 }
229}
230
231impl fmt::Display for ValidityRequirement {
232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233 match self {
234 Self::Inhabited => f.write_str("is inhabited"),
235 Self::Zero => f.write_str("allows being left zeroed"),
236 Self::UninitMitigated0x01Fill => f.write_str("allows being filled with 0x01"),
237 Self::Uninit => f.write_str("allows being left uninitialized"),
238 }
239 }
240}
241
242#[derive(#[automatically_derived]
impl ::core::marker::Copy for SimdLayoutError { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for SimdLayoutError { }
#[automatically_derived]
impl ::core::clone::Clone for SimdLayoutError {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Limit>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for SimdLayoutError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::ZeroLength =>
::core::fmt::Formatter::write_str(f, "ZeroLength"),
Self::TooManyLanes(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"TooManyLanes", &__self_0),
}
}
}Debug, const _: () =
{
impl ::rustc_data_structures::stable_hash::StableHash for
SimdLayoutError {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
match *self {
SimdLayoutError::ZeroLength => {}
SimdLayoutError::TooManyLanes(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash, const _: () =
{
impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
::rustc_serialize::Encodable<__E> for SimdLayoutError {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
SimdLayoutError::ZeroLength => { 0usize }
SimdLayoutError::TooManyLanes(ref __binding_0) => { 1usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
SimdLayoutError::ZeroLength => {}
SimdLayoutError::TooManyLanes(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
}
}
};TyEncodable, const _: () =
{
impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
::rustc_serialize::Decodable<__D> for SimdLayoutError {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { SimdLayoutError::ZeroLength }
1usize => {
SimdLayoutError::TooManyLanes(::rustc_serialize::Decodable::decode(__decoder))
}
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SimdLayoutError`, expected 0..2, actual {0}",
n));
}
}
}
}
};TyDecodable)]
243pub enum SimdLayoutError {
244 ZeroLength,
246 TooManyLanes(Limit),
249}
250
251#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for LayoutError<'tcx> { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for LayoutError<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for LayoutError<'tcx> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<SimdLayoutError>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<NormalizationError<'tcx>>;
let _: ::core::clone::AssertParamIsClone<ErrorGuaranteed>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for LayoutError<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Unknown(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Unknown", &__self_0),
Self::SizeOverflow(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"SizeOverflow", &__self_0),
Self::InvalidSimd { ty: __self_0, kind: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"InvalidSimd", "ty", __self_0, "kind", &__self_1),
Self::TooGeneric(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"TooGeneric", &__self_0),
Self::NormalizationFailure(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f,
"NormalizationFailure", __self_0, &__self_1),
Self::ReferencesError(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"ReferencesError", &__self_0),
}
}
}Debug, const _: () =
{
impl<'tcx> ::rustc_data_structures::stable_hash::StableHash for
LayoutError<'tcx> {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
match *self {
LayoutError::Unknown(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
LayoutError::SizeOverflow(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
LayoutError::InvalidSimd {
ty: ref __binding_0, kind: ref __binding_1 } => {
{ __binding_0.stable_hash(__hcx, __hasher); }
{ __binding_1.stable_hash(__hcx, __hasher); }
}
LayoutError::TooGeneric(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
LayoutError::NormalizationFailure(ref __binding_0,
ref __binding_1) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
{ __binding_1.stable_hash(__hcx, __hasher); }
}
LayoutError::ReferencesError(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash, const _: () =
{
impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
::rustc_serialize::Encodable<__E> for LayoutError<'tcx> {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
LayoutError::Unknown(ref __binding_0) => { 0usize }
LayoutError::SizeOverflow(ref __binding_0) => { 1usize }
LayoutError::InvalidSimd {
ty: ref __binding_0, kind: ref __binding_1 } => {
2usize
}
LayoutError::TooGeneric(ref __binding_0) => { 3usize }
LayoutError::NormalizationFailure(ref __binding_0,
ref __binding_1) => {
4usize
}
LayoutError::ReferencesError(ref __binding_0) => { 5usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
LayoutError::Unknown(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
LayoutError::SizeOverflow(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
LayoutError::InvalidSimd {
ty: ref __binding_0, kind: ref __binding_1 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
LayoutError::TooGeneric(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
LayoutError::NormalizationFailure(ref __binding_0,
ref __binding_1) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
LayoutError::ReferencesError(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
}
}
};TyEncodable, const _: () =
{
impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
::rustc_serialize::Decodable<__D> for LayoutError<'tcx> {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => {
LayoutError::Unknown(::rustc_serialize::Decodable::decode(__decoder))
}
1usize => {
LayoutError::SizeOverflow(::rustc_serialize::Decodable::decode(__decoder))
}
2usize => {
LayoutError::InvalidSimd {
ty: ::rustc_serialize::Decodable::decode(__decoder),
kind: ::rustc_serialize::Decodable::decode(__decoder),
}
}
3usize => {
LayoutError::TooGeneric(::rustc_serialize::Decodable::decode(__decoder))
}
4usize => {
LayoutError::NormalizationFailure(::rustc_serialize::Decodable::decode(__decoder),
::rustc_serialize::Decodable::decode(__decoder))
}
5usize => {
LayoutError::ReferencesError(::rustc_serialize::Decodable::decode(__decoder))
}
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `LayoutError`, expected 0..6, actual {0}",
n));
}
}
}
}
};TyDecodable)]
252pub enum LayoutError<'tcx> {
253 Unknown(Ty<'tcx>),
261 SizeOverflow(Ty<'tcx>),
263 InvalidSimd { ty: Ty<'tcx>, kind: SimdLayoutError },
265 TooGeneric(Ty<'tcx>),
270 NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
278 ReferencesError(ErrorGuaranteed),
280}
281
282impl<'tcx> fmt::Display for LayoutError<'tcx> {
283 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
284 match *self {
285 LayoutError::Unknown(ty) => f.write_fmt(format_args!("the type `{0}` has an unknown layout", ty))write!(f, "the type `{ty}` has an unknown layout"),
286 LayoutError::TooGeneric(ty) => {
287 f.write_fmt(format_args!("the type `{0}` does not have a fixed layout", ty))write!(f, "the type `{ty}` does not have a fixed layout")
288 }
289 LayoutError::SizeOverflow(ty) => {
290 f.write_fmt(format_args!("values of the type `{0}` are too big for the target architecture",
ty))write!(f, "values of the type `{ty}` are too big for the target architecture")
291 }
292 LayoutError::InvalidSimd { ty, kind: SimdLayoutError::TooManyLanes(max_lanes) } => {
293 f.write_fmt(format_args!("the SIMD type `{0}` has more elements than the limit {1}",
ty, max_lanes))write!(f, "the SIMD type `{ty}` has more elements than the limit {max_lanes}")
294 }
295 LayoutError::InvalidSimd { ty, kind: SimdLayoutError::ZeroLength } => {
296 f.write_fmt(format_args!("the SIMD type `{0}` has zero elements", ty))write!(f, "the SIMD type `{ty}` has zero elements")
297 }
298 LayoutError::NormalizationFailure(t, e) => f.write_fmt(format_args!("unable to determine layout for `{0}` because `{1}` cannot be normalized",
t, e.get_type_for_failure()))write!(
299 f,
300 "unable to determine layout for `{}` because `{}` cannot be normalized",
301 t,
302 e.get_type_for_failure()
303 ),
304 LayoutError::ReferencesError(_) => f.write_fmt(format_args!("the type has an unknown layout"))write!(f, "the type has an unknown layout"),
305 }
306 }
307}
308
309impl<'tcx> IntoDiagArg for LayoutError<'tcx> {
310 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
311 self.to_string().into_diag_arg(&mut None)
312 }
313}
314
315#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for LayoutCx<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for LayoutCx<'tcx> {
#[inline]
fn clone(&self) -> Self {
let _:
::core::clone::AssertParamIsClone<abi::LayoutCalculator<TyCtxt<'tcx>>>;
let _: ::core::clone::AssertParamIsClone<ty::TypingEnv<'tcx>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for LayoutCx<'tcx> { }Copy)]
316pub struct LayoutCx<'tcx> {
317 pub calc: abi::LayoutCalculator<TyCtxt<'tcx>>,
318 pub typing_env: ty::TypingEnv<'tcx>,
319}
320
321impl<'tcx> LayoutCx<'tcx> {
322 pub fn new(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Self {
323 Self { calc: abi::LayoutCalculator::new(tcx), typing_env }
324 }
325}
326
327#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for SizeSkeleton<'tcx> { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for SizeSkeleton<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for SizeSkeleton<'tcx> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Size>;
let _: ::core::clone::AssertParamIsClone<Option<Align>>;
let _: ::core::clone::AssertParamIsClone<bool>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for SizeSkeleton<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Known(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f, "Known",
__self_0, &__self_1),
Self::Pointer { non_zero: __self_0, tail: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Pointer", "non_zero", __self_0, "tail", &__self_1),
}
}
}Debug)]
332pub enum SizeSkeleton<'tcx> {
333 Known(Size, Option<Align>),
336
337 Pointer {
339 non_zero: bool,
341 tail: Ty<'tcx>,
345 },
346}
347
348impl<'tcx> SizeSkeleton<'tcx> {
349 pub fn compute(
350 ty: Ty<'tcx>,
351 tcx: TyCtxt<'tcx>,
352 typing_env: ty::TypingEnv<'tcx>,
353 span: Span,
354 ) -> Result<SizeSkeleton<'tcx>, &'tcx LayoutError<'tcx>> {
355 Self::compute_inner(ty, tcx, typing_env, span, 0)
356 }
357
358 fn compute_inner(
359 ty: Ty<'tcx>,
360 tcx: TyCtxt<'tcx>,
361 typing_env: ty::TypingEnv<'tcx>,
362 span: Span,
363 depth: usize,
364 ) -> Result<SizeSkeleton<'tcx>, &'tcx LayoutError<'tcx>> {
365 if true {
if !!ty.has_non_region_infer() {
::core::panicking::panic("assertion failed: !ty.has_non_region_infer()")
};
};debug_assert!(!ty.has_non_region_infer());
366
367 let recursion_limit = tcx.recursion_limit();
372 if depth >= recursion_limit.0 {
373 let suggested_limit = match recursion_limit {
374 Limit(0) => Limit(2),
375 limit => limit * 2,
376 };
377 let reported =
378 tcx.dcx().emit_err(crate::diagnostics::RecursionLimitReachedSizeSkeleton {
379 span,
380 ty,
381 suggested_limit,
382 });
383 return Err(tcx.arena.alloc(LayoutError::ReferencesError(reported)));
384 }
385
386 let err = match tcx.layout_of(typing_env.as_query_input(ty)) {
388 Ok(layout) => {
389 if layout.is_sized() {
390 return Ok(SizeSkeleton::Known(layout.size, Some(layout.align.abi)));
391 } else {
392 return Err(tcx.arena.alloc(LayoutError::Unknown(ty)));
394 }
395 }
396 Err(err @ LayoutError::TooGeneric(_)) => err,
397 Err(
399 e @ LayoutError::Unknown(_)
400 | e @ LayoutError::SizeOverflow(_)
401 | e @ LayoutError::InvalidSimd { .. }
402 | e @ LayoutError::NormalizationFailure(..)
403 | e @ LayoutError::ReferencesError(_),
404 ) => return Err(e),
405 };
406
407 match *ty.kind() {
408 ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
409 let non_zero = !ty.is_raw_ptr();
410
411 tcx.assert_fully_normalized(typing_env, pointee);
412 let tail = tcx.struct_tail_raw(
413 pointee,
414 &ObligationCause::dummy(),
415 |ty| match tcx.try_normalize_erasing_regions(typing_env, ty) {
416 Ok(ty) => ty,
417 Err(e) => Ty::new_error_with_message(
418 tcx,
419 DUMMY_SP,
420 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("normalization failed for {0} but no errors reported",
e.get_type_for_failure()))
})format!(
421 "normalization failed for {} but no errors reported",
422 e.get_type_for_failure()
423 ),
424 ),
425 },
426 || {},
427 );
428
429 match tail.kind() {
430 ty::Param(_)
433 | ty::Alias(
434 _,
435 ty::AliasTy { kind: ty::Projection { .. } | ty::Inherent { .. }, .. },
436 ) => {
437 if true {
if !tail.has_non_region_param() {
::core::panicking::panic("assertion failed: tail.has_non_region_param()")
};
};debug_assert!(tail.has_non_region_param());
438 Ok(SizeSkeleton::Pointer {
439 non_zero,
440 tail: tcx.erase_and_anonymize_regions(tail),
441 })
442 }
443 ty::Error(guar) => {
444 return Err(tcx.arena.alloc(LayoutError::ReferencesError(*guar)));
446 }
447 _ => ::rustc_span::macros::bug_impl(None,
format_args!("SizeSkeleton::compute({0}): layout errored ({1:?}), yet tail `{2}` is not a type parameter or a projection",
ty, err, tail), Location::caller())bug!(
448 "SizeSkeleton::compute({ty}): layout errored ({err:?}), yet \
449 tail `{tail}` is not a type parameter or a projection",
450 ),
451 }
452 }
453 ty::Array(inner, len) if tcx.features().transmute_generic_consts() => {
454 let len_eval = len.try_to_target_usize(tcx);
455 if len_eval == Some(0) {
456 return Ok(SizeSkeleton::Known(Size::from_bytes(0), None));
457 }
458
459 match SizeSkeleton::compute_inner(inner, tcx, typing_env, span, depth + 1)? {
460 SizeSkeleton::Known(s, a) => {
463 if let Some(c) = len_eval {
464 let size = s
465 .bytes()
466 .checked_mul(c)
467 .ok_or_else(|| &*tcx.arena.alloc(LayoutError::SizeOverflow(ty)))?;
468 return Ok(SizeSkeleton::Known(Size::from_bytes(size), a));
470 }
471 Err(err)
472 }
473 SizeSkeleton::Pointer { .. } => Err(err),
474 }
475 }
476
477 ty::Adt(def, args) => {
478 if def.is_union() || def.variants().is_empty() || def.variants().len() > 2 {
480 return Err(err);
481 }
482 {
484 let ReprOptions { int, align, pack, flags, scalable, field_shuffle_seed: _ } =
489 def.repr();
490 let mut ignored_flags = ReprFlags::IS_TRANSPARENT
491 | ReprFlags::IS_LINEAR
492 | ReprFlags::RANDOMIZE_LAYOUT;
493 if def.is_struct() {
494 ignored_flags |= ReprFlags::IS_C;
499 }
500 if int.is_some()
501 || align.is_some()
502 || pack.is_some()
503 || flags.difference(ignored_flags) != ReprFlags::default()
504 || scalable.is_some()
505 {
506 return Err(err);
507 }
508 }
509
510 let zero_or_ptr_variant = |i| -> Result<Option<SizeSkeleton<'tcx>>, _> {
514 let i = VariantIdx::from_usize(i);
515 let fields = def.variant(i).fields.iter().map(|field| {
516 SizeSkeleton::compute_inner(
517 field.ty(tcx, args).skip_norm_wip(),
518 tcx,
519 typing_env,
520 span,
521 depth + 1,
522 )
523 });
524 let mut ptr = None;
525 for field in fields {
526 let field = field?;
527 match field {
528 SizeSkeleton::Known(size, align) => {
529 let is_1zst = size.bytes() == 0
530 && align.is_some_and(|align| align.bytes() == 1);
531 if !is_1zst {
532 return Err(err);
533 }
534 }
535 SizeSkeleton::Pointer { .. } => {
536 if ptr.is_some() {
537 return Err(err);
538 }
539 ptr = Some(field);
540 }
541 }
542 }
543 Ok(ptr)
544 };
545
546 let v0 = zero_or_ptr_variant(0)?;
547 if def.variants().len() == 1 {
550 if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
551 return Ok(SizeSkeleton::Pointer { non_zero, tail });
552 } else {
553 return Err(err);
554 }
555 }
556
557 let v1 = zero_or_ptr_variant(1)?;
558 match (v0, v1) {
562 (Some(SizeSkeleton::Pointer { non_zero: true, tail }), None)
563 | (None, Some(SizeSkeleton::Pointer { non_zero: true, tail })) => {
564 Ok(SizeSkeleton::Pointer { non_zero: false, tail })
565 }
566 _ => Err(err),
567 }
568 }
569
570 ty::Alias(..) => {
571 let normalized =
572 tcx.normalize_erasing_regions(typing_env, Unnormalized::new_wip(ty));
573 if ty == normalized {
574 Err(err)
575 } else {
576 SizeSkeleton::compute_inner(normalized, tcx, typing_env, span, depth + 1)
577 }
578 }
579
580 ty::Pat(base, pat) => {
581 let base = SizeSkeleton::compute_inner(base, tcx, typing_env, span, depth + 1);
583 match *pat {
584 ty::PatternKind::Range { .. } | ty::PatternKind::Or(_) => base,
585 ty::PatternKind::NotNull => match base? {
588 SizeSkeleton::Known(..) => base,
589 SizeSkeleton::Pointer { non_zero: _, tail } => {
590 Ok(SizeSkeleton::Pointer { non_zero: true, tail })
591 }
592 },
593 }
594 }
595
596 _ => Err(err),
597 }
598 }
599
600 pub fn same_size(self, other: SizeSkeleton<'tcx>) -> bool {
601 match (self, other) {
602 (SizeSkeleton::Known(a, _), SizeSkeleton::Known(b, _)) => a == b,
603 (SizeSkeleton::Pointer { tail: a, .. }, SizeSkeleton::Pointer { tail: b, .. }) => {
604 a == b
605 }
606 _ => false,
607 }
608 }
609}
610
611pub trait HasTyCtxt<'tcx>: HasDataLayout {
612 fn tcx(&self) -> TyCtxt<'tcx>;
613}
614
615pub trait HasTypingEnv<'tcx> {
616 fn typing_env(&self) -> ty::TypingEnv<'tcx>;
617}
618
619impl<'tcx> HasDataLayout for TyCtxt<'tcx> {
620 #[inline]
621 fn data_layout(&self) -> &TargetDataLayout {
622 &self.data_layout
623 }
624}
625
626impl<'tcx> HasTargetSpec for TyCtxt<'tcx> {
627 fn target_spec(&self) -> &Target {
628 &self.sess.target
629 }
630}
631
632impl<'tcx> HasX86AbiOpt for TyCtxt<'tcx> {
633 fn x86_abi_opt(&self) -> X86Abi {
634 X86Abi {
635 regparm: self.sess.opts.unstable_opts.regparm,
636 reg_struct_return: self.sess.opts.unstable_opts.reg_struct_return,
637 }
638 }
639}
640
641impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
642 #[inline]
643 fn tcx(&self) -> TyCtxt<'tcx> {
644 *self
645 }
646}
647
648impl<'tcx> HasDataLayout for TyCtxtAt<'tcx> {
649 #[inline]
650 fn data_layout(&self) -> &TargetDataLayout {
651 &self.data_layout
652 }
653}
654
655impl<'tcx> HasTargetSpec for TyCtxtAt<'tcx> {
656 fn target_spec(&self) -> &Target {
657 &self.sess.target
658 }
659}
660
661impl<'tcx> HasTyCtxt<'tcx> for TyCtxtAt<'tcx> {
662 #[inline]
663 fn tcx(&self) -> TyCtxt<'tcx> {
664 **self
665 }
666}
667
668impl<'tcx> HasTypingEnv<'tcx> for LayoutCx<'tcx> {
669 fn typing_env(&self) -> ty::TypingEnv<'tcx> {
670 self.typing_env
671 }
672}
673
674impl<'tcx> HasDataLayout for LayoutCx<'tcx> {
675 fn data_layout(&self) -> &TargetDataLayout {
676 self.calc.cx.data_layout()
677 }
678}
679
680impl<'tcx> HasTargetSpec for LayoutCx<'tcx> {
681 fn target_spec(&self) -> &Target {
682 self.calc.cx.target_spec()
683 }
684}
685
686impl<'tcx> HasX86AbiOpt for LayoutCx<'tcx> {
687 fn x86_abi_opt(&self) -> X86Abi {
688 self.calc.cx.x86_abi_opt()
689 }
690}
691
692impl<'tcx> HasTyCtxt<'tcx> for LayoutCx<'tcx> {
693 fn tcx(&self) -> TyCtxt<'tcx> {
694 self.calc.cx
695 }
696}
697
698pub trait MaybeResult<T> {
699 type Error;
700
701 fn from(x: Result<T, Self::Error>) -> Self;
702 fn to_result(self) -> Result<T, Self::Error>;
703}
704
705impl<T> MaybeResult<T> for T {
706 type Error = !;
707
708 fn from(Ok(x): Result<T, Self::Error>) -> Self {
709 x
710 }
711 fn to_result(self) -> Result<T, Self::Error> {
712 Ok(self)
713 }
714}
715
716impl<T, E> MaybeResult<T> for Result<T, E> {
717 type Error = E;
718
719 fn from(x: Result<T, Self::Error>) -> Self {
720 x
721 }
722 fn to_result(self) -> Result<T, Self::Error> {
723 self
724 }
725}
726
727pub type TyAndLayout<'tcx> = rustc_abi::TyAndLayout<'tcx, Ty<'tcx>>;
728
729pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasTypingEnv<'tcx> {
732 type LayoutOfResult: MaybeResult<TyAndLayout<'tcx>> = TyAndLayout<'tcx>;
735
736 #[inline]
739 fn layout_tcx_at_span(&self) -> Span {
740 DUMMY_SP
741 }
742
743 fn handle_layout_err(
751 &self,
752 err: LayoutError<'tcx>,
753 span: Span,
754 ty: Ty<'tcx>,
755 ) -> <Self::LayoutOfResult as MaybeResult<TyAndLayout<'tcx>>>::Error;
756}
757
758pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
760 #[inline]
763 fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
764 self.spanned_layout_of(ty, DUMMY_SP)
765 }
766
767 #[inline]
772 fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
773 let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() };
774 let tcx = self.tcx().at(span);
775
776 MaybeResult::from(
777 tcx.layout_of(self.typing_env().as_query_input(ty))
778 .map_err(|err| self.handle_layout_err(*err, span, ty)),
779 )
780 }
781}
782
783impl<'tcx, C: LayoutOfHelpers<'tcx>> LayoutOf<'tcx> for C {}
784
785impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx> {
786 type LayoutOfResult = Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>>;
787
788 #[inline]
789 fn handle_layout_err(
790 &self,
791 err: LayoutError<'tcx>,
792 _: Span,
793 _: Ty<'tcx>,
794 ) -> &'tcx LayoutError<'tcx> {
795 self.tcx().arena.alloc(err)
796 }
797}
798
799impl<'tcx, C> TyAbiInterface<'tcx, C> for Ty<'tcx>
800where
801 C: HasTyCtxt<'tcx> + HasTypingEnv<'tcx>,
802{
803 fn ty_and_layout_for_variant(
804 this: TyAndLayout<'tcx>,
805 cx: &C,
806 variant_index: VariantIdx,
807 ) -> TyAndLayout<'tcx> {
808 let layout = match this.variants {
809 Variants::Single { index } if index == variant_index => {
811 return this;
812 }
813
814 Variants::Single { .. } | Variants::Empty => {
815 let tcx = cx.tcx();
820 let typing_env = cx.typing_env();
821
822 if let Ok(original_layout) = tcx.layout_of(typing_env.as_query_input(this.ty)) {
824 {
match (&original_layout.variants, &this.variants) {
(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!(original_layout.variants, this.variants);
825 }
826
827 let fields = match this.ty.kind() {
828 ty::Adt(def, _) if def.variants().is_empty() => {
829 ::rustc_span::macros::bug_impl(None,
format_args!("for_variant called on zero-variant enum {0}", this.ty),
Location::caller())bug!("for_variant called on zero-variant enum {}", this.ty)
830 }
831 ty::Adt(def, _) => def.variant(variant_index).fields.len(),
832 _ => ::rustc_span::macros::bug_impl(None,
format_args!("`ty_and_layout_for_variant` on unexpected type {0}",
this.ty), Location::caller())bug!("`ty_and_layout_for_variant` on unexpected type {}", this.ty),
833 };
834 tcx.mk_layout(LayoutData::uninhabited_variant(cx, variant_index, fields))
835 }
836
837 Variants::Multiple { .. } => {
838 cx.tcx().mk_layout(LayoutData::for_variant(&this, variant_index))
839 }
840 };
841
842 {
match (&*layout.variants(), &Variants::Single { index: variant_index }) {
(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!(*layout.variants(), Variants::Single { index: variant_index });
843
844 TyAndLayout { ty: this.ty, layout }
845 }
846
847 fn ty_and_layout_field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> TyAndLayout<'tcx> {
848 enum TyMaybeWithLayout<'tcx> {
849 Ty(Ty<'tcx>),
850 TyAndLayout(TyAndLayout<'tcx>),
851 }
852
853 fn field_ty_or_layout<'tcx>(
854 this: TyAndLayout<'tcx>,
855 cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>),
856 i: usize,
857 ) -> TyMaybeWithLayout<'tcx> {
858 let tcx = cx.tcx();
859 let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> {
860 TyAndLayout {
861 layout: tcx.mk_layout(LayoutData::scalar(cx, tag)),
862 ty: tag.primitive().to_ty(tcx),
863 }
864 };
865
866 match *this.ty.kind() {
867 ty::Bool
868 | ty::Char
869 | ty::Int(_)
870 | ty::Uint(_)
871 | ty::Float(_)
872 | ty::FnPtr(..)
873 | ty::Never
874 | ty::FnDef(..)
875 | ty::CoroutineWitness(..)
876 | ty::Foreign(..)
877 | ty::Dynamic(_, _) => {
878 ::rustc_span::macros::bug_impl(None,
format_args!("TyAndLayout::field({0:?}): not applicable", this),
Location::caller())bug!("TyAndLayout::field({:?}): not applicable", this)
879 }
880
881 ty::Pat(base, _) => {
882 {
match (&i, &0) {
(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!(i, 0);
883 TyMaybeWithLayout::Ty(base)
884 }
885
886 ty::UnsafeBinder(bound_ty) => {
887 let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into());
888 field_ty_or_layout(TyAndLayout { ty, ..this }, cx, i)
889 }
890
891 ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
893 if !(i < this.fields.count()) {
::core::panicking::panic("assertion failed: i < this.fields.count()")
};assert!(i < this.fields.count());
894
895 if i == 0 {
900 let nil = tcx.types.unit;
901 let unit_ptr_ty = if this.ty.is_raw_ptr() {
902 Ty::new_mut_ptr(tcx, nil)
903 } else {
904 Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, nil)
905 };
906
907 let typing_env = ty::TypingEnv::fully_monomorphized();
911 return TyMaybeWithLayout::TyAndLayout(TyAndLayout {
912 ty: this.ty,
913 ..tcx.layout_of(typing_env.as_query_input(unit_ptr_ty)).unwrap()
914 });
915 }
916
917 let mk_dyn_vtable = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| {
918 let min_count = ty::vtable_min_entries(
919 tcx,
920 principal.map(|principal| {
921 tcx.instantiate_bound_regions_with_erased(principal)
922 }),
923 );
924 Ty::new_imm_ref(
925 tcx,
926 tcx.lifetimes.re_static,
927 Ty::new_array(tcx, tcx.types.usize, min_count.try_into().unwrap()),
929 )
930 };
931
932 let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type()
933 && !pointee.references_error()
936 {
937 let metadata = tcx.normalize_erasing_regions(
938 cx.typing_env(),
939 Unnormalized::new(Ty::new_projection(
940 tcx,
941 ty::IsRigid::No,
942 metadata_def_id,
943 [pointee],
944 )),
945 );
946
947 if let ty::Adt(def, args) = metadata.kind()
952 && tcx.is_lang_item(def.did(), LangItem::DynMetadata)
953 && let ty::Dynamic(data, _) = args.type_at(0).kind()
954 {
955 mk_dyn_vtable(data.principal())
956 } else {
957 metadata
958 }
959 } else {
960 match tcx.struct_tail_for_codegen(pointee, cx.typing_env()).kind() {
961 ty::Slice(_) | ty::Str => tcx.types.usize,
962 ty::Dynamic(data, _) => mk_dyn_vtable(data.principal()),
963 _ => ::rustc_span::macros::bug_impl(None,
format_args!("TyAndLayout::field({0:?}): not applicable", this),
Location::caller())bug!("TyAndLayout::field({:?}): not applicable", this),
964 }
965 };
966
967 TyMaybeWithLayout::Ty(metadata)
968 }
969
970 ty::Array(element, _) | ty::Slice(element) => TyMaybeWithLayout::Ty(element),
972 ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8),
973
974 ty::Closure(_, args) => field_ty_or_layout(
976 TyAndLayout { ty: args.as_closure().tupled_upvars_ty(), ..this },
977 cx,
978 i,
979 ),
980
981 ty::CoroutineClosure(_, args) => field_ty_or_layout(
982 TyAndLayout { ty: args.as_coroutine_closure().tupled_upvars_ty(), ..this },
983 cx,
984 i,
985 ),
986
987 ty::Coroutine(def_id, args) => match this.variants {
988 Variants::Empty => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
989 Variants::Single { index } => TyMaybeWithLayout::Ty(
990 args.as_coroutine()
991 .state_tys(def_id, tcx)
992 .nth(index.as_usize())
993 .unwrap()
994 .nth(i)
995 .unwrap(),
996 ),
997 Variants::Multiple { tag, tag_field, .. } => {
998 if FieldIdx::from_usize(i) == tag_field {
999 TyMaybeWithLayout::TyAndLayout(tag_layout(tag))
1000 } else {
1001 TyMaybeWithLayout::Ty(args.as_coroutine().upvar_tys()[i])
1002 }
1003 }
1004 },
1005
1006 ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i]),
1007
1008 ty::Adt(def, args) => {
1010 match this.variants {
1011 Variants::Single { index } => {
1012 let field = &def.variant(index).fields[FieldIdx::from_usize(i)];
1013 TyMaybeWithLayout::Ty(field.ty(tcx, args).skip_norm_wip())
1014 }
1015 Variants::Empty => {
::core::panicking::panic_fmt(format_args!("there is no field in Variants::Empty types"));
}panic!("there is no field in Variants::Empty types"),
1016
1017 Variants::Multiple { tag, .. } => {
1019 {
match (&i, &0) {
(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!(i, 0);
1020 return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
1021 }
1022 }
1023 }
1024
1025 ty::Alias(..)
1026 | ty::Bound(..)
1027 | ty::Placeholder(..)
1028 | ty::Param(_)
1029 | ty::Infer(_)
1030 | ty::Error(_) => ::rustc_span::macros::bug_impl(None,
format_args!("TyAndLayout::field: unexpected type `{0}`", this.ty),
Location::caller())bug!("TyAndLayout::field: unexpected type `{}`", this.ty),
1031 }
1032 }
1033
1034 match field_ty_or_layout(this, cx, i) {
1035 TyMaybeWithLayout::Ty(field_ty) => {
1036 cx.tcx().layout_of(cx.typing_env().as_query_input(field_ty)).unwrap_or_else(|e| {
1037 ::rustc_span::macros::bug_impl(None,
format_args!("failed to get layout for `{0}`: {1:?},\ndespite it being a field (#{2}) of an existing layout: {3:#?}",
field_ty, e, i, this), Location::caller())bug!(
1038 "failed to get layout for `{field_ty}`: {e:?},\n\
1039 despite it being a field (#{i}) of an existing layout: {this:#?}",
1040 )
1041 })
1042 }
1043 TyMaybeWithLayout::TyAndLayout(field_layout) => field_layout,
1044 }
1045 }
1046
1047 fn ty_and_layout_pointee_info_at(
1050 this: TyAndLayout<'tcx>,
1051 cx: &C,
1052 offset: Size,
1053 ) -> Option<PointeeInfo> {
1054 let tcx = cx.tcx();
1055 let typing_env = cx.typing_env();
1056
1057 let optimize = tcx.sess.opts.optimize != OptLevel::No;
1061
1062 let pointee_info = match *this.ty.kind() {
1063 ty::RawPtr(_, _) | ty::FnPtr(..) if offset.bytes() == 0 => {
1064 Some(PointeeInfo { safe: None, size: Size::ZERO, align: Align::ONE })
1065 }
1066 ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
1067 tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| {
1068 let kind;
1069 let size;
1070
1071 match mt {
1072 hir::Mutability::Not => {
1073 let frozen = optimize && ty.is_freeze(tcx, typing_env);
1074 kind = PointerKind::SharedRef { frozen };
1075
1076 size = layout.size * frozen as _;
1088 }
1089 hir::Mutability::Mut => {
1090 let unpin = optimize
1091 && ty.is_unpin(tcx, typing_env)
1092 && ty.is_unsafe_unpin(tcx, typing_env);
1093 kind = PointerKind::MutableRef { unpin };
1094
1095 size = layout.size * unpin as _;
1098 }
1099 };
1100
1101 PointeeInfo { safe: Some(kind), size, align: layout.align.abi }
1102 })
1103 }
1104
1105 ty::Adt(..)
1106 if offset.bytes() == 0
1107 && let Some(pointee) = this.ty.boxed_ty() =>
1108 {
1109 tcx.layout_of(typing_env.as_query_input(pointee)).ok().map(|layout| {
1110 let unpin = optimize
1112 && pointee.is_unpin(tcx, typing_env)
1113 && pointee.is_unsafe_unpin(tcx, typing_env);
1114 let size = layout.size * unpin as _;
1115
1116 PointeeInfo {
1117 safe: Some(PointerKind::Box { unpin, global: this.ty.is_box_global(tcx) }),
1118 size,
1119 align: layout.align.abi,
1120 }
1121 })
1122 }
1123
1124 _ => {
1125 let mut data_variant = match &this.variants {
1126 Variants::Multiple {
1136 tag_encoding:
1137 TagEncoding::Niche { untagged_variant, niche_variants, niche_start },
1138 tag_field,
1139 variants,
1140 ..
1141 } if variants.len() == 2
1142 && this.fields.offset(tag_field.as_usize()) == offset =>
1143 {
1144 let tagged_variant = if *untagged_variant == VariantIdx::ZERO {
1145 VariantIdx::from_u32(1)
1146 } else {
1147 VariantIdx::from_u32(0)
1148 };
1149 {
match (&tagged_variant, &niche_variants.start) {
(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!(tagged_variant, niche_variants.start);
1150 if *niche_start == 0 {
1151 Some(this.for_variant(cx, *untagged_variant))
1157 } else {
1158 None
1159 }
1160 }
1161 Variants::Multiple { .. } => None,
1162 Variants::Empty | Variants::Single { .. } => Some(this),
1163 };
1164
1165 if let Some(variant) = data_variant
1166 && let FieldsShape::Union(_) = variant.fields
1168 {
1169 data_variant = None;
1170 }
1171
1172 let mut result = None;
1173
1174 if let Some(variant) = data_variant {
1175 let ptr_end = offset + Primitive::Pointer(AddressSpace::ZERO).size(cx);
1178 for i in 0..variant.fields.count() {
1179 let field_start = variant.fields.offset(i);
1180 if field_start <= offset {
1181 let field = variant.field(cx, i);
1182 result = field.to_result().ok().and_then(|field| {
1183 if ptr_end <= field_start + field.size {
1184 let field_info =
1186 field.pointee_info_at(cx, offset - field_start);
1187 field_info
1188 } else {
1189 None
1190 }
1191 });
1192 if result.is_some() {
1193 break;
1194 }
1195 }
1196 }
1197 }
1198
1199 if this.ty.is_like_maybe_dangling()
1201 && let Some(info) = result
1202 {
1203 result = Some(PointeeInfo {
1204 safe: None,
1207 size: Size::ZERO,
1209 align: info.align,
1211 });
1212 }
1213
1214 result
1215 }
1216 };
1217
1218 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/07e526db9df34143c99ec8064acc8ad543f69b30/compiler/rustc_middle/src/ty/layout.rs:1218",
"rustc_middle::ty::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/07e526db9df34143c99ec8064acc8ad543f69b30/compiler/rustc_middle/src/ty/layout.rs"),
::tracing_core::__macro_support::Option::Some(1218u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::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!("pointee_info_at (offset={0:?}, type kind: {1:?}) => {2:?}",
offset, this.ty.kind(), pointee_info) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(
1219 "pointee_info_at (offset={:?}, type kind: {:?}) => {:?}",
1220 offset,
1221 this.ty.kind(),
1222 pointee_info
1223 );
1224
1225 pointee_info
1226 }
1227
1228 fn is_adt(this: TyAndLayout<'tcx>) -> bool {
1229 #[allow(non_exhaustive_omitted_patterns)] match this.ty.kind() {
ty::Adt(..) => true,
_ => false,
}matches!(this.ty.kind(), ty::Adt(..))
1230 }
1231
1232 fn is_enum(this: TyAndLayout<'tcx>) -> bool {
1233 #[allow(non_exhaustive_omitted_patterns)] match this.ty.kind() {
ty::Adt(def, _) if def.is_enum() => true,
_ => false,
}matches!(this.ty.kind(), ty::Adt(def, _) if def.is_enum())
1234 }
1235
1236 fn is_never(this: TyAndLayout<'tcx>) -> bool {
1237 #[allow(non_exhaustive_omitted_patterns)] match this.ty.kind() {
ty::Never => true,
_ => false,
}matches!(this.ty.kind(), ty::Never)
1238 }
1239
1240 fn is_tuple(this: TyAndLayout<'tcx>) -> bool {
1241 #[allow(non_exhaustive_omitted_patterns)] match this.ty.kind() {
ty::Tuple(..) => true,
_ => false,
}matches!(this.ty.kind(), ty::Tuple(..))
1242 }
1243
1244 fn is_unit(this: TyAndLayout<'tcx>) -> bool {
1245 #[allow(non_exhaustive_omitted_patterns)] match this.ty.kind() {
ty::Tuple(list) if list.len() == 0 => true,
_ => false,
}matches!(this.ty.kind(), ty::Tuple(list) if list.len() == 0)
1246 }
1247
1248 fn is_transparent(this: TyAndLayout<'tcx>) -> bool {
1249 #[allow(non_exhaustive_omitted_patterns)] match this.ty.kind() {
ty::Adt(def, _) if def.repr().transparent() => true,
_ => false,
}matches!(this.ty.kind(), ty::Adt(def, _) if def.repr().transparent())
1250 }
1251
1252 fn is_complex_number_lang_item(this: TyAndLayout<'tcx>, cx: &C) -> bool {
1254 let Some(def) = this.ty.ty_adt_def() else { return false };
1255 cx.tcx().is_lang_item(def.did(), LangItem::Complex)
1256 }
1257
1258 fn is_scalable_vector(this: TyAndLayout<'tcx>) -> bool {
1259 this.ty.is_scalable_vector()
1260 }
1261
1262 fn is_pass_indirectly_in_non_rustic_abis_flag_set(this: TyAndLayout<'tcx>) -> bool {
1264 #[allow(non_exhaustive_omitted_patterns)] match this.ty.kind() {
ty::Adt(def, _) if
def.repr().flags.contains(ReprFlags::PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS)
=> true,
_ => false,
}matches!(this.ty.kind(), ty::Adt(def, _) if def.repr().flags.contains(ReprFlags::PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS))
1265 }
1266}
1267
1268#[inline]
1309{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("fn_can_unwind",
"rustc_middle::ty::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/07e526db9df34143c99ec8064acc8ad543f69b30/compiler/rustc_middle/src/ty/layout.rs"),
::tracing_core::__macro_support::Option::Some(1309u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("fn_def_id")
}> =
::tracing::__macro_support::FieldName::new("fn_def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("abi")
}> =
::tracing::__macro_support::FieldName::new("abi");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&fn_def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&abi)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: bool = loop {};
return __tracing_attr_fake_return;
}
{
if let Some(did) = fn_def_id {
if tcx.codegen_fn_attrs(did).flags.contains(CodegenFnAttrFlags::NEVER_UNWIND)
{
return false;
}
if !tcx.sess.panic_strategy().unwinds() &&
!tcx.is_foreign_item(did) {
return false;
}
if !tcx.sess.opts.unstable_opts.panic_in_drop.unwinds() &&
tcx.is_lang_item(did, LangItem::DropGlue) {
return false;
}
}
use ExternAbi::*;
match abi {
C { unwind } | System { unwind } | Cdecl { unwind } |
Stdcall { unwind } | Fastcall { unwind } | Vectorcall {
unwind } | Thiscall { unwind } | Aapcs { unwind } | Win64 {
unwind } | SysV64 { unwind } => unwind,
PtxKernel | Msp430Interrupt | X86Interrupt | GpuKernel |
EfiApi | AvrInterrupt | AvrNonBlockingInterrupt |
CmseNonSecureCall | CmseNonSecureEntry | Custom |
RiscvInterruptM | RiscvInterruptS | RustInvalid | Swift |
LlvmIntrinsic => false,
Rust | RustCall | RustCold | RustPreserveNone | RustTail => {
tcx.sess.panic_strategy().unwinds()
}
}
}
}
}#[tracing::instrument(level = "debug", skip(tcx))]
1310pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi) -> bool {
1311 if let Some(did) = fn_def_id {
1312 if tcx.codegen_fn_attrs(did).flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) {
1314 return false;
1315 }
1316
1317 if !tcx.sess.panic_strategy().unwinds() && !tcx.is_foreign_item(did) {
1322 return false;
1323 }
1324
1325 if !tcx.sess.opts.unstable_opts.panic_in_drop.unwinds()
1330 && tcx.is_lang_item(did, LangItem::DropGlue)
1331 {
1332 return false;
1333 }
1334 }
1335
1336 use ExternAbi::*;
1343 match abi {
1344 C { unwind }
1345 | System { unwind }
1346 | Cdecl { unwind }
1347 | Stdcall { unwind }
1348 | Fastcall { unwind }
1349 | Vectorcall { unwind }
1350 | Thiscall { unwind }
1351 | Aapcs { unwind }
1352 | Win64 { unwind }
1353 | SysV64 { unwind } => unwind,
1354 PtxKernel
1355 | Msp430Interrupt
1356 | X86Interrupt
1357 | GpuKernel
1358 | EfiApi
1359 | AvrInterrupt
1360 | AvrNonBlockingInterrupt
1361 | CmseNonSecureCall
1362 | CmseNonSecureEntry
1363 | Custom
1364 | RiscvInterruptM
1365 | RiscvInterruptS
1366 | RustInvalid
1367 | Swift
1368 | LlvmIntrinsic => false,
1369 Rust | RustCall | RustCold | RustPreserveNone | RustTail => {
1370 tcx.sess.panic_strategy().unwinds()
1371 }
1372 }
1373}
1374
1375#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for FnAbiError<'tcx> { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for FnAbiError<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for FnAbiError<'tcx> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<LayoutError<'tcx>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for FnAbiError<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Layout(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Layout",
&__self_0),
}
}
}Debug, const _: () =
{
impl<'tcx> ::rustc_data_structures::stable_hash::StableHash for
FnAbiError<'tcx> {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
match *self {
FnAbiError::Layout(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash)]
1377pub enum FnAbiError<'tcx> {
1378 Layout(LayoutError<'tcx>),
1380}
1381
1382impl<'a, 'b> Diagnostic<'a> for FnAbiError<'b> {
1383 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> {
1384 match self {
1385 Self::Layout(e) => Diag::new(dcx, level, e.to_string()),
1386 }
1387 }
1388}
1389
1390#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for FnAbiRequest<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::OfFnPtr { sig: __self_0, extra_args: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"OfFnPtr", "sig", __self_0, "extra_args", &__self_1),
Self::OfInstance { instance: __self_0, extra_args: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"OfInstance", "instance", __self_0, "extra_args",
&__self_1),
}
}
}Debug)]
1393pub enum FnAbiRequest<'tcx> {
1394 OfFnPtr { sig: ty::PolyFnSig<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>> },
1395 OfInstance { instance: ty::Instance<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>> },
1396}
1397
1398pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> {
1401 type FnAbiOfResult: MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>> = &'tcx FnAbi<'tcx, Ty<'tcx>>;
1404
1405 fn handle_fn_abi_err(
1415 &self,
1416 err: FnAbiError<'tcx>,
1417 span: Span,
1418 fn_abi_request: FnAbiRequest<'tcx>,
1419 ) -> <Self::FnAbiOfResult as MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>>::Error;
1420}
1421
1422pub fn codegen_handle_fn_abi_err<'tcx>(
1424 tcx: TyCtxt<'tcx>,
1425 err: FnAbiError<'tcx>,
1426 span: Span,
1427 fn_abi_request: FnAbiRequest<'tcx>,
1428) -> ErrorGuaranteed {
1429 match err {
1430 FnAbiError::Layout(LayoutError::ReferencesError(guar)) => guar,
1431 FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) => {
1432 tcx.dcx().emit_err(Spanned { span, node: err })
1433 }
1434 _ => match fn_abi_request {
1435 FnAbiRequest::OfFnPtr { sig, extra_args } => {
1436 ::rustc_span::macros::bug_impl(Some(span),
format_args!("`fn_abi_of_fn_ptr({0}, {1:?})` failed: {2:?}", sig,
extra_args, err), Location::caller());span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}",);
1437 }
1438 FnAbiRequest::OfInstance { instance, extra_args } => {
1439 ::rustc_span::macros::bug_impl(Some(span),
format_args!("`fn_abi_of_instance({0}, {1:?})` failed: {2:?}", instance,
extra_args, err), Location::caller());span_bug!(span, "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}",);
1440 }
1441 },
1442 }
1443}
1444
1445pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
1447 #[inline]
1452 fn fn_abi_of_fn_ptr(
1453 &self,
1454 sig: ty::PolyFnSig<'tcx>,
1455 extra_args: &'tcx ty::List<Ty<'tcx>>,
1456 ) -> Self::FnAbiOfResult {
1457 let span = self.layout_tcx_at_span();
1459 let tcx = self.tcx().at(span);
1460
1461 MaybeResult::from(
1462 tcx.fn_abi_of_fn_ptr(self.typing_env().as_query_input((sig, extra_args))).map_err(
1463 |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
1464 ),
1465 )
1466 }
1467
1468 #[inline]
1480 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("fn_abi_of_instance_no_deduced_attrs",
"rustc_middle::ty::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/07e526db9df34143c99ec8064acc8ad543f69b30/compiler/rustc_middle/src/ty/layout.rs"),
::tracing_core::__macro_support::Option::Some(1480u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("instance")
}> =
::tracing::__macro_support::FieldName::new("instance");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("extra_args")
}> =
::tracing::__macro_support::FieldName::new("extra_args");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instance)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&extra_args)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Self::FnAbiOfResult = loop {};
return __tracing_attr_fake_return;
}
{
let span = self.layout_tcx_at_span();
let tcx = self.tcx().at(span);
MaybeResult::from(tcx.fn_abi_of_instance_no_deduced_attrs(self.typing_env().as_query_input((instance,
extra_args))).map_err(|err|
{
let span =
if !span.is_dummy() {
span
} else { tcx.def_span(instance.def_id()) };
self.handle_fn_abi_err(*err, span,
FnAbiRequest::OfInstance { instance, extra_args })
}))
}
}
}#[tracing::instrument(level = "debug", skip(self))]
1481 fn fn_abi_of_instance_no_deduced_attrs(
1482 &self,
1483 instance: ty::Instance<'tcx>,
1484 extra_args: &'tcx ty::List<Ty<'tcx>>,
1485 ) -> Self::FnAbiOfResult {
1486 let span = self.layout_tcx_at_span();
1488 let tcx = self.tcx().at(span);
1489
1490 MaybeResult::from(
1491 tcx.fn_abi_of_instance_no_deduced_attrs(
1492 self.typing_env().as_query_input((instance, extra_args)),
1493 )
1494 .map_err(|err| {
1495 let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
1500 self.handle_fn_abi_err(
1501 *err,
1502 span,
1503 FnAbiRequest::OfInstance { instance, extra_args },
1504 )
1505 }),
1506 )
1507 }
1508
1509 #[inline]
1519 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("fn_abi_of_instance",
"rustc_middle::ty::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/07e526db9df34143c99ec8064acc8ad543f69b30/compiler/rustc_middle/src/ty/layout.rs"),
::tracing_core::__macro_support::Option::Some(1519u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("instance")
}> =
::tracing::__macro_support::FieldName::new("instance");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("extra_args")
}> =
::tracing::__macro_support::FieldName::new("extra_args");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instance)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&extra_args)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Self::FnAbiOfResult = loop {};
return __tracing_attr_fake_return;
}
{
let span = self.layout_tcx_at_span();
let tcx = self.tcx().at(span);
MaybeResult::from(tcx.fn_abi_of_instance(self.typing_env().as_query_input((instance,
extra_args))).map_err(|err|
{
let span =
if !span.is_dummy() {
span
} else { tcx.def_span(instance.def_id()) };
self.handle_fn_abi_err(*err, span,
FnAbiRequest::OfInstance { instance, extra_args })
}))
}
}
}#[tracing::instrument(level = "debug", skip(self))]
1520 fn fn_abi_of_instance(
1521 &self,
1522 instance: ty::Instance<'tcx>,
1523 extra_args: &'tcx ty::List<Ty<'tcx>>,
1524 ) -> Self::FnAbiOfResult {
1525 let span = self.layout_tcx_at_span();
1527 let tcx = self.tcx().at(span);
1528
1529 MaybeResult::from(
1530 tcx.fn_abi_of_instance(self.typing_env().as_query_input((instance, extra_args)))
1531 .map_err(|err| {
1532 let span =
1537 if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
1538 self.handle_fn_abi_err(
1539 *err,
1540 span,
1541 FnAbiRequest::OfInstance { instance, extra_args },
1542 )
1543 }),
1544 )
1545 }
1546}
1547
1548impl<'tcx, C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {}