Auto merge of #129881 - veluca93:struct_tf, r= · rust-lang/rust@446b363 (original) (raw)
`@@ -8,7 +8,8 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
`
8
8
`use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
`
9
9
`use rustc_hir::{LangItem, lang_items};
`
10
10
`use rustc_middle::middle::codegen_fn_attrs::{
`
11
``
`-
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
`
``
11
`+
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, TargetFeature,
`
``
12
`+
extend_with_struct_target_features,
`
12
13
`};
`
13
14
`use rustc_middle::mir::mono::Linkage;
`
14
15
`use rustc_middle::query::Providers;
`
`@@ -78,23 +79,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
`
78
79
`let mut link_ordinal_span = None;
`
79
80
`let mut no_sanitize_span = None;
`
80
81
``
``
82
`+
let fn_sig_outer = || {
`
``
83
`+
use DefKind::*;
`
``
84
+
``
85
`+
let def_kind = tcx.def_kind(did);
`
``
86
`+
if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { None }
`
``
87
`+
};
`
``
88
+
81
89
`for attr in attrs.iter() {
`
82
90
`` // In some cases, attribute are only valid on functions, but it's the check_attr
``
83
91
`// pass that check that they aren't used anywhere else, rather this module.
`
84
92
`// In these cases, we bail from performing further checks that are only meaningful for
`
85
93
`` // functions (such as calling fn_sig
, which ICEs if given a non-function). We also
``
86
94
`` // report a delayed bug, just in case check_attr
isn't doing its job.
``
87
95
`let fn_sig = || {
`
88
``
`-
use DefKind::*;
`
89
``
-
90
``
`-
let def_kind = tcx.def_kind(did);
`
91
``
`-
if let Fn | AssocFn | Variant | Ctor(..) = def_kind {
`
92
``
`-
Some(tcx.fn_sig(did))
`
93
``
`-
} else {
`
``
96
`+
let sig = fn_sig_outer();
`
``
97
`+
if sig.is_none() {
`
94
98
` tcx.dcx()
`
95
99
`.span_delayed_bug(attr.span, "this attribute can only be applied to functions");
`
96
``
`-
None
`
97
100
`}
`
``
101
`+
sig
`
98
102
`};
`
99
103
``
100
104
`let Some(Ident { name, .. }) = attr.ident() else {
`
`@@ -246,7 +250,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
`
246
250
` && let Some(fn_sig) = fn_sig()
`
247
251
` && fn_sig.skip_binder().safety() == hir::Safety::Safe
`
248
252
`{
`
249
``
`-
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
`
``
253
`+
if attr.meta_item_list().is_some_and(|list| {
`
``
254
`+
list.len() == 1 && list[0].ident().is_some_and(|x| x.name == sym::from_args)
`
``
255
`+
}) {
`
``
256
`+
// #[target_feature(from_args)] can be applied to safe functions and safe
`
``
257
`+
// trait methods.
`
``
258
`+
} else if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
`
250
259
`` // The #[target_feature]
attribute is allowed on
``
251
260
`// WebAssembly targets on all functions, including safe
`
252
261
`` // ones. Other targets require that #[target_feature]
is
``
`@@ -284,7 +293,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
`
284
293
` tcx,
`
285
294
` attr,
`
286
295
` supported_target_features,
`
287
``
`-
&mut codegen_fn_attrs.target_features,
`
``
296
`+
&mut codegen_fn_attrs.def_target_features,
`
``
297
`+
Some(&mut codegen_fn_attrs.target_features_from_args),
`
288
298
`);
`
289
299
`}
`
290
300
` sym::linkage => {
`
`@@ -590,16 +600,39 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
`
590
600
`let owner_id = tcx.parent(did.to_def_id());
`
591
601
`if tcx.def_kind(owner_id).has_codegen_attrs() {
`
592
602
` codegen_fn_attrs
`
593
``
`-
.target_features
`
594
``
`-
.extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
`
``
603
`+
.def_target_features
`
``
604
`+
.extend(tcx.codegen_fn_attrs(owner_id).def_target_features.iter().copied());
`
595
605
`}
`
596
606
`}
`
597
607
``
598
``
`-
// If a function uses #[target_feature] it can't be inlined into general
`
``
608
`+
if let Some(sig) = fn_sig_outer()
`
``
609
`+
&& codegen_fn_attrs.target_features_from_args
`
``
610
`+
{
`
``
611
`+
let mut additional_tf = vec![];
`
``
612
`+
for ty in sig.skip_binder().inputs().skip_binder() {
`
``
613
`+
extend_with_struct_target_features(
`
``
614
`+
tcx,
`
``
615
`+
tcx.param_env(did.to_def_id()).and(*ty),
`
``
616
`+
&mut additional_tf,
`
``
617
`+
)
`
``
618
`+
}
`
``
619
`+
if !additional_tf.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always {
`
``
620
`+
tcx.dcx().span_err(
`
``
621
`+
tcx.hir().span(tcx.local_def_id_to_hir_id(did)),
`
``
622
`+
"cannot use a struct with target features in a #[inline(always)] function",
`
``
623
`+
);
`
``
624
`+
}
`
``
625
`+
codegen_fn_attrs
`
``
626
`+
.def_target_features
`
``
627
`+
.extend(additional_tf.iter().map(|tf| TargetFeature { implied: true, ..*tf }));
`
``
628
`+
}
`
``
629
+
``
630
`+
// If a function uses non-default target_features it can't be inlined into general
`
599
631
`// purpose functions as they wouldn't have the right target features
`
600
632
`// enabled. For that reason we also forbid #[inline(always)] as it can't be
`
601
633
`// respected.
`
602
``
`-
if !codegen_fn_attrs.target_features.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always
`
``
634
`+
if !codegen_fn_attrs.def_target_features.is_empty()
`
``
635
`+
&& codegen_fn_attrs.inline == InlineAttr::Always
`
603
636
`{
`
604
637
`if let Some(span) = inline_span {
`
605
638
` tcx.dcx().span_err(
`
`@@ -738,6 +771,20 @@ fn check_link_name_xor_ordinal(
`
738
771
`}
`
739
772
`}
`
740
773
``
``
774
`+
fn struct_target_features(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[TargetFeature] {
`
``
775
`+
let mut features = vec![];
`
``
776
`+
let supported_features = tcx.supported_target_features(LOCAL_CRATE);
`
``
777
`+
for attr in tcx.get_attrs(def_id, sym::target_feature) {
`
``
778
`+
from_target_feature(tcx, attr, supported_features, &mut features, None);
`
``
779
`+
}
`
``
780
`+
tcx.arena.alloc_slice(&features)
`
``
781
`+
}
`
``
782
+
741
783
`pub(crate) fn provide(providers: &mut Providers) {
`
742
``
`-
*providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
`
``
784
`+
*providers = Providers {
`
``
785
`+
codegen_fn_attrs,
`
``
786
`+
should_inherit_track_caller,
`
``
787
`+
struct_target_features,
`
``
788
`+
..*providers
`
``
789
`+
};
`
743
790
`}
`