rustc_middle/middle/codegen_fn_attrs/
ferrocene.rs1use rustc_hir::def::DefKind;
2use rustc_hir::def_id::{DefId, LocalDefId};
3use rustc_hir::{
4 ForeignItem, ForeignItemKind, Item, ItemKind, Node, TraitFn, TraitItem, TraitItemKind,
5};
6use rustc_macros::{StableHash, TyDecodable, TyEncodable};
7use rustc_middle::ty::{self, TyCtxt};
8use rustc_span::{Span, Symbol, sym};
9use tracing::{info, instrument};
10
11#[derive(#[automatically_derived]
impl ::core::clone::Clone for Validated {
#[inline]
fn clone(&self) -> Validated { Validated {} }
}Clone, const _: () =
{
impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
::rustc_serialize::Encodable<__E> for Validated {
fn encode(&self, __encoder: &mut __E) {
match *self { Validated {} => {} }
}
}
};TyEncodable, const _: () =
{
impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
::rustc_serialize::Decodable<__D> for Validated {
fn decode(__decoder: &mut __D) -> Self { Validated {} }
}
};TyDecodable, const _: () =
{
impl ::rustc_data_structures::stable_hash::StableHash for Validated {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
match *self { Validated {} => {} }
}
}
};StableHash, #[automatically_derived]
impl ::core::fmt::Debug for Validated {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Validated")
}
}Debug)]
12pub struct Validated {
13 }
16
17const VALIDATED_ATTR: &[Symbol; 2] = &[sym::ferrocene, sym::prevalidated];
18
19#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ValidatedStatus {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
ValidatedStatus::Validated {
annotation: __self_0, inherited: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Validated", "annotation", __self_0, "inherited",
&__self_1),
ValidatedStatus::Unvalidated =>
::core::fmt::Formatter::write_str(f, "Unvalidated"),
ValidatedStatus::WorkaroundDelegationBugs =>
::core::fmt::Formatter::write_str(f,
"WorkaroundDelegationBugs"),
}
}
}Debug)]
20pub enum ValidatedStatus {
21 Validated {
22 annotation: Option<Span>,
25 inherited: bool,
31 },
32 Unvalidated,
33 WorkaroundDelegationBugs,
34}
35
36impl ValidatedStatus {
37 pub fn allowed_in_certified_build(self) -> bool {
38 match self {
39 ValidatedStatus::Validated { .. } => true,
40 ValidatedStatus::WorkaroundDelegationBugs | ValidatedStatus::Unvalidated => false,
41 }
42 }
43
44 pub fn needs_test(self) -> bool {
45 match self {
46 ValidatedStatus::Validated { annotation, inherited } => {
47 annotation.is_some() || inherited
48 }
49 _ => false,
50 }
51 }
52}
53
54fn implied_validation(tcx: TyCtxt<'_>, local: LocalDefId) -> Option<ValidatedStatus> {
55 match tcx.hir_node_by_def_id(local) {
56 Node::Item(Item { kind: ItemKind::Fn { has_body: false, .. }, .. })
60 | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(..), .. })
62 | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Required(_)), .. }) => {
63 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/middle/codegen_fn_attrs/ferrocene.rs:63",
"rustc_middle::middle::codegen_fn_attrs::ferrocene",
::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/middle/codegen_fn_attrs/ferrocene.rs"),
::tracing_core::__macro_support::Option::Some(63u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::middle::codegen_fn_attrs::ferrocene"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::INFO <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::INFO <=
::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!("skipping item {0:?}",
local) as &dyn ::tracing::field::Value))])
});
} else { ; }
};info!("skipping item {local:?}");
64 return Some(ValidatedStatus::Validated { annotation: None, inherited: false, });
65 }
66 Node::ImplItem(..) => {}
67 _ => return None,
68 }
69
70 let parent = tcx.parent(local.into());
72 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/middle/codegen_fn_attrs/ferrocene.rs:72",
"rustc_middle::middle::codegen_fn_attrs::ferrocene",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/middle/codegen_fn_attrs/ferrocene.rs"),
::tracing_core::__macro_support::Option::Some(72u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::middle::codegen_fn_attrs::ferrocene"),
::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!("parent={1:?}, kind={0:?}",
tcx.def_kind(parent), parent) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};tracing::debug!("parent={parent:?}, kind={:?}", tcx.def_kind(parent));
73 #[allow(deprecated)]
74 if #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(parent) {
DefKind::Impl { .. } => true,
_ => false,
}matches!(tcx.def_kind(parent), DefKind::Impl { .. }) {
75 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/middle/codegen_fn_attrs/ferrocene.rs:75",
"rustc_middle::middle::codegen_fn_attrs::ferrocene",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/middle/codegen_fn_attrs/ferrocene.rs"),
::tracing_core::__macro_support::Option::Some(75u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::middle::codegen_fn_attrs::ferrocene"),
::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!("attrs={0:?}",
tcx.get_all_attrs(parent)) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};tracing::debug!("attrs={:?}", tcx.get_all_attrs(parent));
76 }
77
78 let derived = #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(parent) {
DefKind::Impl { .. } => true,
_ => false,
}matches!(tcx.def_kind(parent), DefKind::Impl { .. })
79 && tcx.is_automatically_derived(parent);
80
81 if !derived {
82 return None;
83 }
84
85 if !tcx.is_builtin_derived(parent) {
88 return Some(ValidatedStatus::Unvalidated);
89 }
90
91 let self_ty = tcx.type_of(parent);
92 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/middle/codegen_fn_attrs/ferrocene.rs:92",
"rustc_middle::middle::codegen_fn_attrs::ferrocene",
::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/middle/codegen_fn_attrs/ferrocene.rs"),
::tracing_core::__macro_support::Option::Some(92u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::middle::codegen_fn_attrs::ferrocene"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::INFO <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::INFO <=
::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!("checking {0:?}",
self_ty) as &dyn ::tracing::field::Value))])
});
} else { ; }
};info!("checking {self_ty:?}");
93 let unwrapped_ty = self_ty.skip_binder().peel_refs();
95 match unwrapped_ty.kind() {
96 ty::Adt(adt_def, _) => {
97 let self_id = adt_def.did();
98 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/middle/codegen_fn_attrs/ferrocene.rs:98",
"rustc_middle::middle::codegen_fn_attrs::ferrocene",
::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/middle/codegen_fn_attrs/ferrocene.rs"),
::tracing_core::__macro_support::Option::Some(98u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::middle::codegen_fn_attrs::ferrocene"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::INFO <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::INFO <=
::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!("{0} is marked #[automatically_derived], checking {1}",
tcx.def_path_str(local), tcx.def_path_str(self_id)) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};info!(
99 "{} is marked #[automatically_derived], checking {}",
100 tcx.def_path_str(local),
101 tcx.def_path_str(self_id)
102 );
103 return Some(item_is_validated(tcx, self_id));
104 }
105 ty::Error(..) => None,
106 _ if unwrapped_ty.is_primitive_ty() => None,
107 _ => Some(ValidatedStatus::Unvalidated),
110 }
111}
112
113x;#[instrument(skip(tcx), ret)]
118pub fn item_is_validated(tcx: TyCtxt<'_>, def_id: DefId) -> ValidatedStatus {
119 let owner = tcx.typeck_root_def_id(def_id);
121
122 let synthetic = match tcx.def_kind(owner) {
124 DefKind::Ctor(..) | DefKind::SyntheticCoroutineBody => true,
125 _ => tcx.intrinsic(owner).is_some_and(|def| def.must_be_overridden),
128 };
129 if synthetic {
130 info!("skipping synthetic item {owner:?}");
131 return ValidatedStatus::Validated { annotation: None, inherited: false };
132 }
133
134 if let Some(local) = owner.as_local()
135 && let Some(status) = implied_validation(tcx, local)
136 {
137 return status;
138 }
139
140 if let Some(annotation) = any_parent_is_validated(tcx, owner) {
141 return annotation;
142 }
143
144 let delegation_enabled = tcx.dcx().has_errors().is_some() || tcx.features().fn_delegation();
148 let is_main = delegation_enabled || tcx.entry_fn(()).map_or(false, |(main, _)| main == owner);
149 let main_is_validated = is_main && !tcx.sess.opts.test;
152
153 if delegation_enabled {
154 ValidatedStatus::WorkaroundDelegationBugs
156 } else if main_is_validated {
157 ValidatedStatus::Validated { annotation: None, inherited: false }
158 } else {
159 ValidatedStatus::Unvalidated
160 }
161}
162
163fn any_parent_is_validated(tcx: TyCtxt<'_>, item: DefId) -> Option<ValidatedStatus> {
165 let mut current = item;
166 loop {
167 match tcx.def_kind(current) {
170 DefKind::ForeignMod => {
171 current = tcx.parent(current);
172 continue;
173 }
174 _ => {}
175 }
176 if let Some(attr) = tcx.get_attrs_by_path(current, VALIDATED_ATTR).next() {
178 return Some(ValidatedStatus::Validated {
179 annotation: Some(attr.span()),
180 inherited: current != item,
181 });
182 }
183
184 if current.is_crate_root() {
185 return None;
186 }
187
188 current = tcx.parent(current);
189 }
190}