diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index da41f974068ec..22565ea402803 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3077,9 +3077,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>( let def_id = item.owner_id.to_def_id(); cx.with_param_env(def_id, |cx| { let kind = match item.kind { - // FIXME(missing_unsafe_on_extern) handle safety of foreign fns. - // Safety was added as part of the implementation of unsafe extern blocks PR #124482 - hir::ForeignItemKind::Fn(decl, names, generics, _) => { + hir::ForeignItemKind::Fn(decl, names, generics, safety) => { let (generics, decl) = enter_impl_trait(cx, |cx| { // NOTE: generics must be cleaned before args let generics = clean_generics(generics, cx); @@ -3087,13 +3085,12 @@ fn clean_maybe_renamed_foreign_item<'tcx>( let decl = clean_fn_decl_with_args(cx, decl, None, args); (generics, decl) }); - ForeignFunctionItem(Box::new(Function { decl, generics })) - } - // FIXME(missing_unsafe_on_extern) handle safety of foreign statics. - // Safety was added as part of the implementation of unsafe extern blocks PR #124482 - hir::ForeignItemKind::Static(ty, mutability, _) => { - ForeignStaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: None }) + ForeignFunctionItem(Box::new(Function { decl, generics }), safety) } + hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem( + Static { type_: clean_ty(ty, cx), mutability, expr: None }, + safety, + ), hir::ForeignItemKind::Type => ForeignTypeItem, }; diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 69678b727c116..c4020f2a450bc 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -639,14 +639,14 @@ impl Item { hir::FnHeader { safety: sig.safety(), abi: sig.abi(), constness, asyncness } } let header = match *self.kind { - ItemKind::ForeignFunctionItem(_) => { + ItemKind::ForeignFunctionItem(_, safety) => { let def_id = self.def_id().unwrap(); let abi = tcx.fn_sig(def_id).skip_binder().abi(); hir::FnHeader { safety: if abi == Abi::RustIntrinsic { intrinsic_operation_unsafety(tcx, def_id.expect_local()) } else { - hir::Safety::Unsafe + safety }, abi, constness: if tcx.is_const_fn(def_id) @@ -842,9 +842,9 @@ pub(crate) enum ItemKind { StructFieldItem(Type), VariantItem(Variant), /// `fn`s from an extern block - ForeignFunctionItem(Box), + ForeignFunctionItem(Box, hir::Safety), /// `static`s from an extern block - ForeignStaticItem(Static), + ForeignStaticItem(Static, hir::Safety), /// `type`s from an extern block ForeignTypeItem, MacroItem(Macro), @@ -893,8 +893,8 @@ impl ItemKind { | TyMethodItem(_) | MethodItem(_, _) | StructFieldItem(_) - | ForeignFunctionItem(_) - | ForeignStaticItem(_) + | ForeignFunctionItem(_, _) + | ForeignStaticItem(_, _) | ForeignTypeItem | MacroItem(_) | ProcMacroItem(_) @@ -924,8 +924,8 @@ impl ItemKind { | StaticItem(_) | ConstantItem(_, _, _) | TraitAliasItem(_) - | ForeignFunctionItem(_) - | ForeignStaticItem(_) + | ForeignFunctionItem(_, _) + | ForeignStaticItem(_, _) | ForeignTypeItem | MacroItem(_) | ProcMacroItem(_) diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index c85b955d4c57a..346e9a4e113a5 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -84,8 +84,8 @@ pub(crate) trait DocFolder: Sized { | TyMethodItem(_) | MethodItem(_, _) | StructFieldItem(_) - | ForeignFunctionItem(_) - | ForeignStaticItem(_) + | ForeignFunctionItem(..) + | ForeignStaticItem(..) | ForeignTypeItem | MacroItem(_) | ProcMacroItem(_) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index e1f79254b2488..0097386591529 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -254,7 +254,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf match &*item.kind { clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items), - clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => { + clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f, _) => { item_function(buf, cx, item, f) } 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 clean::MacroItem(ref m) => item_macro(buf, cx, item, m), clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m), clean::PrimitiveItem(_) => item_primitive(buf, cx, item), - clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => item_static(buf, cx, item, i), + clean::StaticItem(ref i) => item_static(buf, cx, item, i, None), + clean::ForeignStaticItem(ref i, safety) => item_static(buf, cx, item, i, Some(*safety)), clean::ConstantItem(generics, ty, c) => item_constant(buf, cx, item, generics, ty, c), clean::ForeignTypeItem => item_foreign_type(buf, cx, item), clean::KeywordItem => item_keyword(buf, cx, item), @@ -491,11 +492,14 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: } let unsafety_flag = match *myitem.kind { - clean::FunctionItem(_) | clean::ForeignFunctionItem(_) + clean::FunctionItem(_) | clean::ForeignFunctionItem(..) if myitem.fn_header(tcx).unwrap().safety == hir::Safety::Unsafe => { "" } + clean::ForeignStaticItem(_, hir::Safety::Unsafe) => { + "" + } _ => "", }; @@ -1957,13 +1961,22 @@ fn item_fields( } } -fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) { +fn item_static( + w: &mut impl fmt::Write, + cx: &mut Context<'_>, + it: &clean::Item, + s: &clean::Static, + safety: Option, +) { wrap_item(w, |buffer| { render_attributes_in_code(buffer, it, cx); write!( buffer, - "{vis}static {mutability}{name}: {typ}", + "{vis}{safe}static {mutability}{name}: {typ}", vis = visibility_print_with_space(it, cx), + safe = safety + .map(|safe| if safe == hir::Safety::Unsafe { "unsafe " } else { "" }) + .unwrap_or(""), mutability = s.mutability.print_with_space(), name = it.name.unwrap(), typ = s.type_.print(cx) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index afafb4fbe4b09..d099a97f1cba2 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -310,14 +310,16 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { EnumItem(e) => ItemEnum::Enum(e.into_tcx(tcx)), VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)), FunctionItem(f) => ItemEnum::Function(from_function(f, true, header.unwrap(), tcx)), - ForeignFunctionItem(f) => ItemEnum::Function(from_function(f, false, header.unwrap(), tcx)), + ForeignFunctionItem(f, _) => { + ItemEnum::Function(from_function(f, false, header.unwrap(), tcx)) + } TraitItem(t) => ItemEnum::Trait((*t).into_tcx(tcx)), TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)), MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), tcx)), TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), tcx)), ImplItem(i) => ItemEnum::Impl((*i).into_tcx(tcx)), StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), - ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), + ForeignStaticItem(s, _) => ItemEnum::Static(s.into_tcx(tcx)), ForeignTypeItem => ItemEnum::ForeignType, TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)), OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)), diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index 0660037e4d83d..b335dc5bd16b8 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -33,8 +33,8 @@ pub(crate) trait DocVisitor: Sized { | TyMethodItem(_) | MethodItem(_, _) | StructFieldItem(_) - | ForeignFunctionItem(_) - | ForeignStaticItem(_) + | ForeignFunctionItem(..) + | ForeignStaticItem(..) | ForeignTypeItem | MacroItem(_) | ProcMacroItem(_) diff --git a/tests/rustdoc/unsafe-extern-blocks.rs b/tests/rustdoc/unsafe-extern-blocks.rs new file mode 100644 index 0000000000000..22d3beea6c3a9 --- /dev/null +++ b/tests/rustdoc/unsafe-extern-blocks.rs @@ -0,0 +1,30 @@ +// Test to ensure the feature is working as expected. + +#![feature(unsafe_extern_blocks)] +#![crate_name = "foo"] + +// @has 'foo/index.html' + +// First we check that both the static and the function have a "sup" element +// to tell they're unsafe. + +// @count - '//ul[@class="item-table"]//sup[@title="unsafe static"]' 1 +// @has - '//ul[@class="item-table"]//sup[@title="unsafe static"]' '⚠' +// @count - '//ul[@class="item-table"]//sup[@title="unsafe function"]' 1 +// @has - '//ul[@class="item-table"]//sup[@title="unsafe function"]' '⚠' + +unsafe extern { + // @has 'foo/static.FOO.html' + // @has - '//pre[@class="rust item-decl"]' 'pub static FOO: i32' + pub safe static FOO: i32; + // @has 'foo/static.BAR.html' + // @has - '//pre[@class="rust item-decl"]' 'pub unsafe static BAR: i32' + pub static BAR: i32; + + // @has 'foo/fn.foo.html' + // @has - '//pre[@class="rust item-decl"]' 'pub extern "C" fn foo()' + pub safe fn foo(); + // @has 'foo/fn.bar.html' + // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn bar()' + pub fn bar(); +}