Skip to content

Commit 48a7fbc

Browse files
authored
Unrolled build for #158313
Rollup merge of #158313 - obeis:move-check_target_feature, r=JonathanBrouwer Move `check_target_feature` into the attribute parser Updates #153101 Use `TargetFeatureParser` to reject `#[target_feature]` on functions marked as lang items (via `#[lang = "..."]` or `#[panic_handler]`), replacing `check_target_feature` in `rustc_passes`. r? @JonathanBrouwer
2 parents cb41b6d + 74830a7 commit 48a7fbc

10 files changed

Lines changed: 77 additions & 83 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::attributes::AttributeSafety;
1010
use crate::session_diagnostics::{
1111
EmptyExportName, NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass,
1212
NullOnObjcSelector, ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral,
13-
SanitizeInvalidStatic,
13+
SanitizeInvalidStatic, TargetFeatureOnLangItem,
1414
};
1515
use crate::target_checking::Policy::AllowSilent;
1616

@@ -524,15 +524,6 @@ impl CombineAttributeParser for TargetFeatureParser {
524524
was_forced: false,
525525
};
526526
const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]);
527-
const STABILITY: AttributeStability = AttributeStability::Stable;
528-
529-
fn extend(
530-
cx: &mut AcceptContext<'_, '_>,
531-
args: &ArgParser,
532-
) -> impl IntoIterator<Item = Self::Item> {
533-
parse_tf_attribute(cx, args)
534-
}
535-
536527
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
537528
Allow(Target::Fn),
538529
Allow(Target::Method(MethodKind::Inherent)),
@@ -544,6 +535,29 @@ impl CombineAttributeParser for TargetFeatureParser {
544535
Warn(Target::MacroDef),
545536
Warn(Target::MacroCall),
546537
]);
538+
const STABILITY: AttributeStability = AttributeStability::Stable;
539+
540+
fn extend(
541+
cx: &mut AcceptContext<'_, '_>,
542+
args: &ArgParser,
543+
) -> impl IntoIterator<Item = Self::Item> {
544+
parse_tf_attribute(cx, args)
545+
}
546+
547+
fn finalize_check(cx: &FinalizeContext<'_, '_>, attr_span: Span) {
548+
// `#[target_feature]` is incompatible with lang item functions,
549+
// except on WASM where calling target-feature functions is safe (see #84988).
550+
if !cx.sess().target.is_like_wasm && !cx.sess().opts.actually_rustdoc {
551+
// `#[panic_handler]` is checked first so it takes priority in the diagnostic.
552+
let lang_kind = cx
553+
.all_attrs
554+
.iter()
555+
.find_map(|a| [sym::panic_handler, sym::lang].into_iter().find(|&s| a.word_is(s)));
556+
if let Some(kind) = lang_kind {
557+
cx.emit_err(TargetFeatureOnLangItem { attr_span, kind, item_span: cx.target_span });
558+
}
559+
}
560+
}
547561
}
548562

549563
pub(crate) struct ForceTargetFeatureParser;

