1
Fork 0

Rollup merge of #139001 - folkertdev:naked-function-rustic-abi, r=traviscross,compiler-errors

add `naked_functions_rustic_abi` feature gate

tracking issue: https://github.com/rust-lang/rust/issues/138997

Because the details of the rust abi are unstable, and a naked function must match its stated ABI, this feature gate keeps naked functions with a rustic abi ("Rust", "rust-cold", "rust-call" and "rust-intrinsic") unstable.

r? ````@traviscross````
This commit is contained in:
Jacob Pratt 2025-04-13 17:37:52 -04:00 committed by GitHub
commit 7f691d28f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 142 additions and 107 deletions

View file

@ -565,6 +565,8 @@ declare_features! (
(incomplete, mut_ref, "1.79.0", Some(123076)),
/// Allows using `#[naked]` on functions.
(unstable, naked_functions, "1.9.0", Some(90957)),
/// Allows using `#[naked]` on `extern "Rust"` functions.
(unstable, naked_functions_rustic_abi, "CURRENT_RUSTC_VERSION", Some(138997)),
/// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions.
(unstable, naked_functions_target_feature, "1.86.0", Some(138568)),
/// Allows specifying the as-needed link modifier

View file

@ -606,6 +606,11 @@ fn register_builtins(store: &mut LintStore) {
"converted into hard error, see issue #127323 \
<https://github.com/rust-lang/rust/issues/127323> for more information",
);
store.register_removed(
"undefined_naked_function_abi",
"converted into hard error, see PR #139001 \
<https://github.com/rust-lang/rust/issues/139001> for more information",
);
}
fn register_internals(store: &mut LintStore) {

View file

@ -110,7 +110,6 @@ declare_lint_pass! {
UNCONDITIONAL_PANIC,
UNCONDITIONAL_RECURSION,
UNCOVERED_PARAM_IN_PROJECTION,
UNDEFINED_NAKED_FUNCTION_ABI,
UNEXPECTED_CFGS,
UNFULFILLED_LINT_EXPECTATIONS,
UNINHABITED_STATIC,
@ -2830,39 +2829,6 @@ declare_lint! {
"detects deprecation attributes with no effect",
}
declare_lint! {
/// The `undefined_naked_function_abi` lint detects naked function definitions that
/// either do not specify an ABI or specify the Rust ABI.
///
/// ### Example
///
/// ```rust
/// #![feature(asm_experimental_arch, naked_functions)]
///
/// use std::arch::naked_asm;
///
/// #[naked]
/// pub fn default_abi() -> u32 {
/// unsafe { naked_asm!(""); }
/// }
///
/// #[naked]
/// pub extern "Rust" fn rust_abi() -> u32 {
/// unsafe { naked_asm!(""); }
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// The Rust ABI is currently undefined. Therefore, naked functions should
/// specify a non-Rust ABI.
pub UNDEFINED_NAKED_FUNCTION_ABI,
Warn,
"undefined naked function ABI"
}
declare_lint! {
/// The `ineffective_unstable_trait_impl` lint detects `#[unstable]` attributes which are not used.
///

View file

@ -742,9 +742,6 @@ passes_trait_impl_const_stable =
passes_transparent_incompatible =
transparent {$target} cannot have other repr hints
passes_undefined_naked_function_abi =
Rust ABI is unsupported in naked functions
passes_unknown_external_lang_item =
unknown external lang item: `{$lang_item}`

View file

@ -624,6 +624,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
match target {
Target::Fn
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {
let fn_sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
let abi = fn_sig.header.abi;
if abi.is_rustic_abi() && !self.tcx.features().naked_functions_rustic_abi() {
feature_err(
&self.tcx.sess,
sym::naked_functions_rustic_abi,
fn_sig.span,
format!(
"`#[naked]` is currently unstable on `extern \"{}\"` functions",
abi.as_str()
),
)
.emit();
}
for other_attr in attrs {
// this covers "sugared doc comments" of the form `/// ...`
// it does not cover `#[doc = "..."]`, which is handled below

View file

@ -1197,10 +1197,6 @@ pub(crate) struct UnlabeledCfInWhileCondition<'a> {
pub cf_type: &'a str,
}
#[derive(LintDiagnostic)]
#[diag(passes_undefined_naked_function_abi)]
pub(crate) struct UndefinedNakedFunctionAbi;
#[derive(Diagnostic)]
#[diag(passes_no_patterns)]
pub(crate) struct NoPatterns {

View file

@ -1,6 +1,5 @@
//! Checks validity of naked functions.
use rustc_abi::ExternAbi;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
@ -10,12 +9,11 @@ use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
use rustc_span::{Span, sym};
use crate::errors::{
NakedAsmOutsideNakedFn, NakedFunctionsAsmBlock, NakedFunctionsMustNakedAsm, NoPatterns,
ParamsNotAllowed, UndefinedNakedFunctionAbi,
ParamsNotAllowed,
};
pub(crate) fn provide(providers: &mut Providers) {
@ -29,26 +27,21 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
continue;
}
let (fn_header, body_id) = match tcx.hir_node_by_def_id(def_id) {
let body = match tcx.hir_node_by_def_id(def_id) {
hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn { sig, body: body_id, .. },
..
kind: hir::ItemKind::Fn { body: body_id, .. }, ..
})
| hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)),
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)),
..
})
| hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Fn(sig, body_id),
..
}) => (sig.header, *body_id),
kind: hir::ImplItemKind::Fn(_, body_id), ..
}) => tcx.hir_body(*body_id),
_ => continue,
};
let body = tcx.hir_body(body_id);
if tcx.has_attr(def_id, sym::naked) {
check_abi(tcx, def_id, fn_header.abi);
check_no_patterns(tcx, body.params);
check_no_parameters_use(tcx, body);
check_asm(tcx, def_id, body);
@ -60,20 +53,6 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
}
}
/// Checks that function uses non-Rust ABI.
fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: ExternAbi) {
if abi == ExternAbi::Rust {
let hir_id = tcx.local_def_id_to_hir_id(def_id);
let span = tcx.def_span(def_id);
tcx.emit_node_span_lint(
UNDEFINED_NAKED_FUNCTION_ABI,
hir_id,
span,
UndefinedNakedFunctionAbi,
);
}
}
/// Checks that parameters don't use patterns. Mirrors the checks for function declarations.
fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
for param in params {

View file

@ -1400,6 +1400,7 @@ symbols! {
naked,
naked_asm,
naked_functions,
naked_functions_rustic_abi,
naked_functions_target_feature,
name,
names,