Skip to content

Commit

Permalink
Unrolled build for rust-lang#133715
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#133715 - aDotInTheVoid:rdj-static, r=GuillaumeGomez

rustdoc-json: Include safety of `static`s

`static`s in an `extern` block can have an associated safety annotation ["because there is nothing guaranteeing that the bit pattern at the static’s memory is valid for the type it is declared with"](https://doc.rust-lang.org/reference/items/external-blocks.html#statics). Rustdoc already knows this and displays in for HTML. This PR also includes it in JSON.

Inspired by obi1kenobi/cargo-semver-checks#975 which needs this, but it's probably useful in other places.

r? `@GuillaumeGomez.` Possibly easier to review commit-by-commit.
  • Loading branch information
rust-timer authored Dec 2, 2024
2 parents 32eea2f + f33dba0 commit 1a16e93
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 14 deletions.
29 changes: 16 additions & 13 deletions src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,8 +321,8 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)),
TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), renderer)),
ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)),
StaticItem(s) => ItemEnum::Static(s.into_json(renderer)),
ForeignStaticItem(s, _) => ItemEnum::Static(s.into_json(renderer)),
StaticItem(s) => ItemEnum::Static(convert_static(s, rustc_hir::Safety::Safe, renderer)),
ForeignStaticItem(s, safety) => ItemEnum::Static(convert_static(s, safety, renderer)),
ForeignTypeItem => ItemEnum::ExternType,
TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)),
// FIXME(generic_const_items): Add support for generic free consts
Expand Down Expand Up @@ -831,17 +831,20 @@ impl FromClean<Box<clean::TypeAlias>> for TypeAlias {
}
}

impl FromClean<clean::Static> for Static {
fn from_clean(stat: clean::Static, renderer: &JsonRenderer<'_>) -> Self {
let tcx = renderer.tcx;
Static {
type_: (*stat.type_).into_json(renderer),
is_mutable: stat.mutability == ast::Mutability::Mut,
expr: stat
.expr
.map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
.unwrap_or_default(),
}
fn convert_static(
stat: clean::Static,
safety: rustc_hir::Safety,
renderer: &JsonRenderer<'_>,
) -> Static {
let tcx = renderer.tcx;
Static {
type_: (*stat.type_).into_json(renderer),
is_mutable: stat.mutability == ast::Mutability::Mut,
is_unsafe: safety == rustc_hir::Safety::Unsafe,
expr: stat
.expr
.map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
.unwrap_or_default(),
}
}

Expand Down
18 changes: 17 additions & 1 deletion src/rustdoc-json-types/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
/// This integer is incremented with every breaking change to the API,
/// and is returned along with the JSON blob as [`Crate::format_version`].
/// Consuming code should assert that this value matches the format version(s) that it supports.
pub const FORMAT_VERSION: u32 = 36;
pub const FORMAT_VERSION: u32 = 37;

/// The root of the emitted JSON blob.
///
Expand Down Expand Up @@ -1238,6 +1238,22 @@ pub struct Static {
///
/// It's not guaranteed that it'll match the actual source code for the initial value.
pub expr: String,

/// Is the static `unsafe`?
///
/// This is only true if it's in an `extern` block, and not explicity marked
/// as `safe`.
///
/// ```rust
/// unsafe extern {
/// static A: i32; // unsafe
/// safe static B: i32; // safe
/// }
///
/// static C: i32 = 0; // safe
/// static mut D: i32 = 0; // safe
/// ```
pub is_unsafe: bool,
}

/// A primitive type declaration. Declarations of this kind can only come from the core library.
Expand Down
39 changes: 39 additions & 0 deletions tests/rustdoc-json/statics/extern.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// ignore-tidy-linelength
//@ edition: 2021

extern "C" {
//@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe' true
//@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false
pub static A: i32;
//@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe' true
//@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true
pub static mut B: i32;

// items in unadorned `extern` blocks cannot have safety qualifiers
}

unsafe extern "C" {
//@ is '$.index[*][?(@.name=="C")].inner.static.is_unsafe' true
//@ is '$.index[*][?(@.name=="C")].inner.static.is_mutable' false
pub static C: i32;
//@ is '$.index[*][?(@.name=="D")].inner.static.is_unsafe' true
//@ is '$.index[*][?(@.name=="D")].inner.static.is_mutable' true
pub static mut D: i32;

//@ is '$.index[*][?(@.name=="E")].inner.static.is_unsafe' false
//@ is '$.index[*][?(@.name=="E")].inner.static.is_mutable' false
pub safe static E: i32;
//@ is '$.index[*][?(@.name=="F")].inner.static.is_unsafe' false
//@ is '$.index[*][?(@.name=="F")].inner.static.is_mutable' true
pub safe static mut F: i32;

//@ is '$.index[*][?(@.name=="G")].inner.static.is_unsafe' true
//@ is '$.index[*][?(@.name=="G")].inner.static.is_mutable' false
pub unsafe static G: i32;
//@ is '$.index[*][?(@.name=="H")].inner.static.is_unsafe' true
//@ is '$.index[*][?(@.name=="H")].inner.static.is_mutable' true
pub unsafe static mut H: i32;
}

//@ ismany '$.index[*][?(@.inner.static)].inner.static.expr' '""' '""' '""' '""' '""' '""' '""' '""'
//@ ismany '$.index[*][?(@.inner.static)].inner.static.type.primitive' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"'
12 changes: 12 additions & 0 deletions tests/rustdoc-json/statics/statics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//@ is '$.index[*][?(@.name=="A")].inner.static.type.primitive' '"i32"'
//@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false
//@ is '$.index[*][?(@.name=="A")].inner.static.expr' '"5"'
//@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe' false
pub static A: i32 = 5;

//@ is '$.index[*][?(@.name=="B")].inner.static.type.primitive' '"u32"'
//@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true
// Expr value isn't gaurenteed, it'd be fine to change it.
//@ is '$.index[*][?(@.name=="B")].inner.static.expr' '"_"'
//@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe' false
pub static mut B: u32 = 2 + 3;

0 comments on commit 1a16e93

Please sign in to comment.