From 61b6f6588402123ee20467f7df9863a9194d4fe2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 28 Apr 2023 21:55:14 +0200 Subject: [PATCH] Get `repr` information through `AdtDef` for foreign items --- src/librustdoc/html/render/mod.rs | 69 ++++++++++++++++++++---- src/librustdoc/html/render/print_item.rs | 23 ++++---- src/librustdoc/lib.rs | 1 + 3 files changed, 72 insertions(+), 21 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index a5f08fdac11..55b249f8bbf 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -849,10 +849,10 @@ fn assoc_method( let (indent, indent_str, end_newline) = if parent == ItemType::Trait { header_len += 4; let indent_str = " "; - write!(w, "{}", render_attributes_in_pre(meth, indent_str)); + write!(w, "{}", render_attributes_in_pre(meth, indent_str, tcx)); (4, indent_str, Ending::NoNewline) } else { - render_attributes_in_code(w, meth); + render_attributes_in_code(w, meth, tcx); (0, "", Ending::Newline) }; w.reserve(header_len + "{".len() + "".len()); @@ -1024,8 +1024,12 @@ fn render_assoc_item( const ALLOWED_ATTRIBUTES: &[Symbol] = &[sym::export_name, sym::link_section, sym::no_mangle, sym::repr, sym::non_exhaustive]; -fn attributes(it: &clean::Item) -> Vec { - it.attrs +fn attributes(it: &clean::Item, tcx: TyCtxt<'_>) -> Vec { + use rustc_abi::IntegerType; + use rustc_middle::ty::ReprFlags; + + let mut attrs: Vec = it + .attrs .other_attrs .iter() .filter_map(|attr| { @@ -1040,17 +1044,62 @@ fn attributes(it: &clean::Item) -> Vec { None } }) - .collect() + .collect(); + if let Some(def_id) = it.item_id.as_def_id() && + !def_id.is_local() && + // This check is needed because `adt_def` will panic if not a compatible type otherwise... + matches!(it.type_(), ItemType::Struct | ItemType::Enum | ItemType::Union) + { + let repr = tcx.adt_def(def_id).repr(); + let mut out = Vec::new(); + if repr.flags.contains(ReprFlags::IS_C) { + out.push("C"); + } + if repr.flags.contains(ReprFlags::IS_TRANSPARENT) { + out.push("transparent"); + } + if repr.flags.contains(ReprFlags::IS_SIMD) { + out.push("simd"); + } + let pack_s; + if let Some(pack) = repr.pack { + pack_s = format!("packed({})", pack.bytes()); + out.push(&pack_s); + } + let align_s; + if let Some(align) = repr.align { + align_s = format!("align({})", align.bytes()); + out.push(&align_s); + } + let int_s; + if let Some(int) = repr.int { + int_s = match int { + IntegerType::Pointer(is_signed) => { + format!("{}size", if is_signed { 'i' } else { 'u' }) + } + IntegerType::Fixed(size, is_signed) => { + format!("{}{}", if is_signed { 'i' } else { 'u' }, size.size().bytes() * 8) + } + }; + out.push(&int_s); + } + if out.is_empty() { + return Vec::new(); + } + attrs.push(format!("#[repr({})]", out.join(", "))); + } + attrs } // When an attribute is rendered inside a `
` tag, it is formatted using
 // a whitespace prefix and newline.
-fn render_attributes_in_pre<'a>(
+fn render_attributes_in_pre<'a, 'b: 'a>(
     it: &'a clean::Item,
     prefix: &'a str,
-) -> impl fmt::Display + Captures<'a> {
+    tcx: TyCtxt<'b>,
+) -> impl fmt::Display + Captures<'a> + Captures<'b> {
     crate::html::format::display_fn(move |f| {
-        for a in attributes(it) {
+        for a in attributes(it, tcx) {
             writeln!(f, "{}{}", prefix, a)?;
         }
         Ok(())
@@ -1059,8 +1108,8 @@ fn render_attributes_in_pre<'a>(
 
 // When an attribute is rendered inside a  tag, it is formatted using
 // a div to produce a newline after it.
-fn render_attributes_in_code(w: &mut Buffer, it: &clean::Item) {
-    for a in attributes(it) {
+fn render_attributes_in_code(w: &mut Buffer, it: &clean::Item, tcx: TyCtxt<'_>) {
+    for a in attributes(it, tcx) {
         write!(w, "
{}
", a); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 3e71d41ec96..40f69189a8e 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -548,7 +548,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle w, "{attrs}{vis}{constness}{asyncness}{unsafety}{abi}fn \ {name}{generics}{decl}{notable_traits}{where_clause}", - attrs = render_attributes_in_pre(it, ""), + attrs = render_attributes_in_pre(it, "", tcx), vis = visibility, constness = constness, asyncness = asyncness, @@ -589,7 +589,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: it.name.unwrap(), t.generics.print(cx), bounds, - attrs = render_attributes_in_pre(it, ""), + attrs = render_attributes_in_pre(it, "", tcx), ); if !t.generics.where_predicates.is_empty() { @@ -1063,7 +1063,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: & t.generics.print(cx), print_where_clause(&t.generics, cx, 0, Ending::Newline), bounds(&t.bounds, true, cx), - attrs = render_attributes_in_pre(it, ""), + attrs = render_attributes_in_pre(it, "", cx.tcx()), ); }); @@ -1085,7 +1085,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &cl t.generics.print(cx), where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline), bounds = bounds(&t.bounds, false, cx), - attrs = render_attributes_in_pre(it, ""), + attrs = render_attributes_in_pre(it, "", cx.tcx()), ); }); @@ -1109,7 +1109,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea t.generics.print(cx), where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline), type_ = t.type_.print(cx), - attrs = render_attributes_in_pre(it, ""), + attrs = render_attributes_in_pre(it, "", cx.tcx()), ); }); } @@ -1168,7 +1168,8 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: &'b self, ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let v = render_attributes_in_pre(self.it, ""); + let tcx = self.cx.borrow().tcx(); + let v = render_attributes_in_pre(self.it, "", tcx); write!(f, "{v}") }) } @@ -1250,7 +1251,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: visibility_print_with_space(it.visibility(tcx), it.item_id, cx), it.name.unwrap(), e.generics.print(cx), - attrs = render_attributes_in_pre(it, ""), + attrs = render_attributes_in_pre(it, "", tcx), ); if !print_where_clause_and_check(w, &e.generics, cx) { // If there wasn't a `where` clause, we add a whitespace. @@ -1445,7 +1446,7 @@ fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) { wrap_item(w, |w| { let tcx = cx.tcx(); - render_attributes_in_code(w, it); + render_attributes_in_code(w, it, tcx); write!( w, @@ -1492,7 +1493,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) { wrap_item(w, |w| { - render_attributes_in_code(w, it); + render_attributes_in_code(w, it, cx.tcx()); render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx); }); @@ -1542,7 +1543,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) { wrap_item(w, |w| { - render_attributes_in_code(w, it); + render_attributes_in_code(w, it, cx.tcx()); write!( w, "{vis}static {mutability}{name}: {typ}", @@ -1558,7 +1559,7 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { wrap_item(w, |w| { w.write_str("extern {\n"); - render_attributes_in_code(w, it); + render_attributes_in_code(w, it, cx.tcx()); write!( w, " {}type {};\n}}", diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index c15afca2261..eb589bb2414 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -33,6 +33,7 @@ extern crate tracing; // Dependencies listed in Cargo.toml do not need `extern crate`. extern crate pulldown_cmark; +extern crate rustc_abi; extern crate rustc_ast; extern crate rustc_ast_pretty; extern crate rustc_attr;