1use std::{assert_matches, iter};
2
3use rustc_abi::Primitive::Pointer;
4use rustc_abi::{Align, BackendRepr, ExternAbi, PointerKind, Scalar, Size};
5use rustc_hir as hir;
6use rustc_hir::lang_items::LangItem;
7use rustc_middle::bug;
8use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs;
9use rustc_middle::query::Providers;
10use rustc_middle::ty::layout::{
11 FnAbiError, HasTyCtxt, HasTypingEnv, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind,
12};
13use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt};
14use rustc_span::DUMMY_SP;
15use rustc_span::def_id::DefId;
16use rustc_target::callconv::{
17 AbiMap, ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, FnAbi, PassMode,
18};
19use tracing::debug;
20
21pub(crate) fn provide(providers: &mut Providers) {
22 *providers = Providers {
23 fn_abi_of_fn_ptr,
24 fn_abi_of_instance_no_deduced_attrs,
25 fn_abi_of_instance_raw,
26 ..*providers
27 };
28}
29
30#[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_sig_for_fn_abi",
"rustc_ty_utils::abi", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/abi.rs"),
::tracing_core::__macro_support::Option::Some(35u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
::tracing_core::field::FieldSet::new(&["instance"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instance)
as &dyn 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: ty::FnSig<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
if let InstanceKind::ThreadLocalShim(..) = instance.def {
return tcx.mk_fn_sig([],
tcx.thread_local_ptr_ty(instance.def_id()), false,
hir::Safety::Safe, rustc_abi::ExternAbi::Rust);
}
let ty = instance.ty(tcx, typing_env);
match *ty.kind() {
ty::FnDef(def_id, args) => {
let mut sig =
tcx.instantiate_bound_regions_with_erased(tcx.fn_sig(def_id).instantiate(tcx,
args));
if let ty::InstanceKind::VTableShim(..) = instance.def {
let mut inputs_and_output = sig.inputs_and_output.to_vec();
inputs_and_output[0] =
Ty::new_mut_ptr(tcx, inputs_and_output[0]);
sig.inputs_and_output =
tcx.mk_type_list(&inputs_and_output);
}
sig
}
ty::Closure(def_id, args) => {
let sig =
tcx.instantiate_bound_regions_with_erased(args.as_closure().sig());
let env_ty =
tcx.closure_env_ty(Ty::new_closure(tcx, def_id, args),
args.as_closure().kind(), tcx.lifetimes.re_erased);
tcx.mk_fn_sig(iter::once(env_ty).chain(sig.inputs().iter().cloned()),
sig.output(), sig.c_variadic, sig.safety, sig.abi)
}
ty::CoroutineClosure(def_id, args) => {
let coroutine_ty =
Ty::new_coroutine_closure(tcx, def_id, args);
let sig =
args.as_coroutine_closure().coroutine_closure_sig();
let mut coroutine_kind = args.as_coroutine_closure().kind();
let env_ty =
if let InstanceKind::ConstructCoroutineInClosureShim {
receiver_by_ref, .. } = instance.def {
coroutine_kind = ty::ClosureKind::FnOnce;
if receiver_by_ref {
Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty)
} else { coroutine_ty }
} else {
tcx.closure_env_ty(coroutine_ty, coroutine_kind,
tcx.lifetimes.re_erased)
};
let sig = tcx.instantiate_bound_regions_with_erased(sig);
tcx.mk_fn_sig(iter::once(env_ty).chain([sig.tupled_inputs_ty]),
sig.to_coroutine_given_kind_and_upvars(tcx,
args.as_coroutine_closure().parent_args(),
tcx.coroutine_for_closure(def_id), coroutine_kind,
tcx.lifetimes.re_erased,
args.as_coroutine_closure().tupled_upvars_ty(),
args.as_coroutine_closure().coroutine_captures_by_ref_ty()),
sig.c_variadic, sig.safety, sig.abi)
}
ty::Coroutine(did, args) => {
let coroutine_kind = tcx.coroutine_kind(did).unwrap();
let sig = args.as_coroutine().sig();
let env_ty =
Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty);
let pin_did =
tcx.require_lang_item(LangItem::Pin, DUMMY_SP);
let pin_adt_ref = tcx.adt_def(pin_did);
let pin_args = tcx.mk_args(&[env_ty.into()]);
let env_ty =
match coroutine_kind {
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen,
_) => {
env_ty
}
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async,
_) |
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen,
_) | hir::CoroutineKind::Coroutine(_) =>
Ty::new_adt(tcx, pin_adt_ref, pin_args),
};
let (resume_ty, ret_ty) =
match coroutine_kind {
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async,
_) => {
match (&sig.yield_ty, &tcx.types.unit) {
(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);
}
}
};
let poll_did =
tcx.require_lang_item(LangItem::Poll, DUMMY_SP);
let poll_adt_ref = tcx.adt_def(poll_did);
let poll_args = tcx.mk_args(&[sig.return_ty.into()]);
let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_args);
{
if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
let expected_adt =
tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy,
DUMMY_SP));
match (&*resume_ty_adt, &expected_adt) {
(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);
}
}
};
} else {
{
::core::panicking::panic_fmt(format_args!("expected `ResumeTy`, found `{0:?}`",
sig.resume_ty));
};
};
}
let context_mut_ref = Ty::new_task_context(tcx);
(Some(context_mut_ref), ret_ty)
}
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen,
_) => {
let option_did =
tcx.require_lang_item(LangItem::Option, DUMMY_SP);
let option_adt_ref = tcx.adt_def(option_did);
let option_args = tcx.mk_args(&[sig.yield_ty.into()]);
let ret_ty = Ty::new_adt(tcx, option_adt_ref, option_args);
match (&sig.return_ty, &tcx.types.unit) {
(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);
}
}
};
match (&sig.resume_ty, &tcx.types.unit) {
(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);
}
}
};
(None, ret_ty)
}
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen,
_) => {
match (&sig.return_ty, &tcx.types.unit) {
(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);
}
}
};
let ret_ty = sig.yield_ty;
{
if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
let expected_adt =
tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy,
DUMMY_SP));
match (&*resume_ty_adt, &expected_adt) {
(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);
}
}
};
} else {
{
::core::panicking::panic_fmt(format_args!("expected `ResumeTy`, found `{0:?}`",
sig.resume_ty));
};
};
}
let context_mut_ref = Ty::new_task_context(tcx);
(Some(context_mut_ref), ret_ty)
}
hir::CoroutineKind::Coroutine(_) => {
let state_did =
tcx.require_lang_item(LangItem::CoroutineState, DUMMY_SP);
let state_adt_ref = tcx.adt_def(state_did);
let state_args =
tcx.mk_args(&[sig.yield_ty.into(), sig.return_ty.into()]);
let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_args);
(Some(sig.resume_ty), ret_ty)
}
};
if let Some(resume_ty) = resume_ty {
tcx.mk_fn_sig([env_ty, resume_ty], ret_ty, false,
hir::Safety::Safe, rustc_abi::ExternAbi::Rust)
} else {
tcx.mk_fn_sig([env_ty], ret_ty, false, hir::Safety::Safe,
rustc_abi::ExternAbi::Rust)
}
}
_ =>
::rustc_middle::util::bug::bug_fmt(format_args!("unexpected type {0:?} in Instance::fn_sig",
ty)),
}
}
}
}#[tracing::instrument(level = "debug", skip(tcx, typing_env))]
36fn fn_sig_for_fn_abi<'tcx>(
37 tcx: TyCtxt<'tcx>,
38 instance: ty::Instance<'tcx>,
39 typing_env: ty::TypingEnv<'tcx>,
40) -> ty::FnSig<'tcx> {
41 if let InstanceKind::ThreadLocalShim(..) = instance.def {
42 return tcx.mk_fn_sig(
43 [],
44 tcx.thread_local_ptr_ty(instance.def_id()),
45 false,
46 hir::Safety::Safe,
47 rustc_abi::ExternAbi::Rust,
48 );
49 }
50
51 let ty = instance.ty(tcx, typing_env);
52 match *ty.kind() {
53 ty::FnDef(def_id, args) => {
54 let mut sig = tcx
55 .instantiate_bound_regions_with_erased(tcx.fn_sig(def_id).instantiate(tcx, args));
56
57 if let ty::InstanceKind::VTableShim(..) = instance.def {
59 let mut inputs_and_output = sig.inputs_and_output.to_vec();
60 inputs_and_output[0] = Ty::new_mut_ptr(tcx, inputs_and_output[0]);
61 sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
62 }
63
64 sig
65 }
66 ty::Closure(def_id, args) => {
67 let sig = tcx.instantiate_bound_regions_with_erased(args.as_closure().sig());
68 let env_ty = tcx.closure_env_ty(
69 Ty::new_closure(tcx, def_id, args),
70 args.as_closure().kind(),
71 tcx.lifetimes.re_erased,
72 );
73
74 tcx.mk_fn_sig(
75 iter::once(env_ty).chain(sig.inputs().iter().cloned()),
76 sig.output(),
77 sig.c_variadic,
78 sig.safety,
79 sig.abi,
80 )
81 }
82 ty::CoroutineClosure(def_id, args) => {
83 let coroutine_ty = Ty::new_coroutine_closure(tcx, def_id, args);
84 let sig = args.as_coroutine_closure().coroutine_closure_sig();
85
86 let mut coroutine_kind = args.as_coroutine_closure().kind();
91
92 let env_ty =
93 if let InstanceKind::ConstructCoroutineInClosureShim { receiver_by_ref, .. } =
94 instance.def
95 {
96 coroutine_kind = ty::ClosureKind::FnOnce;
97
98 if receiver_by_ref {
101 Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty)
102 } else {
103 coroutine_ty
104 }
105 } else {
106 tcx.closure_env_ty(coroutine_ty, coroutine_kind, tcx.lifetimes.re_erased)
107 };
108
109 let sig = tcx.instantiate_bound_regions_with_erased(sig);
110
111 tcx.mk_fn_sig(
112 iter::once(env_ty).chain([sig.tupled_inputs_ty]),
113 sig.to_coroutine_given_kind_and_upvars(
114 tcx,
115 args.as_coroutine_closure().parent_args(),
116 tcx.coroutine_for_closure(def_id),
117 coroutine_kind,
118 tcx.lifetimes.re_erased,
119 args.as_coroutine_closure().tupled_upvars_ty(),
120 args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
121 ),
122 sig.c_variadic,
123 sig.safety,
124 sig.abi,
125 )
126 }
127 ty::Coroutine(did, args) => {
128 let coroutine_kind = tcx.coroutine_kind(did).unwrap();
129 let sig = args.as_coroutine().sig();
130
131 let env_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty);
132
133 let pin_did = tcx.require_lang_item(LangItem::Pin, DUMMY_SP);
134 let pin_adt_ref = tcx.adt_def(pin_did);
135 let pin_args = tcx.mk_args(&[env_ty.into()]);
136 let env_ty = match coroutine_kind {
137 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) => {
138 env_ty
141 }
142 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
143 | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)
144 | hir::CoroutineKind::Coroutine(_) => Ty::new_adt(tcx, pin_adt_ref, pin_args),
145 };
146
147 let (resume_ty, ret_ty) = match coroutine_kind {
154 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _) => {
155 assert_eq!(sig.yield_ty, tcx.types.unit);
157
158 let poll_did = tcx.require_lang_item(LangItem::Poll, DUMMY_SP);
159 let poll_adt_ref = tcx.adt_def(poll_did);
160 let poll_args = tcx.mk_args(&[sig.return_ty.into()]);
161 let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_args);
162
163 #[cfg(debug_assertions)]
166 {
167 if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
168 let expected_adt =
169 tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, DUMMY_SP));
170 assert_eq!(*resume_ty_adt, expected_adt);
171 } else {
172 panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty);
173 };
174 }
175 let context_mut_ref = Ty::new_task_context(tcx);
176
177 (Some(context_mut_ref), ret_ty)
178 }
179 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) => {
180 let option_did = tcx.require_lang_item(LangItem::Option, DUMMY_SP);
182 let option_adt_ref = tcx.adt_def(option_did);
183 let option_args = tcx.mk_args(&[sig.yield_ty.into()]);
184 let ret_ty = Ty::new_adt(tcx, option_adt_ref, option_args);
185
186 assert_eq!(sig.return_ty, tcx.types.unit);
187 assert_eq!(sig.resume_ty, tcx.types.unit);
188
189 (None, ret_ty)
190 }
191 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => {
192 assert_eq!(sig.return_ty, tcx.types.unit);
195
196 let ret_ty = sig.yield_ty;
198
199 #[cfg(debug_assertions)]
202 {
203 if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
204 let expected_adt =
205 tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, DUMMY_SP));
206 assert_eq!(*resume_ty_adt, expected_adt);
207 } else {
208 panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty);
209 };
210 }
211 let context_mut_ref = Ty::new_task_context(tcx);
212
213 (Some(context_mut_ref), ret_ty)
214 }
215 hir::CoroutineKind::Coroutine(_) => {
216 let state_did = tcx.require_lang_item(LangItem::CoroutineState, DUMMY_SP);
218 let state_adt_ref = tcx.adt_def(state_did);
219 let state_args = tcx.mk_args(&[sig.yield_ty.into(), sig.return_ty.into()]);
220 let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_args);
221
222 (Some(sig.resume_ty), ret_ty)
223 }
224 };
225
226 if let Some(resume_ty) = resume_ty {
227 tcx.mk_fn_sig(
228 [env_ty, resume_ty],
229 ret_ty,
230 false,
231 hir::Safety::Safe,
232 rustc_abi::ExternAbi::Rust,
233 )
234 } else {
235 tcx.mk_fn_sig(
237 [env_ty],
238 ret_ty,
239 false,
240 hir::Safety::Safe,
241 rustc_abi::ExternAbi::Rust,
242 )
243 }
244 }
245 _ => bug!("unexpected type {:?} in Instance::fn_sig", ty),
246 }
247}
248
249struct FnAbiDesc<'tcx> {
251 layout_cx: LayoutCx<'tcx>,
252 sig: ty::FnSig<'tcx>,
253
254 determined_fn_def_id: Option<DefId>,
256 caller_location: Option<Ty<'tcx>>,
257 is_virtual_call: bool,
258 extra_args: &'tcx [Ty<'tcx>],
259}
260
261impl<'tcx> FnAbiDesc<'tcx> {
262 fn for_fn_ptr(
263 tcx: TyCtxt<'tcx>,
264 query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
265 ) -> Self {
266 let ty::PseudoCanonicalInput { typing_env, value: (sig, extra_args) } = query;
267 Self {
268 layout_cx: LayoutCx::new(tcx, typing_env),
269 sig: tcx.normalize_erasing_regions(
270 typing_env,
271 tcx.instantiate_bound_regions_with_erased(sig),
272 ),
273 determined_fn_def_id: None,
276 caller_location: None,
277 is_virtual_call: false,
278 extra_args,
279 }
280 }
281
282 fn for_instance(
283 tcx: TyCtxt<'tcx>,
284 query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
285 ) -> Self {
286 let ty::PseudoCanonicalInput { typing_env, value: (instance, extra_args) } = query;
287 let is_virtual_call = #[allow(non_exhaustive_omitted_patterns)] match instance.def {
ty::InstanceKind::Virtual(..) => true,
_ => false,
}matches!(instance.def, ty::InstanceKind::Virtual(..));
288 let is_tls_shim_call = #[allow(non_exhaustive_omitted_patterns)] match instance.def {
ty::InstanceKind::ThreadLocalShim(_) => true,
_ => false,
}matches!(instance.def, ty::InstanceKind::ThreadLocalShim(_));
289 Self {
290 layout_cx: LayoutCx::new(tcx, typing_env),
291 sig: tcx.normalize_erasing_regions(
292 typing_env,
293 fn_sig_for_fn_abi(tcx, instance, typing_env),
294 ),
295 determined_fn_def_id: (!is_virtual_call && !is_tls_shim_call)
299 .then(|| instance.def_id()),
300 caller_location: instance
301 .def
302 .requires_caller_location(tcx)
303 .then(|| tcx.caller_location_ty()),
304 is_virtual_call,
305 extra_args,
306 }
307 }
308}
309
310fn fn_abi_of_fn_ptr<'tcx>(
311 tcx: TyCtxt<'tcx>,
312 query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
313) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
314 let desc = FnAbiDesc::for_fn_ptr(tcx, query);
315 fn_abi_new_uncached(desc)
316}
317
318fn fn_abi_of_instance_no_deduced_attrs<'tcx>(
319 tcx: TyCtxt<'tcx>,
320 query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
321) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
322 let desc = FnAbiDesc::for_instance(tcx, query);
323 fn_abi_new_uncached(desc)
324}
325
326fn fn_abi_of_instance_raw<'tcx>(
327 tcx: TyCtxt<'tcx>,
328 query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
329) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
330 tcx.fn_abi_of_instance_no_deduced_attrs(query).map(|fn_abi| {
333 let params = FnAbiDesc::for_instance(tcx, query);
334 params.determined_fn_def_id.map_or(fn_abi, |fn_def_id| {
337 fn_abi_adjust_for_deduced_attrs(¶ms.layout_cx, fn_abi, params.sig.abi, fn_def_id)
338 })
339 })
340}
341
342fn arg_attrs_for_rust_scalar<'tcx>(
352 cx: LayoutCx<'tcx>,
353 scalar: Scalar,
354 layout: TyAndLayout<'tcx>,
355 offset: Size,
356 is_return: bool,
357 drop_target_pointee: Option<Ty<'tcx>>,
358) -> ArgAttributes {
359 let mut attrs = ArgAttributes::new();
360
361 if scalar.is_bool() {
363 attrs.ext(ArgExtension::Zext);
364 attrs.set(ArgAttribute::NoUndef);
365 return attrs;
366 }
367
368 if !scalar.is_uninit_valid() {
369 attrs.set(ArgAttribute::NoUndef);
370 }
371
372 let Scalar::Initialized { value: Pointer(_), valid_range } = scalar else { return attrs };
374
375 if !valid_range.contains(0) || drop_target_pointee.is_some() {
378 attrs.set(ArgAttribute::NonNull);
379 }
380
381 let tcx = cx.tcx();
382
383 let drop_target_pointee_info = drop_target_pointee.and_then(|pointee| {
384 match (&pointee, &layout.ty.builtin_deref(true).unwrap()) {
(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!(pointee, layout.ty.builtin_deref(true).unwrap());
385 match (&offset, &Size::ZERO) {
(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!(offset, Size::ZERO);
386 let mutref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, pointee);
388 let layout = cx.layout_of(mutref).unwrap();
389 layout.pointee_info_at(&cx, offset)
390 });
391
392 if let Some(pointee) = drop_target_pointee_info.or_else(|| layout.pointee_info_at(&cx, offset))
393 {
394 if pointee.align > Align::ONE {
395 attrs.pointee_align =
396 Some(pointee.align.min(cx.tcx().sess.target.max_reliable_alignment()));
397 }
398
399 if !is_return {
404 attrs.pointee_size = pointee.size;
405 };
406
407 if let Some(kind) = pointee.safe {
408 let noalias_for_box = tcx.sess.opts.unstable_opts.box_noalias;
412
413 let noalias_mut_ref = tcx.sess.opts.unstable_opts.mutable_noalias;
417
418 let no_alias = match kind {
425 PointerKind::SharedRef { frozen } => frozen,
426 PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref,
427 PointerKind::Box { unpin, global } => unpin && global && noalias_for_box,
428 };
429 if no_alias && !is_return {
432 attrs.set(ArgAttribute::NoAlias);
433 }
434
435 if #[allow(non_exhaustive_omitted_patterns)] match kind {
PointerKind::SharedRef { frozen: true } => true,
_ => false,
}matches!(kind, PointerKind::SharedRef { frozen: true }) && !is_return {
436 attrs.set(ArgAttribute::ReadOnly);
437 attrs.set(ArgAttribute::CapturesReadOnly);
438 }
439 }
440 }
441
442 attrs
443}
444
445fn fn_abi_sanity_check<'tcx>(
447 cx: &LayoutCx<'tcx>,
448 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
449 spec_abi: ExternAbi,
450) {
451 fn fn_arg_sanity_check<'tcx>(
452 cx: &LayoutCx<'tcx>,
453 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
454 spec_abi: ExternAbi,
455 arg: &ArgAbi<'tcx, Ty<'tcx>>,
456 ) {
457 let tcx = cx.tcx();
458
459 if spec_abi.is_rustic_abi() {
460 if arg.layout.is_zst() {
461 if !arg.is_ignore() {
::core::panicking::panic("assertion failed: arg.is_ignore()")
};assert!(arg.is_ignore());
464 }
465 if let PassMode::Indirect { on_stack, .. } = arg.mode {
466 if !!on_stack {
{
::core::panicking::panic_fmt(format_args!("rust abi shouldn\'t use on_stack"));
}
};assert!(!on_stack, "rust abi shouldn't use on_stack");
467 }
468 } else if arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
469 match arg.mode {
PassMode::Indirect { on_stack: false, .. } => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"PassMode::Indirect { on_stack: false, .. }",
::core::option::Option::Some(format_args!("the {0} ABI does not implement `#[rustc_pass_indirectly_in_non_rustic_abis]`",
spec_abi)));
}
};assert_matches!(
470 arg.mode,
471 PassMode::Indirect { on_stack: false, .. },
472 "the {spec_abi} ABI does not implement `#[rustc_pass_indirectly_in_non_rustic_abis]`"
473 );
474 }
475
476 match &arg.mode {
477 PassMode::Ignore => {
478 if !arg.layout.is_zst() {
::core::panicking::panic("assertion failed: arg.layout.is_zst()")
};assert!(arg.layout.is_zst());
479 }
480 PassMode::Direct(_) => {
481 match arg.layout.backend_repr {
486 BackendRepr::Scalar(_)
487 | BackendRepr::SimdVector { .. }
488 | BackendRepr::ScalableVector { .. } => {}
489 BackendRepr::ScalarPair(..) => {
490 {
::core::panicking::panic_fmt(format_args!("`PassMode::Direct` used for ScalarPair type {0}",
arg.layout.ty));
}panic!("`PassMode::Direct` used for ScalarPair type {}", arg.layout.ty)
491 }
492 BackendRepr::Memory { sized } => {
493 if !sized {
{
::core::panicking::panic_fmt(format_args!("`PassMode::Direct` for unsized type in ABI: {0:#?}",
fn_abi));
}
};assert!(sized, "`PassMode::Direct` for unsized type in ABI: {:#?}", fn_abi);
496
497 if !#[allow(non_exhaustive_omitted_patterns)] match spec_abi {
ExternAbi::Unadjusted => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("`PassMode::Direct` for aggregates only allowed for \"unadjusted\"\nProblematic type: {0:#?}",
arg.layout));
}
};assert!(
503 matches!(spec_abi, ExternAbi::Unadjusted),
504 "`PassMode::Direct` for aggregates only allowed for \"unadjusted\"\n\
505 Problematic type: {:#?}",
506 arg.layout,
507 );
508 }
509 }
510 }
511 PassMode::Pair(_, _) => {
512 if !#[allow(non_exhaustive_omitted_patterns)] match arg.layout.backend_repr {
BackendRepr::ScalarPair(..) => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("PassMode::Pair for type {0}",
arg.layout.ty));
}
};assert!(
515 matches!(arg.layout.backend_repr, BackendRepr::ScalarPair(..)),
516 "PassMode::Pair for type {}",
517 arg.layout.ty
518 );
519 }
520 PassMode::Cast { .. } => {
521 if !arg.layout.is_sized() {
::core::panicking::panic("assertion failed: arg.layout.is_sized()")
};assert!(arg.layout.is_sized());
523 }
524 PassMode::Indirect { meta_attrs: None, .. } => {
525 if !arg.layout.is_sized() {
::core::panicking::panic("assertion failed: arg.layout.is_sized()")
};assert!(arg.layout.is_sized());
530 }
531 PassMode::Indirect { meta_attrs: Some(_), on_stack, .. } => {
532 if !(arg.layout.is_unsized() && !on_stack) {
::core::panicking::panic("assertion failed: arg.layout.is_unsized() && !on_stack")
};assert!(arg.layout.is_unsized() && !on_stack);
534 let tail = tcx.struct_tail_for_codegen(arg.layout.ty, cx.typing_env);
536 if #[allow(non_exhaustive_omitted_patterns)] match tail.kind() {
ty::Foreign(..) => true,
_ => false,
}matches!(tail.kind(), ty::Foreign(..)) {
537 {
::core::panicking::panic_fmt(format_args!("unsized arguments must not be `extern` types"));
};panic!("unsized arguments must not be `extern` types");
542 }
543 }
544 }
545 }
546
547 for arg in fn_abi.args.iter() {
548 fn_arg_sanity_check(cx, fn_abi, spec_abi, arg);
549 }
550 fn_arg_sanity_check(cx, fn_abi, spec_abi, &fn_abi.ret);
551}
552
553#[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_new_uncached",
"rustc_ty_utils::abi", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/abi.rs"),
::tracing_core::__macro_support::Option::Some(553u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
::tracing_core::field::FieldSet::new(&["sig", "extra_args"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sig)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&extra_args)
as &dyn 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:
Result<&'tcx FnAbi<'tcx, Ty<'tcx>>,
&'tcx FnAbiError<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
let tcx = cx.tcx();
let abi_map = AbiMap::from_target(&tcx.sess.target);
let conv = abi_map.canonize_abi(sig.abi, sig.c_variadic).unwrap();
let mut inputs = sig.inputs();
let extra_args =
if sig.abi == ExternAbi::RustCall {
if !(!sig.c_variadic && extra_args.is_empty()) {
::core::panicking::panic("assertion failed: !sig.c_variadic && extra_args.is_empty()")
};
if let Some(input) = sig.inputs().last() &&
let ty::Tuple(tupled_arguments) = input.kind() {
inputs = &sig.inputs()[0..sig.inputs().len() - 1];
tupled_arguments
} else {
::rustc_middle::util::bug::bug_fmt(format_args!("argument to function with \"rust-call\" ABI is not a tuple"));
}
} else {
if !(sig.c_variadic || extra_args.is_empty()) {
::core::panicking::panic("assertion failed: sig.c_variadic || extra_args.is_empty()")
};
extra_args
};
let is_drop_in_place =
determined_fn_def_id.is_some_and(|def_id|
{
tcx.is_lang_item(def_id, LangItem::DropInPlace) ||
tcx.is_lang_item(def_id, LangItem::AsyncDropInPlace)
});
let arg_of =
|ty: Ty<'tcx>, arg_idx: Option<usize>|
-> Result<_, &'tcx FnAbiError<'tcx>>
{
let span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("arg_of",
"rustc_ty_utils::abi", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/abi.rs"),
::tracing_core::__macro_support::Option::Some(598u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
::tracing_core::field::FieldSet::new(&[],
::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,
&{ meta.fields().value_set(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
let _entered = span.enter();
let is_return = arg_idx.is_none();
let is_drop_target = is_drop_in_place && arg_idx == Some(0);
let drop_target_pointee =
is_drop_target.then(||
match ty.kind() {
ty::RawPtr(ty, _) => *ty,
_ =>
::rustc_middle::util::bug::bug_fmt(format_args!("argument to drop_in_place is not a raw ptr: {0:?}",
ty)),
});
let layout =
cx.layout_of(ty).map_err(|err|
&*tcx.arena.alloc(FnAbiError::Layout(*err)))?;
let layout =
if is_virtual_call && arg_idx == Some(0) {
make_thin_self_ptr(cx, layout)
} else { layout };
Ok(ArgAbi::new(cx, layout,
|scalar, offset|
{
arg_attrs_for_rust_scalar(*cx, scalar, layout, offset,
is_return,
drop_target_pointee.filter(|_| offset == Size::ZERO))
}))
};
let mut fn_abi =
FnAbi {
ret: arg_of(sig.output(), None)?,
args: inputs.iter().copied().chain(extra_args.iter().copied()).chain(caller_location).enumerate().map(|(i,
ty)| arg_of(ty, Some(i))).collect::<Result<_, _>>()?,
c_variadic: sig.c_variadic,
fixed_count: inputs.len() as u32,
conv,
can_unwind: fn_can_unwind(tcx, determined_fn_def_id,
sig.abi),
};
fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/abi.rs:653",
"rustc_ty_utils::abi", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/abi.rs"),
::tracing_core::__macro_support::Option::Some(653u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("fn_abi_new_uncached = {0:?}",
fn_abi) as &dyn Value))])
});
} else { ; }
};
fn_abi_sanity_check(cx, &fn_abi, sig.abi);
Ok(tcx.arena.alloc(fn_abi))
}
}
}#[tracing::instrument(
554 level = "debug",
555 skip(cx, caller_location, determined_fn_def_id, is_virtual_call)
556)]
557fn fn_abi_new_uncached<'tcx>(
558 FnAbiDesc {
559 layout_cx: ref cx,
560 sig,
561 determined_fn_def_id,
562 caller_location,
563 is_virtual_call,
564 extra_args,
565 }: FnAbiDesc<'tcx>,
566) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
567 let tcx = cx.tcx();
568
569 let abi_map = AbiMap::from_target(&tcx.sess.target);
570 let conv = abi_map.canonize_abi(sig.abi, sig.c_variadic).unwrap();
571
572 let mut inputs = sig.inputs();
573 let extra_args = if sig.abi == ExternAbi::RustCall {
574 assert!(!sig.c_variadic && extra_args.is_empty());
575
576 if let Some(input) = sig.inputs().last()
577 && let ty::Tuple(tupled_arguments) = input.kind()
578 {
579 inputs = &sig.inputs()[0..sig.inputs().len() - 1];
580 tupled_arguments
581 } else {
582 bug!(
583 "argument to function with \"rust-call\" ABI \
584 is not a tuple"
585 );
586 }
587 } else {
588 assert!(sig.c_variadic || extra_args.is_empty());
589 extra_args
590 };
591
592 let is_drop_in_place = determined_fn_def_id.is_some_and(|def_id| {
593 tcx.is_lang_item(def_id, LangItem::DropInPlace)
594 || tcx.is_lang_item(def_id, LangItem::AsyncDropInPlace)
595 });
596
597 let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, &'tcx FnAbiError<'tcx>> {
598 let span = tracing::debug_span!("arg_of");
599 let _entered = span.enter();
600 let is_return = arg_idx.is_none();
601 let is_drop_target = is_drop_in_place && arg_idx == Some(0);
602 let drop_target_pointee = is_drop_target.then(|| match ty.kind() {
603 ty::RawPtr(ty, _) => *ty,
604 _ => bug!("argument to drop_in_place is not a raw ptr: {:?}", ty),
605 });
606
607 let layout = cx.layout_of(ty).map_err(|err| &*tcx.arena.alloc(FnAbiError::Layout(*err)))?;
608 let layout = if is_virtual_call && arg_idx == Some(0) {
609 make_thin_self_ptr(cx, layout)
613 } else {
614 layout
615 };
616
617 Ok(ArgAbi::new(cx, layout, |scalar, offset| {
618 arg_attrs_for_rust_scalar(
619 *cx,
620 scalar,
621 layout,
622 offset,
623 is_return,
624 drop_target_pointee.filter(|_| offset == Size::ZERO),
627 )
628 }))
629 };
630
631 let mut fn_abi = FnAbi {
632 ret: arg_of(sig.output(), None)?,
633 args: inputs
634 .iter()
635 .copied()
636 .chain(extra_args.iter().copied())
637 .chain(caller_location)
638 .enumerate()
639 .map(|(i, ty)| arg_of(ty, Some(i)))
640 .collect::<Result<_, _>>()?,
641 c_variadic: sig.c_variadic,
642 fixed_count: inputs.len() as u32,
643 conv,
644 can_unwind: fn_can_unwind(
646 tcx,
647 determined_fn_def_id,
649 sig.abi,
650 ),
651 };
652 fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi);
653 debug!("fn_abi_new_uncached = {:?}", fn_abi);
654 fn_abi_sanity_check(cx, &fn_abi, sig.abi);
655 Ok(tcx.arena.alloc(fn_abi))
656}
657
658#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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_adjust_for_abi",
"rustc_ty_utils::abi", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/abi.rs"),
::tracing_core::__macro_support::Option::Some(658u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
::tracing_core::field::FieldSet::new(&["fn_abi", "abi"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&fn_abi)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&abi)
as &dyn 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: () = loop {};
return __tracing_attr_fake_return;
}
{
if abi == ExternAbi::Unadjusted {
fn unadjust<'tcx>(arg: &mut ArgAbi<'tcx, Ty<'tcx>>) {
if #[allow(non_exhaustive_omitted_patterns)] match arg.layout.backend_repr
{
BackendRepr::Memory { .. } => true,
_ => false,
} {
if !arg.layout.backend_repr.is_sized() {
{
::core::panicking::panic_fmt(format_args!("\'unadjusted\' ABI does not support unsized arguments"));
}
};
}
arg.make_direct_deprecated();
}
unadjust(&mut fn_abi.ret);
for arg in fn_abi.args.iter_mut() { unadjust(arg); }
} else if abi.is_rustic_abi() {
fn_abi.adjust_for_rust_abi(cx);
} else { fn_abi.adjust_for_foreign_abi(cx, abi); }
}
}
}#[tracing::instrument(level = "trace", skip(cx))]
659fn fn_abi_adjust_for_abi<'tcx>(
660 cx: &LayoutCx<'tcx>,
661 fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
662 abi: ExternAbi,
663) {
664 if abi == ExternAbi::Unadjusted {
665 fn unadjust<'tcx>(arg: &mut ArgAbi<'tcx, Ty<'tcx>>) {
668 if matches!(arg.layout.backend_repr, BackendRepr::Memory { .. }) {
671 assert!(
672 arg.layout.backend_repr.is_sized(),
673 "'unadjusted' ABI does not support unsized arguments"
674 );
675 }
676 arg.make_direct_deprecated();
677 }
678
679 unadjust(&mut fn_abi.ret);
680 for arg in fn_abi.args.iter_mut() {
681 unadjust(arg);
682 }
683 } else if abi.is_rustic_abi() {
684 fn_abi.adjust_for_rust_abi(cx);
685 } else {
686 fn_abi.adjust_for_foreign_abi(cx, abi);
687 }
688}
689
690#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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_adjust_for_deduced_attrs",
"rustc_ty_utils::abi", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/abi.rs"),
::tracing_core::__macro_support::Option::Some(690u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
::tracing_core::field::FieldSet::new(&["fn_abi", "abi",
"fn_def_id"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&fn_abi)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&abi)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&fn_def_id)
as &dyn 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: &'tcx FnAbi<'tcx, Ty<'tcx>> =
loop {};
return __tracing_attr_fake_return;
}
{
let tcx = cx.tcx();
let deduced =
if abi.is_rustic_abi() {
tcx.deduced_param_attrs(fn_def_id)
} else { &[] };
if deduced.is_empty() {
fn_abi
} else {
let mut fn_abi = fn_abi.clone();
apply_deduced_attributes(cx, deduced, 0, &mut fn_abi.ret);
for (arg_idx, arg) in fn_abi.args.iter_mut().enumerate() {
apply_deduced_attributes(cx, deduced, arg_idx + 1, arg);
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/abi.rs:709",
"rustc_ty_utils::abi", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/abi.rs"),
::tracing_core::__macro_support::Option::Some(709u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("fn_abi_adjust_for_deduced_attrs = {0:?}",
fn_abi) as &dyn Value))])
});
} else { ; }
};
fn_abi_sanity_check(cx, &fn_abi, abi);
tcx.arena.alloc(fn_abi)
}
}
}
}#[tracing::instrument(level = "trace", skip(cx))]
691fn fn_abi_adjust_for_deduced_attrs<'tcx>(
692 cx: &LayoutCx<'tcx>,
693 fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
694 abi: ExternAbi,
695 fn_def_id: DefId,
696) -> &'tcx FnAbi<'tcx, Ty<'tcx>> {
697 let tcx = cx.tcx();
698 let deduced = if abi.is_rustic_abi() { tcx.deduced_param_attrs(fn_def_id) } else { &[] };
701 if deduced.is_empty() {
702 fn_abi
703 } else {
704 let mut fn_abi = fn_abi.clone();
705 apply_deduced_attributes(cx, deduced, 0, &mut fn_abi.ret);
706 for (arg_idx, arg) in fn_abi.args.iter_mut().enumerate() {
707 apply_deduced_attributes(cx, deduced, arg_idx + 1, arg);
708 }
709 debug!("fn_abi_adjust_for_deduced_attrs = {:?}", fn_abi);
710 fn_abi_sanity_check(cx, &fn_abi, abi);
711 tcx.arena.alloc(fn_abi)
712 }
713}
714
715fn apply_deduced_attributes<'tcx>(
720 cx: &LayoutCx<'tcx>,
721 deduced: &[DeducedParamAttrs],
722 idx: usize,
723 arg: &mut ArgAbi<'tcx, Ty<'tcx>>,
724) {
725 let PassMode::Indirect { ref mut attrs, .. } = arg.mode else {
727 return;
728 };
729 let Some(deduced) = deduced.get(idx) else {
731 return;
732 };
733 if deduced.read_only(cx.tcx(), cx.typing_env, arg.layout.ty) {
734 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/abi.rs:734",
"rustc_ty_utils::abi", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/abi.rs"),
::tracing_core::__macro_support::Option::Some(734u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("added deduced ReadOnly attribute")
as &dyn Value))])
});
} else { ; }
};debug!("added deduced ReadOnly attribute");
735 attrs.regular.insert(ArgAttribute::ReadOnly);
736 }
737 if deduced.captures_none(cx.tcx(), cx.typing_env, arg.layout.ty) {
738 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/abi.rs:738",
"rustc_ty_utils::abi", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/abi.rs"),
::tracing_core::__macro_support::Option::Some(738u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("added deduced CapturesNone attribute")
as &dyn Value))])
});
} else { ; }
};debug!("added deduced CapturesNone attribute");
739 attrs.regular.insert(ArgAttribute::CapturesNone);
740 }
741}
742
743#[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("make_thin_self_ptr",
"rustc_ty_utils::abi", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/abi.rs"),
::tracing_core::__macro_support::Option::Some(743u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
::tracing_core::field::FieldSet::new(&["layout"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&layout)
as &dyn 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: TyAndLayout<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
let tcx = cx.tcx();
let wide_pointer_ty =
if layout.is_unsized() {
Ty::new_mut_ptr(tcx, layout.ty)
} else {
match layout.backend_repr {
BackendRepr::ScalarPair(..) | BackendRepr::Scalar(..) => (),
_ =>
::rustc_middle::util::bug::bug_fmt(format_args!("receiver type has unsupported layout: {0:?}",
layout)),
}
let mut wide_pointer_layout = layout;
while !wide_pointer_layout.ty.is_raw_ptr() &&
!wide_pointer_layout.ty.is_ref() {
wide_pointer_layout =
wide_pointer_layout.non_1zst_field(cx).expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type").1
}
wide_pointer_layout.ty
};
let unit_ptr_ty = Ty::new_mut_ptr(tcx, tcx.types.unit);
TyAndLayout {
ty: wide_pointer_ty,
..tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(unit_ptr_ty)).unwrap()
}
}
}
}#[tracing::instrument(level = "debug", skip(cx))]
744fn make_thin_self_ptr<'tcx>(
745 cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>),
746 layout: TyAndLayout<'tcx>,
747) -> TyAndLayout<'tcx> {
748 let tcx = cx.tcx();
749 let wide_pointer_ty = if layout.is_unsized() {
750 Ty::new_mut_ptr(tcx, layout.ty)
753 } else {
754 match layout.backend_repr {
755 BackendRepr::ScalarPair(..) | BackendRepr::Scalar(..) => (),
756 _ => bug!("receiver type has unsupported layout: {:?}", layout),
757 }
758
759 let mut wide_pointer_layout = layout;
765 while !wide_pointer_layout.ty.is_raw_ptr() && !wide_pointer_layout.ty.is_ref() {
766 wide_pointer_layout = wide_pointer_layout
767 .non_1zst_field(cx)
768 .expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type")
769 .1
770 }
771
772 wide_pointer_layout.ty
773 };
774
775 let unit_ptr_ty = Ty::new_mut_ptr(tcx, tcx.types.unit);
779
780 TyAndLayout {
781 ty: wide_pointer_ty,
782
783 ..tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(unit_ptr_ty)).unwrap()
786 }
787}