Skip to content

Commit 3cb521a

Browse files
committed
Auto merge of #126761 - GuillaumeGomez:unsafe_extern_blocks, r=spastorino
rustdoc: Add support for `missing_unsafe_on_extern` feature Follow-up of #124482. Not sure if the `safe` keyword is supposed to be displayed or not though? For now I didn't add it in the generated doc, only `unsafe` as usual. cc `@spastorino` r? `@fmease`
2 parents a0f01c3 + 630c3ad commit 3cb521a

File tree

7 files changed

+70
-28
lines changed

7 files changed

+70
-28
lines changed

src/librustdoc/clean/mod.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -3077,23 +3077,20 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
30773077
let def_id = item.owner_id.to_def_id();
30783078
cx.with_param_env(def_id, |cx| {
30793079
let kind = match item.kind {
3080-
// FIXME(missing_unsafe_on_extern) handle safety of foreign fns.
3081-
// Safety was added as part of the implementation of unsafe extern blocks PR #124482
3082-
hir::ForeignItemKind::Fn(decl, names, generics, _) => {
3080+
hir::ForeignItemKind::Fn(decl, names, generics, safety) => {
30833081
let (generics, decl) = enter_impl_trait(cx, |cx| {
30843082
// NOTE: generics must be cleaned before args
30853083
let generics = clean_generics(generics, cx);
30863084
let args = clean_args_from_types_and_names(cx, decl.inputs, names);
30873085
let decl = clean_fn_decl_with_args(cx, decl, None, args);
30883086
(generics, decl)
30893087
});
3090-
ForeignFunctionItem(Box::new(Function { decl, generics }))
3091-
}
3092-
// FIXME(missing_unsafe_on_extern) handle safety of foreign statics.
3093-
// Safety was added as part of the implementation of unsafe extern blocks PR #124482
3094-
hir::ForeignItemKind::Static(ty, mutability, _) => {
3095-
ForeignStaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: None })
3088+
ForeignFunctionItem(Box::new(Function { decl, generics }), safety)
30963089
}
3090+
hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem(
3091+
Static { type_: clean_ty(ty, cx), mutability, expr: None },
3092+
safety,
3093+
),
30973094
hir::ForeignItemKind::Type => ForeignTypeItem,
30983095
};
30993096

src/librustdoc/clean/types.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -639,14 +639,14 @@ impl Item {
639639
hir::FnHeader { safety: sig.safety(), abi: sig.abi(), constness, asyncness }
640640
}
641641
let header = match *self.kind {
642-
ItemKind::ForeignFunctionItem(_) => {
642+
ItemKind::ForeignFunctionItem(_, safety) => {
643643
let def_id = self.def_id().unwrap();
644644
let abi = tcx.fn_sig(def_id).skip_binder().abi();
645645
hir::FnHeader {
646646
safety: if abi == Abi::RustIntrinsic {
647647
intrinsic_operation_unsafety(tcx, def_id.expect_local())
648648
} else {
649-
hir::Safety::Unsafe
649+
safety
650650
},
651651
abi,
652652
constness: if tcx.is_const_fn(def_id)
@@ -842,9 +842,9 @@ pub(crate) enum ItemKind {
842842
StructFieldItem(Type),
843843
VariantItem(Variant),
844844
/// `fn`s from an extern block
845-
ForeignFunctionItem(Box<Function>),
845+
ForeignFunctionItem(Box<Function>, hir::Safety),
846846
/// `static`s from an extern block
847-
ForeignStaticItem(Static),
847+
ForeignStaticItem(Static, hir::Safety),
848848
/// `type`s from an extern block
849849
ForeignTypeItem,
850850
MacroItem(Macro),
@@ -893,8 +893,8 @@ impl ItemKind {
893893
| TyMethodItem(_)
894894
| MethodItem(_, _)
895895
| StructFieldItem(_)
896-
| ForeignFunctionItem(_)
897-
| ForeignStaticItem(_)
896+
| ForeignFunctionItem(_, _)
897+
| ForeignStaticItem(_, _)
898898
| ForeignTypeItem
899899
| MacroItem(_)
900900
| ProcMacroItem(_)
@@ -924,8 +924,8 @@ impl ItemKind {
924924
| StaticItem(_)
925925
| ConstantItem(_, _, _)
926926
| TraitAliasItem(_)
927-
| ForeignFunctionItem(_)
928-
| ForeignStaticItem(_)
927+
| ForeignFunctionItem(_, _)
928+
| ForeignStaticItem(_, _)
929929
| ForeignTypeItem
930930
| MacroItem(_)
931931
| ProcMacroItem(_)

src/librustdoc/fold.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ pub(crate) trait DocFolder: Sized {
8484
| TyMethodItem(_)
8585
| MethodItem(_, _)
8686
| StructFieldItem(_)
87-
| ForeignFunctionItem(_)
88-
| ForeignStaticItem(_)
87+
| ForeignFunctionItem(..)
88+
| ForeignStaticItem(..)
8989
| ForeignTypeItem
9090
| MacroItem(_)
9191
| ProcMacroItem(_)

src/librustdoc/html/render/print_item.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
254254

255255
match &*item.kind {
256256
clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items),
257-
clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => {
257+
clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f, _) => {
258258
item_function(buf, cx, item, f)
259259
}
260260
clean::TraitItem(ref t) => item_trait(buf, cx, item, t),
@@ -265,7 +265,8 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
265265
clean::MacroItem(ref m) => item_macro(buf, cx, item, m),
266266
clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m),
267267
clean::PrimitiveItem(_) => item_primitive(buf, cx, item),
268-
clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => item_static(buf, cx, item, i),
268+
clean::StaticItem(ref i) => item_static(buf, cx, item, i, None),
269+
clean::ForeignStaticItem(ref i, safety) => item_static(buf, cx, item, i, Some(*safety)),
269270
clean::ConstantItem(generics, ty, c) => item_constant(buf, cx, item, generics, ty, c),
270271
clean::ForeignTypeItem => item_foreign_type(buf, cx, item),
271272
clean::KeywordItem => item_keyword(buf, cx, item),
@@ -491,11 +492,14 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
491492
}
492493

493494
let unsafety_flag = match *myitem.kind {
494-
clean::FunctionItem(_) | clean::ForeignFunctionItem(_)
495+
clean::FunctionItem(_) | clean::ForeignFunctionItem(..)
495496
if myitem.fn_header(tcx).unwrap().safety == hir::Safety::Unsafe =>
496497
{
497498
"<sup title=\"unsafe function\">⚠</sup>"
498499
}
500+
clean::ForeignStaticItem(_, hir::Safety::Unsafe) => {
501+
"<sup title=\"unsafe static\">⚠</sup>"
502+
}
499503
_ => "",
500504
};
501505

@@ -1957,13 +1961,22 @@ fn item_fields(
19571961
}
19581962
}
19591963

1960-
fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
1964+
fn item_static(
1965+
w: &mut impl fmt::Write,
1966+
cx: &mut Context<'_>,
1967+
it: &clean::Item,
1968+
s: &clean::Static,
1969+
safety: Option<hir::Safety>,
1970+
) {
19611971
wrap_item(w, |buffer| {
19621972
render_attributes_in_code(buffer, it, cx);
19631973
write!(
19641974
buffer,
1965-
"{vis}static {mutability}{name}: {typ}",
1975+
"{vis}{safe}static {mutability}{name}: {typ}",
19661976
vis = visibility_print_with_space(it, cx),
1977+
safe = safety
1978+
.map(|safe| if safe == hir::Safety::Unsafe { "unsafe " } else { "" })
1979+
.unwrap_or(""),
19671980
mutability = s.mutability.print_with_space(),
19681981
name = it.name.unwrap(),
19691982
typ = s.type_.print(cx)

src/librustdoc/json/conversions.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -310,14 +310,16 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
310310
EnumItem(e) => ItemEnum::Enum(e.into_tcx(tcx)),
311311
VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)),
312312
FunctionItem(f) => ItemEnum::Function(from_function(f, true, header.unwrap(), tcx)),
313-
ForeignFunctionItem(f) => ItemEnum::Function(from_function(f, false, header.unwrap(), tcx)),
313+
ForeignFunctionItem(f, _) => {
314+
ItemEnum::Function(from_function(f, false, header.unwrap(), tcx))
315+
}
314316
TraitItem(t) => ItemEnum::Trait((*t).into_tcx(tcx)),
315317
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
316318
MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), tcx)),
317319
TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), tcx)),
318320
ImplItem(i) => ItemEnum::Impl((*i).into_tcx(tcx)),
319321
StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
320-
ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
322+
ForeignStaticItem(s, _) => ItemEnum::Static(s.into_tcx(tcx)),
321323
ForeignTypeItem => ItemEnum::ForeignType,
322324
TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)),
323325
OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)),