compiler/rustc_attr_parsing/src/attributes/link_attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ impl NoArgsAttributeParser for FfiPureParser {
576576
const STABILITY: AttributeStability = unstable!(ffi_pure);
577577
const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;
578578

579-
fn finalize_check(attr_span: Span, cx: &FinalizeContext<'_, '_>) {
579+
fn finalize_check(cx: &FinalizeContext<'_, '_>, attr_span: Span) {
580580
// `#[ffi_const]` functions cannot be `#[ffi_pure]`.
581581
if cx.all_attrs.iter().any(|a| a.word_is(sym::ffi_const)) {
582582
cx.emit_err(BothFfiConstAndPure { attr_span });

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ pub(crate) trait SingleAttributeParser: 'static {
154154
/// reject incompatible combinations. `attr_span` is the span of this attribute.
155155
///
156156
/// Defaults to a no-op.
157-
fn finalize_check(_attr_span: Span, _cx: &FinalizeContext<'_, '_>) {}
157+
fn finalize_check(_cx: &FinalizeContext<'_, '_>, _attr_span: Span) {}
158158
}
159159

160160
/// Use in combination with [`SingleAttributeParser`].
@@ -187,7 +187,7 @@ impl<T: SingleAttributeParser> AttributeParser for Single<T> {
187187

188188
fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
189189
let (kind, span) = self.1?;
190-
T::finalize_check(span, cx);
190+
T::finalize_check(cx, span);
191191
Some(kind)
192192
}
193193
}
@@ -275,7 +275,7 @@ pub(crate) trait NoArgsAttributeParser: 'static {
275275
/// `attr_span` is the span of this attribute.
276276
///
277277
/// Defaults to a no-op.
278-
fn finalize_check(_attr_span: Span, _cx: &FinalizeContext<'_, '_>) {}
278+
fn finalize_check(_cx: &FinalizeContext<'_, '_>, _attr_span: Span) {}
279279
}
280280

281281
pub(crate) struct WithoutArgs<T: NoArgsAttributeParser>(PhantomData<T>);
@@ -299,8 +299,8 @@ impl<T: NoArgsAttributeParser> SingleAttributeParser for WithoutArgs<T> {
299299
Some(T::CREATE(cx.attr_span))
300300
}
301301

302-
fn finalize_check(attr_span: Span, cx: &FinalizeContext<'_, '_>) {
303-
T::finalize_check(attr_span, cx)
302+
fn finalize_check(cx: &FinalizeContext<'_, '_>, attr_span: Span) {
303+
T::finalize_check(cx, attr_span)
304304
}
305305
}
306306

@@ -335,6 +335,14 @@ pub(crate) trait CombineAttributeParser: 'static {
335335
cx: &mut AcceptContext<'_, '_>,
336336
args: &ArgParser,
337337
) -> impl IntoIterator<Item = Self::Item>;
338+
339+
/// Optional cross-attribute validation, run once during finalization after all
340+
/// attributes on the item have been parsed. Has access to the sibling attributes via
341+
/// [`FinalizeContext::all_attrs`], so it can reject incompatible combinations.
342+
/// `attr_span` is the span of the first attribute that was encountered.
343+
///
344+
/// Defaults to a no-op.
345+
fn finalize_check(_cx: &FinalizeContext<'_, '_>, _attr_span: Span) {}
338346
}
339347

340348
/// Use in combination with [`CombineAttributeParser`].
@@ -367,8 +375,9 @@ impl<T: CombineAttributeParser> AttributeParser for Combine<T> {
367375
const ALLOWED_TARGETS: AllowedTargets<'_> = T::ALLOWED_TARGETS;
368376
const SAFETY: AttributeSafety = T::SAFETY;
369377

370-
fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
378+
fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
371379
if let Some(first_span) = self.first_span {
380+
T::finalize_check(cx, first_span);
372381
Some(T::CONVERT(self.items, first_span))
373382
} else {
374383
None

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,26 @@ pub(crate) struct DocAttributeNotAttribute {
8080
pub attribute: Symbol,
8181
}
8282

83+
#[derive(Diagnostic)]
84+
#[diag(
85+
"`#[target_feature]` cannot be applied to a {$kind ->
86+
[panic_handler] `#[panic_handler]`
87+
*[other] lang item
88+
} function"
89+
)]
90+
pub(crate) struct TargetFeatureOnLangItem {
91+
#[primary_span]
92+
pub attr_span: Span,
93+
pub kind: Symbol,
94+
#[label(
95+
"{$kind ->
96+
[panic_handler] `#[panic_handler]`
97+
*[other] lang item
98+
} function is not allowed to have `#[target_feature]`"
99+
)]
100+
pub item_span: Span,
101+
}
102+
83103
#[derive(Diagnostic)]
84104
#[diag("missing 'since'", code = E0542)]
85105
pub(crate) struct MissingSince {

compiler/rustc_passes/src/check_attr.rs

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
204204
AttributeKind::Deprecated { span: attr_span, .. } => {
205205
self.check_deprecated(hir_id, *attr_span, target)
206206
}
207-
AttributeKind::TargetFeature { attr_span, .. } => {
208-
self.check_target_feature(hir_id, *attr_span, target, attrs)
209-
}
210207
AttributeKind::RustcDumpObjectLifetimeDefaults => {
211208
self.check_dump_object_lifetime_defaults(hir_id);
212209
}
@@ -406,6 +403,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
406403
AttributeKind::ShouldPanic { .. } => (),
407404
AttributeKind::Splat(..) => (),
408405
AttributeKind::Stability { .. } => (),
406+
AttributeKind::TargetFeature { .. } => {}
409407
AttributeKind::TestRunner(..) => (),
410408
AttributeKind::ThreadLocal => (),
411409
AttributeKind::TypeLengthLimit { .. } => (),
@@ -799,37 +797,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
799797
}
800798
}
801799

