Skip to content

Commit 119ebd4

Browse files
committed
Lint #[inline(always)] closure in #[target_feature] functions
1 parent 826b673 commit 119ebd4

File tree

6 files changed

+123
-10
lines changed

6 files changed

+123
-10
lines changed

compiler/rustc_codegen_ssa/messages.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ codegen_ssa_incorrect_cgu_reuse_type =
8282
*[other] {""}
8383
}`{$expected_reuse}`
8484
85+
codegen_ssa_inline_always_closure_in_target_feature_function =
86+
cannot use `#[inline(always)]` with `#[target_feature]`
87+
.note = `#[target_feature]` will not be applied to this closure and may result in unpredictable code generation
88+
.help = consider using `#[inline]` instead
89+
8590
codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient.
8691
8792
codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -584,15 +584,25 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
584584
// its parent function, which effectively inherits the features anyway. Boxing this closure
585585
// would result in this closure being compiled without the inherited target features, but this
586586
// is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
587-
if tcx.features().target_feature_11()
588-
&& tcx.is_closure_like(did.to_def_id())
589-
&& codegen_fn_attrs.inline != InlineAttr::Always
590-
{
587+
if tcx.features().target_feature_11() && tcx.is_closure_like(did.to_def_id()) {
591588
let owner_id = tcx.parent(did.to_def_id());
592-
if tcx.def_kind(owner_id).has_codegen_attrs() {
593-
codegen_fn_attrs
594-
.target_features
595-
.extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
589+
if tcx.def_kind(owner_id).has_codegen_attrs()
590+
&& !tcx.codegen_fn_attrs(owner_id).target_features.is_empty()
591+
{
592+
if codegen_fn_attrs.inline == InlineAttr::Always {
593+
if let Some(inline_span) = inline_span {
594+
tcx.emit_node_span_lint(
595+
lint::builtin::INLINE_ALWAYS_CLOSURE_IN_TARGET_FEATURE_FUNCTION,
596+
rustc_hir::CRATE_HIR_ID,
597+
inline_span,
598+
errors::InlineAlwaysClosureInTargetFeatureFunction,
599+
);
600+
}
601+
} else {
602+
codegen_fn_attrs
603+
.target_features
604+
.extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
605+
}
596606
}
597607
}
598608

compiler/rustc_codegen_ssa/src/errors.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_errors::codes::*;
1010
use rustc_errors::{
1111
Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
1212
};
13-
use rustc_macros::{Diagnostic, Subdiagnostic};
13+
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
1414
use rustc_middle::ty::Ty;
1515
use rustc_middle::ty::layout::LayoutError;
1616
use rustc_span::{Span, Symbol};
@@ -1093,6 +1093,12 @@ pub struct TargetFeatureDisableOrEnable<'a> {
10931093
pub missing_features: Option<MissingFeatures>,
10941094
}
10951095

1096+
#[derive(LintDiagnostic)]
1097+
#[diag(codegen_ssa_inline_always_closure_in_target_feature_function)]
1098+
#[note]
1099+
#[help]
1100+
pub struct InlineAlwaysClosureInTargetFeatureFunction;
1101+
10961102
#[derive(Subdiagnostic)]
10971103
#[help(codegen_ssa_missing_features)]
10981104
pub struct MissingFeatures;

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ declare_lint_pass! {
5252
ILL_FORMED_ATTRIBUTE_INPUT,
5353
INCOMPLETE_INCLUDE,
5454
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
55+
INLINE_ALWAYS_CLOSURE_IN_TARGET_FEATURE_FUNCTION,
5556
INLINE_NO_SANITIZE,
5657
INVALID_DOC_ATTRIBUTES,
5758
INVALID_MACRO_EXPORT_ARGUMENTS,
@@ -5177,3 +5178,38 @@ declare_lint! {
51775178
reference: "issue #116558 <https://github.com/rust-lang/rust/issues/116558>",
51785179
};
51795180
}
5181+
5182+
declare_lint! {
5183+
/// The `inline_always_closure_in_target_feature_function` lint detects using
5184+
/// the `#[inline(always)]` attribute on closures within functions marked with
5185+
/// the `#[target_feature(enable = "...")]` attribute.
5186+
///
5187+
/// ### Example
5188+
///
5189+
/// ```rust,edition2021,compile_fail
5190+
/// #![deny(inline_always_closure_in_target_feature_function)]
5191+
///
5192+
/// #[target_feature(enable = "avx")]
5193+
/// fn example() {
5194+
/// let closure = #[inline(always)] || {};
5195+
/// }
5196+
///
5197+
/// ```
5198+
///
5199+
/// {{produces}}
5200+
///
5201+
/// ### Explanation
5202+
///
5203+
/// Rust previously did not apply a function's target features to closures
5204+
/// within it.
5205+
/// The `#[inline(always)]` attribute is incompatible with target features
5206+
/// due to the possibility of target feature mismatches.
5207+
/// The `#[inline]` attribute may be used instead.
5208+
pub INLINE_ALWAYS_CLOSURE_IN_TARGET_FEATURE_FUNCTION,
5209+
Warn,
5210+
"detect closures marked #[inline(always)] inside functions marked #[target_feature]",
5211+
@future_incompatible = FutureIncompatibleInfo {
5212+
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
5213+
reference: "issue #108655 <https://github.com/rust-lang/rust/issues/108655>",
5214+
};
5215+
}

tests/ui/rfcs/rfc-2396-target_feature-11/issue-108655-inline-always-closure.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,43 @@
55

66
#![feature(target_feature_11)]
77

8+
pub fn okay() {
9+
({
10+
#[inline(always)]
11+
move || {}
12+
})();
13+
}
14+
815
#[target_feature(enable = "avx")]
9-
pub unsafe fn test() {
16+
pub unsafe fn also_okay() {
17+
({
18+
#[inline]
19+
move || {}
20+
})();
21+
}
22+
23+
#[target_feature(enable = "avx")]
24+
pub unsafe fn warn() {
1025
({
1126
#[inline(always)]
27+
//~^ WARNING: cannot use `#[inline(always)]` with `#[target_feature]` [inline_always_closure_in_target_feature_function]
28+
//~^^ WARNING: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
1229
move || {}
1330
})();
1431
}
1532

33+
#[target_feature(enable = "avx")]
34+
pub unsafe fn also_warn() {
35+
({
36+
move || {
37+
({
38+
#[inline(always)]
39+
//~^ WARNING: cannot use `#[inline(always)]` with `#[target_feature]` [inline_always_closure_in_target_feature_function]
40+
//~^^ WARNING: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
41+
move || {}
42+
})();
43+
}
44+
})();
45+
}
46+
1647
fn main() {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
warning: cannot use `#[inline(always)]` with `#[target_feature]`
2+
--> $DIR/issue-108655-inline-always-closure.rs:26:9
3+
|
4+
LL | #[inline(always)]
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8+
= note: for more information, see issue #108655 <https://github.com/rust-lang/rust/issues/108655>
9+
= note: `#[target_feature]` will not be applied to this closure and may result in unpredictable code generation
10+
= help: consider using `#[inline]` instead
11+
= note: `#[warn(inline_always_closure_in_target_feature_function)]` on by default
12+
13+
warning: cannot use `#[inline(always)]` with `#[target_feature]`
14+
--> $DIR/issue-108655-inline-always-closure.rs:38:17
15+
|
16+
LL | #[inline(always)]
17+
| ^^^^^^^^^^^^^^^^^
18+
|
19+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
20+
= note: for more information, see issue #108655 <https://github.com/rust-lang/rust/issues/108655>
21+
= note: `#[target_feature]` will not be applied to this closure and may result in unpredictable code generation
22+
= help: consider using `#[inline]` instead
23+
24+
warning: 2 warnings emitted
25+

0 commit comments

Comments
 (0)