about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPredrag Gruevski <obi1kenobi82@gmail.com>2025-07-07 00:56:29 +0000
committerPredrag Gruevski <obi1kenobi82@gmail.com>2025-07-08 02:02:56 +0000
commit717041232ae0ae0ae445a2a302510aab3375ea47 (patch)
tree2ab5874b3da52231952b75637b0ffe69f36d1551
parenta84ab0ce6c4557a2f01a3a6c3fdb0f92098db78d (diff)
downloadrust-717041232ae0ae0ae445a2a302510aab3375ea47.tar.gz
rust-717041232ae0ae0ae445a2a302510aab3375ea47.zip
Don't mark `#[target_feature]` safe fns as unsafe in rustdoc JSON.
-rw-r--r--src/librustdoc/json/conversions.rs15
-rw-r--r--tests/rustdoc-json/attrs/target_feature.rs23
2 files changed, 37 insertions, 1 deletions
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index f51b35097f6..f76ff11590b 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -9,6 +9,7 @@ use rustc_ast::ast;
 use rustc_attr_data_structures::{self as attrs, DeprecatedSince};
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::DefId;
+use rustc_hir::{HeaderSafety, Safety};
 use rustc_metadata::rendered_const;
 use rustc_middle::{bug, ty};
 use rustc_span::{Pos, kw, sym};
@@ -383,10 +384,22 @@ impl FromClean<clean::Union> for Union {
 
 impl FromClean<rustc_hir::FnHeader> for FunctionHeader {
     fn from_clean(header: &rustc_hir::FnHeader, renderer: &JsonRenderer<'_>) -> Self {
+        let is_unsafe = match header.safety {
+            HeaderSafety::SafeTargetFeatures => {
+                // The type system's internal implementation details consider
+                // safe functions with the `#[target_feature]` attribute to be analogous
+                // to unsafe functions: `header.is_unsafe()` returns `true` for them.
+                // For rustdoc, this isn't the right decision, so we explicitly return `false`.
+                // Context: https://github.com/rust-lang/rust/issues/142655
+                false
+            }
+            HeaderSafety::Normal(Safety::Safe) => false,
+            HeaderSafety::Normal(Safety::Unsafe) => true,
+        };
         FunctionHeader {
             is_async: header.is_async(),
             is_const: header.is_const(),
-            is_unsafe: header.is_unsafe(),
+            is_unsafe,
             abi: header.abi.into_json(renderer),
         }
     }
diff --git a/tests/rustdoc-json/attrs/target_feature.rs b/tests/rustdoc-json/attrs/target_feature.rs
index ee2b3235f72..80262d8e332 100644
--- a/tests/rustdoc-json/attrs/target_feature.rs
+++ b/tests/rustdoc-json/attrs/target_feature.rs
@@ -1,17 +1,40 @@
 //@ only-x86_64
 
 //@ is "$.index[?(@.name=='test1')].attrs" '["#[target_feature(enable=\"avx\")]"]'
+//@ is "$.index[?(@.name=='test1')].inner.function.header.is_unsafe" false
 #[target_feature(enable = "avx")]
 pub fn test1() {}
 
 //@ is "$.index[?(@.name=='test2')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\")]"]'
+//@ is "$.index[?(@.name=='test1')].inner.function.header.is_unsafe" false
 #[target_feature(enable = "avx,avx2")]
 pub fn test2() {}
 
 //@ is "$.index[?(@.name=='test3')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\")]"]'
+//@ is "$.index[?(@.name=='test1')].inner.function.header.is_unsafe" false
 #[target_feature(enable = "avx", enable = "avx2")]
 pub fn test3() {}
 
 //@ is "$.index[?(@.name=='test4')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\", enable=\"avx512f\")]"]'
+//@ is "$.index[?(@.name=='test1')].inner.function.header.is_unsafe" false
 #[target_feature(enable = "avx", enable = "avx2,avx512f")]
 pub fn test4() {}
+
+//@ is "$.index[?(@.name=='test_unsafe_fn')].attrs" '["#[target_feature(enable=\"avx\")]"]'
+//@ is "$.index[?(@.name=='test_unsafe_fn')].inner.function.header.is_unsafe" true
+#[target_feature(enable = "avx")]
+pub unsafe fn test_unsafe_fn() {}
+
+pub struct Example;
+
+impl Example {
+    //@ is "$.index[?(@.name=='safe_assoc_fn')].attrs" '["#[target_feature(enable=\"avx\")]"]'
+    //@ is "$.index[?(@.name=='safe_assoc_fn')].inner.function.header.is_unsafe" false
+    #[target_feature(enable = "avx")]
+    pub fn safe_assoc_fn() {}
+
+    //@ is "$.index[?(@.name=='unsafe_assoc_fn')].attrs" '["#[target_feature(enable=\"avx\")]"]'
+    //@ is "$.index[?(@.name=='unsafe_assoc_fn')].inner.function.header.is_unsafe" true
+    #[target_feature(enable = "avx")]
+    pub unsafe fn unsafe_assoc_fn() {}
+}