802-
/// Checks if the `#[target_feature]` attribute on `item` is valid.
803-
fn check_target_feature(
804-
&self,
805-
hir_id: HirId,
806-
attr_span: Span,
807-
target: Target,
808-
attrs: &[Attribute],
809-
) {
810-
match target {
811-
Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
812-
| Target::Fn => {
813-
// `#[target_feature]` is not allowed in lang items.
814-
if let Some(lang_item) = find_attr!(attrs, Lang(lang ) => lang)
815-
// Calling functions with `#[target_feature]` is
816-
// not unsafe on WASM, see #84988
817-
&& !self.tcx.sess.target.is_like_wasm
818-
&& !self.tcx.sess.opts.actually_rustdoc
819-
{
820-
let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
821-
822-
self.dcx().emit_err(diagnostics::LangItemWithTargetFeature {
823-
attr_span,
824-
name: lang_item.name(),
825-
sig_span: sig.span,
826-
});
827-
}
828-
}
829-
_ => {}
830-
}
831-
}
832-
833800
fn check_doc_alias_value(&self, span: Span, hir_id: HirId, target: Target, alias: Symbol) {
834801
if let Some(location) = match target {
835802
Target::AssocTy => {

compiler/rustc_passes/src/diagnostics.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -362,26 +362,6 @@ pub(crate) struct LangItemWithTrackCaller {
362362
pub sig_span: Span,
363363
}
364364

365-
#[derive(Diagnostic)]
366-
#[diag(
367-
"{$name ->
368-
[panic_impl] `#[panic_handler]`
369-
*[other] `{$name}` lang item
370-
} function is not allowed to have `#[target_feature]`"
371-
)]
372-
pub(crate) struct LangItemWithTargetFeature {
373-
#[primary_span]
374-
pub attr_span: Span,
375-
pub name: Symbol,
376-
#[label(
377-
"{$name ->
378-
[panic_impl] `#[panic_handler]`
379-
*[other] `{$name}` lang item
380-
} function is not allowed to have `#[target_feature]`"
381-
)]
382-
pub sig_span: Span,
383-
}
384-
385365
#[derive(Diagnostic)]
386366
#[diag("duplicate diagnostic item in crate `{$crate_name}`: `{$name}`")]
387367
pub(crate) struct DuplicateDiagnosticItemInCrate {

tests/ui/lang-items/start_lang_item_with_target_feature.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub trait Sized: MetaSized {}
1818

1919
#[lang = "start"]
2020
#[target_feature(enable = "avx2")]
21-
//~^ ERROR `start` lang item function is not allowed to have `#[target_feature]`
21+
//~^ ERROR #[target_feature]` cannot be applied to a lang item function
2222
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
2323
0
2424
}
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
error: `start` lang item function is not allowed to have `#[target_feature]`
1+
error: `#[target_feature]` cannot be applied to a lang item function
22
--> $DIR/start_lang_item_with_target_feature.rs:20:1
33
|
4-
LL | #[target_feature(enable = "avx2")]
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | #[target_feature(enable = "avx2")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
LL |
7-
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
8-
| ------------------------------------------------------------------------------------------- `start` lang item function is not allowed to have `#[target_feature]`
7+
LL | / fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
8+
LL | | 0
9+
LL | | }
10+
| |_- lang item function is not allowed to have `#[target_feature]`
911

1012
error: aborting due to 1 previous error
1113

tests/ui/panic-handler/panic-handler-with-target-feature.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use core::panic::PanicInfo;
88

99
#[panic_handler]
1010
#[target_feature(enable = "avx2")]
11-
//~^ ERROR `#[panic_handler]` function is not allowed to have `#[target_feature]`
11+
//~^ ERROR `#[target_feature]` cannot be applied to a `#[panic_handler]` function
1212
fn panic(info: &PanicInfo) -> ! {
1313
unimplemented!();
1414
}
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
error: `#[panic_handler]` function is not allowed to have `#[target_feature]`
1+
error: `#[target_feature]` cannot be applied to a `#[panic_handler]` function
22
--> $DIR/panic-handler-with-target-feature.rs:10:1
33
|
4-
LL | #[target_feature(enable = "avx2")]
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | #[target_feature(enable = "avx2")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
LL |
7-
LL | fn panic(info: &PanicInfo) -> ! {
8-
| ------------------------------- `#[panic_handler]` function is not allowed to have `#[target_feature]`
7+
LL | / fn panic(info: &PanicInfo) -> ! {
8+
LL | | unimplemented!();
9+
LL | | }
10+
| |_- `#[panic_handler]` function is not allowed to have `#[target_feature]`
911

1012
error: aborting due to 1 previous error
1113

0 commit comments

Comments
 (0)