src/librustdoc/visit.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ pub(crate) trait DocVisitor: Sized {
3333
| TyMethodItem(_)
3434
| MethodItem(_, _)
3535
| StructFieldItem(_)
36-
| ForeignFunctionItem(_)
37-
| ForeignStaticItem(_)
36+
| ForeignFunctionItem(..)
37+
| ForeignStaticItem(..)
3838
| ForeignTypeItem
3939
| MacroItem(_)
4040
| ProcMacroItem(_)

tests/rustdoc/unsafe-extern-blocks.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Test to ensure the feature is working as expected.
2+
3+
#![feature(unsafe_extern_blocks)]
4+
#![crate_name = "foo"]
5+
6+
// @has 'foo/index.html'
7+
8+
// First we check that both the static and the function have a "sup" element
9+
// to tell they're unsafe.
10+
11+
// @count - '//ul[@class="item-table"]//sup[@title="unsafe static"]' 1
12+
// @has - '//ul[@class="item-table"]//sup[@title="unsafe static"]' '⚠'
13+
// @count - '//ul[@class="item-table"]//sup[@title="unsafe function"]' 1
14+
// @has - '//ul[@class="item-table"]//sup[@title="unsafe function"]' '⚠'
15+
16+
unsafe extern {
17+
// @has 'foo/static.FOO.html'
18+
// @has - '//pre[@class="rust item-decl"]' 'pub static FOO: i32'
19+
pub safe static FOO: i32;
20+
// @has 'foo/static.BAR.html'
21+
// @has - '//pre[@class="rust item-decl"]' 'pub unsafe static BAR: i32'
22+
pub static BAR: i32;
23+
24+
// @has 'foo/fn.foo.html'
25+
// @has - '//pre[@class="rust item-decl"]' 'pub extern "C" fn foo()'
26+
pub safe fn foo();
27+
// @has 'foo/fn.bar.html'
28+
// @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn bar()'
29+
pub fn bar();
30+
}

0 commit comments

Comments
 (0)