Skip to content

rustdoc-json: Better Header Type #94137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2777,6 +2777,10 @@ impl FnHeader {
pub fn is_const(&self) -> bool {
matches!(&self.constness, Constness::Const)
}

pub fn is_unsafe(&self) -> bool {
matches!(&self.unsafety, Unsafety::Unsafe)
}
}

#[derive(Debug, HashStable_Generic)]
Expand Down
48 changes: 25 additions & 23 deletions src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ use rustc_hir::{def::CtorKind, def_id::DefId};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::def_id::CRATE_DEF_INDEX;
use rustc_span::Pos;
use rustc_target::spec::abi::Abi as RustcAbi;

use rustdoc_json_types::*;

use crate::clean::utils::print_const_expr;
use crate::clean::{self, ItemId};
use crate::formats::item_type::ItemType;
use crate::json::JsonRenderer;
use std::collections::HashSet;

impl JsonRenderer<'_> {
pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
Expand Down Expand Up @@ -271,22 +271,28 @@ crate fn from_ctor_kind(struct_type: CtorKind) -> StructType {
}
}

crate fn from_fn_header(header: &rustc_hir::FnHeader) -> HashSet<Qualifiers> {
let mut v = HashSet::new();

if let rustc_hir::Unsafety::Unsafe = header.unsafety {
v.insert(Qualifiers::Unsafe);
}

if let rustc_hir::IsAsync::Async = header.asyncness {
v.insert(Qualifiers::Async);
crate fn from_fn_header(header: &rustc_hir::FnHeader) -> Header {
Header {
async_: header.is_async(),
const_: header.is_const(),
unsafe_: header.is_unsafe(),
abi: convert_abi(header.abi),
}
}

if let rustc_hir::Constness::Const = header.constness {
v.insert(Qualifiers::Const);
fn convert_abi(a: RustcAbi) -> Abi {
match a {
RustcAbi::Rust => Abi::Rust,
RustcAbi::C { unwind } => Abi::C { unwind },
RustcAbi::Cdecl { unwind } => Abi::Cdecl { unwind },
RustcAbi::Stdcall { unwind } => Abi::Stdcall { unwind },
RustcAbi::Fastcall { unwind } => Abi::Fastcall { unwind },
RustcAbi::Aapcs { unwind } => Abi::Aapcs { unwind },
RustcAbi::Win64 { unwind } => Abi::Win64 { unwind },
RustcAbi::SysV64 { unwind } => Abi::SysV64 { unwind },
RustcAbi::System { unwind } => Abi::System { unwind },
_ => Abi::Other(a.to_string()),
}

v
}

impl FromWithTcx<clean::Function> for Function {
Expand All @@ -296,7 +302,6 @@ impl FromWithTcx<clean::Function> for Function {
decl: decl.into_tcx(tcx),
generics: generics.into_tcx(tcx),
header: from_fn_header(&header),
abi: header.abi.to_string(),
}
}
}
Expand Down Expand Up @@ -465,16 +470,14 @@ impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer {
fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self {
let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl;
FunctionPointer {
header: if let rustc_hir::Unsafety::Unsafe = unsafety {
let mut hs = HashSet::new();
hs.insert(Qualifiers::Unsafe);
hs
} else {
HashSet::new()
header: Header {
unsafe_: matches!(unsafety, rustc_hir::Unsafety::Unsafe),
const_: false,
async_: false,
abi: convert_abi(abi),
},
generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
decl: decl.into_tcx(tcx),
abi: abi.to_string(),
}
}
}
Expand Down Expand Up @@ -554,7 +557,6 @@ crate fn from_function_method(
decl: decl.into_tcx(tcx),
generics: generics.into_tcx(tcx),
header: from_fn_header(&header),
abi: header.abi.to_string(),
has_body,
}
}
Expand Down
43 changes: 29 additions & 14 deletions src/rustdoc-json-types/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
//! These types are the public API exposed through the `--output-format json` flag. The [`Crate`]
//! struct is the root of the JSON blob and all other items are contained within.

use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
use std::path::PathBuf;

use serde::{Deserialize, Serialize};

/// rustdoc format-version.
pub const FORMAT_VERSION: u32 = 10;
pub const FORMAT_VERSION: u32 = 11;

/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
/// about the language items in the local crate, as well as info about external items to allow
Expand Down Expand Up @@ -287,29 +287,45 @@ pub enum StructType {
Unit,
}

#[non_exhaustive]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum Qualifiers {
Const,
Unsafe,
Async,
pub struct Header {
#[serde(rename = "const")]
pub const_: bool,
#[serde(rename = "unsafe")]
pub unsafe_: bool,
#[serde(rename = "async")]
pub async_: bool,
pub abi: Abi,
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum Abi {
// We only have a concrete listing here for stable ABI's because their are so many
// See rustc_ast_passes::feature_gate::PostExpansionVisitor::check_abi for the list
Rust,
C { unwind: bool },
Cdecl { unwind: bool },
Stdcall { unwind: bool },
Fastcall { unwind: bool },
Aapcs { unwind: bool },
Win64 { unwind: bool },
SysV64 { unwind: bool },
System { unwind: bool },
Other(String),
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Function {
pub decl: FnDecl,
pub generics: Generics,
pub header: HashSet<Qualifiers>,
pub abi: String,
pub header: Header,
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Method {
pub decl: FnDecl,
pub generics: Generics,
pub header: HashSet<Qualifiers>,
pub abi: String,
pub header: Header,
pub has_body: bool,
}

Expand Down Expand Up @@ -426,8 +442,7 @@ pub enum Type {
pub struct FunctionPointer {
pub decl: FnDecl,
pub generic_params: Vec<GenericParamDef>,
pub header: HashSet<Qualifiers>,
pub abi: String,
pub header: Header,
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
Expand Down
25 changes: 25 additions & 0 deletions src/test/rustdoc-json/fn_pointer/abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// ignore-tidy-linelength

#![feature(abi_vectorcall)]
#![feature(c_unwind)]

// @is abi.json "$.index[*][?(@.name=='AbiRust')].inner.type.inner.header.abi" \"Rust\"
pub type AbiRust = fn();

// @is - "$.index[*][?(@.name=='AbiC')].inner.type.inner.header.abi" '{"C": {"unwind": false}}'
pub type AbiC = extern "C" fn();

// @is - "$.index[*][?(@.name=='AbiSystem')].inner.type.inner.header.abi" '{"System": {"unwind": false}}'
pub type AbiSystem = extern "system" fn();

// @is - "$.index[*][?(@.name=='AbiCUnwind')].inner.type.inner.header.abi" '{"C": {"unwind": true}}'
pub type AbiCUnwind = extern "C-unwind" fn();

// @is - "$.index[*][?(@.name=='AbiSystemUnwind')].inner.type.inner.header.abi" '{"System": {"unwind": true}}'
pub type AbiSystemUnwind = extern "system-unwind" fn();

// @is - "$.index[*][?(@.name=='AbiVecorcall')].inner.type.inner.header.abi.Other" '"\"vectorcall\""'
pub type AbiVecorcall = extern "vectorcall" fn();

// @is - "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.type.inner.header.abi.Other" '"\"vectorcall-unwind\""'
pub type AbiVecorcallUnwind = extern "vectorcall-unwind" fn();
5 changes: 0 additions & 5 deletions src/test/rustdoc-json/fn_pointer/header.rs

This file was deleted.

9 changes: 9 additions & 0 deletions src/test/rustdoc-json/fn_pointer/qualifiers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @is qualifiers.json "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.unsafe" false
// @is - "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.const" false
// @is - "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.async" false
pub type FnPointer = fn();

// @is - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.unsafe" true
// @is - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.const" false
// @is - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.async" false
pub type UnsafePointer = unsafe fn();
25 changes: 25 additions & 0 deletions src/test/rustdoc-json/fns/abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// ignore-tidy-linelength

#![feature(abi_vectorcall)]
#![feature(c_unwind)]

// @is abi.json "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\"
pub fn abi_rust() {}

// @is - "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
pub extern "C" fn abi_c() {}

// @is - "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
pub extern "system" fn abi_system() {}

// @is - "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
pub extern "C-unwind" fn abi_c_unwind() {}

// @is - "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
pub extern "system-unwind" fn abi_system_unwind() {}

// @is - "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
pub extern "vectorcall" fn abi_vectorcall() {}

// @is - "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {}
22 changes: 0 additions & 22 deletions src/test/rustdoc-json/fns/header.rs

This file was deleted.

33 changes: 33 additions & 0 deletions src/test/rustdoc-json/fns/qualifiers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// edition:2018

// @is qualifiers.json "$.index[*][?(@.name=='nothing_fn')].inner.header.async" false
// @is - "$.index[*][?(@.name=='nothing_fn')].inner.header.const" false
// @is - "$.index[*][?(@.name=='nothing_fn')].inner.header.unsafe" false
pub fn nothing_fn() {}

// @is - "$.index[*][?(@.name=='unsafe_fn')].inner.header.async" false
// @is - "$.index[*][?(@.name=='unsafe_fn')].inner.header.const" false
// @is - "$.index[*][?(@.name=='unsafe_fn')].inner.header.unsafe" true
pub unsafe fn unsafe_fn() {}

// @is - "$.index[*][?(@.name=='const_fn')].inner.header.async" false
// @is - "$.index[*][?(@.name=='const_fn')].inner.header.const" true
// @is - "$.index[*][?(@.name=='const_fn')].inner.header.unsafe" false
pub const fn const_fn() {}

// @is - "$.index[*][?(@.name=='async_fn')].inner.header.async" true
// @is - "$.index[*][?(@.name=='async_fn')].inner.header.const" false
// @is - "$.index[*][?(@.name=='async_fn')].inner.header.unsafe" false
pub async fn async_fn() {}

// @is - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.async" true
// @is - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.const" false
// @is - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.unsafe" true
pub async unsafe fn async_unsafe_fn() {}

// @is - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.async" false
// @is - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.const" true
// @is - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.unsafe" true
pub const unsafe fn const_unsafe_fn() {}

// It's impossible for a function to be both const and async, so no test for that
25 changes: 0 additions & 25 deletions src/test/rustdoc-json/method_abi.rs

This file was deleted.

55 changes: 55 additions & 0 deletions src/test/rustdoc-json/methods/abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// ignore-tidy-linelength

#![feature(abi_vectorcall)]
#![feature(c_unwind)]
#![feature(no_core)]
#![no_core]

// @has abi.json "$.index[*][?(@.name=='Foo')]"
pub struct Foo;

impl Foo {
// @is - "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\"
pub fn abi_rust() {}

// @is - "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
pub extern "C" fn abi_c() {}

// @is - "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
pub extern "system" fn abi_system() {}

// @is - "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
pub extern "C-unwind" fn abi_c_unwind() {}

// @is - "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
pub extern "system-unwind" fn abi_system_unwind() {}

// @is - "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
pub extern "vectorcall" fn abi_vectorcall() {}

// @is - "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {}
}

pub trait Bar {
// @is - "$.index[*][?(@.name=='trait_abi_rust')].inner.header.abi" \"Rust\"
fn trait_abi_rust() {}

// @is - "$.index[*][?(@.name=='trait_abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
extern "C" fn trait_abi_c() {}

// @is - "$.index[*][?(@.name=='trait_abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
extern "system" fn trait_abi_system() {}

// @is - "$.index[*][?(@.name=='trait_abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
extern "C-unwind" fn trait_abi_c_unwind() {}

// @is - "$.index[*][?(@.name=='trait_abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
extern "system-unwind" fn trait_abi_system_unwind() {}

// @is - "$.index[*][?(@.name=='trait_abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
extern "vectorcall" fn trait_abi_vectorcall() {}

// @is - "$.index[*][?(@.name=='trait_abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
extern "vectorcall-unwind" fn trait_abi_vectorcall_unwind() {}
}
Loading