Rollup merge of #81891 - CraftSpider:fn-header, r=jyn514
[rustdoc-json] Make `header` a vec of modifiers, and FunctionPointer consistent Bumps version number and adds tests, this is a breaking change. I can split this into two (`is_unsafe` -> `header` and `header: Vec<Modifiers>`) if desired. Rationale: Modifiers are individual notes on a function, it makes more sense for them to be a list of an independent enum over a String which is inconsistently exposing the HIR representation (prefix_str vs custom literals). Function pointers currently only support `unsafe`, but there has been talk on and off about allowing them to also support `const`, and this makes handling their modifiers consistent with handling those of a function, allowing better shared code. `@rustbot` modify labels: +A-rustdoc-json +T-rustdoc CC: `@HeroicKatora` r? `@jyn514`
This commit is contained in:
commit
641c3785dc
@ -108,7 +108,7 @@ def check_type(ty):
|
||||
elif ty["kind"] == "function_pointer":
|
||||
for param in ty["inner"]["generic_params"]:
|
||||
check_generic_param(param)
|
||||
check_decl(ty["inner"]["inner"])
|
||||
check_decl(ty["inner"]["decl"])
|
||||
elif ty["kind"] == "qualified_path":
|
||||
check_type(ty["inner"]["self_type"])
|
||||
check_type(ty["inner"]["trait"])
|
||||
|
@ -2,6 +2,8 @@
|
||||
//! the `clean` types but with some fields removed or stringified to simplify the output and not
|
||||
//! expose unstable compiler internals.
|
||||
|
||||
#![allow(rustc::default_hash_types)]
|
||||
|
||||
use std::convert::From;
|
||||
|
||||
use rustc_ast::ast;
|
||||
@ -16,6 +18,7 @@ use crate::clean;
|
||||
use crate::clean::utils::print_const_expr;
|
||||
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> {
|
||||
@ -225,15 +228,22 @@ crate fn from_ctor_kind(struct_type: CtorKind) -> StructType {
|
||||
}
|
||||
}
|
||||
|
||||
fn stringify_header(header: &rustc_hir::FnHeader) -> String {
|
||||
let mut s = String::from(header.unsafety.prefix_str());
|
||||
if header.asyncness == rustc_hir::IsAsync::Async {
|
||||
s.push_str("async ")
|
||||
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 header.constness == rustc_hir::Constness::Const {
|
||||
s.push_str("const ")
|
||||
|
||||
if let rustc_hir::IsAsync::Async = header.asyncness {
|
||||
v.insert(Qualifiers::Async);
|
||||
}
|
||||
s
|
||||
|
||||
if let rustc_hir::Constness::Const = header.constness {
|
||||
v.insert(Qualifiers::Const);
|
||||
}
|
||||
|
||||
v
|
||||
}
|
||||
|
||||
impl From<clean::Function> for Function {
|
||||
@ -242,7 +252,7 @@ impl From<clean::Function> for Function {
|
||||
Function {
|
||||
decl: decl.into(),
|
||||
generics: generics.into(),
|
||||
header: stringify_header(&header),
|
||||
header: from_fn_header(&header),
|
||||
abi: header.abi.to_string(),
|
||||
}
|
||||
}
|
||||
@ -364,7 +374,13 @@ impl From<clean::BareFunctionDecl> for FunctionPointer {
|
||||
fn from(bare_decl: clean::BareFunctionDecl) -> Self {
|
||||
let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl;
|
||||
FunctionPointer {
|
||||
is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
|
||||
header: if let rustc_hir::Unsafety::Unsafe = unsafety {
|
||||
let mut hs = HashSet::new();
|
||||
hs.insert(Qualifiers::Unsafe);
|
||||
hs
|
||||
} else {
|
||||
HashSet::new()
|
||||
},
|
||||
generic_params: generic_params.into_iter().map(Into::into).collect(),
|
||||
decl: decl.into(),
|
||||
abi: abi.to_string(),
|
||||
@ -439,7 +455,7 @@ crate fn from_function_method(function: clean::Function, has_body: bool) -> Meth
|
||||
Method {
|
||||
decl: decl.into(),
|
||||
generics: generics.into(),
|
||||
header: stringify_header(&header),
|
||||
header: from_fn_header(&header),
|
||||
abi: header.abi.to_string(),
|
||||
has_body,
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
format_version: 3,
|
||||
format_version: 4,
|
||||
};
|
||||
let mut p = self.out_path.clone();
|
||||
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! 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;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -281,11 +281,20 @@ 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,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct Function {
|
||||
pub decl: FnDecl,
|
||||
pub generics: Generics,
|
||||
pub header: String,
|
||||
pub header: HashSet<Qualifiers>,
|
||||
pub abi: String,
|
||||
}
|
||||
|
||||
@ -293,7 +302,7 @@ pub struct Function {
|
||||
pub struct Method {
|
||||
pub decl: FnDecl,
|
||||
pub generics: Generics,
|
||||
pub header: String,
|
||||
pub header: HashSet<Qualifiers>,
|
||||
pub abi: String,
|
||||
pub has_body: bool,
|
||||
}
|
||||
@ -404,9 +413,9 @@ pub enum Type {
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct FunctionPointer {
|
||||
pub is_unsafe: bool,
|
||||
pub generic_params: Vec<GenericParamDef>,
|
||||
pub decl: FnDecl,
|
||||
pub generic_params: Vec<GenericParamDef>,
|
||||
pub header: HashSet<Qualifiers>,
|
||||
pub abi: String,
|
||||
}
|
||||
|
||||
|
5
src/test/rustdoc-json/fn_pointer/header.rs
Normal file
5
src/test/rustdoc-json/fn_pointer/header.rs
Normal file
@ -0,0 +1,5 @@
|
||||
// @has header.json "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header" "[]"
|
||||
pub type FnPointer = fn();
|
||||
|
||||
// @has - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header" '["unsafe"]'
|
||||
pub type UnsafePointer = unsafe fn();
|
22
src/test/rustdoc-json/fns/header.rs
Normal file
22
src/test/rustdoc-json/fns/header.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// edition:2018
|
||||
|
||||
// @has header.json "$.index[*][?(@.name=='nothing_fn')].inner.header" "[]"
|
||||
pub fn nothing_fn() {}
|
||||
|
||||
// @has - "$.index[*][?(@.name=='const_fn')].inner.header" '["const"]'
|
||||
pub const fn const_fn() {}
|
||||
|
||||
// @has - "$.index[*][?(@.name=='async_fn')].inner.header" '["async"]'
|
||||
pub async fn async_fn() {}
|
||||
|
||||
// @count - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header[*]" 2
|
||||
// @has - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header[*]" '"async"'
|
||||
// @has - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header[*]" '"unsafe"'
|
||||
pub async unsafe fn async_unsafe_fn() {}
|
||||
|
||||
// @count - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header[*]" 2
|
||||
// @has - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header[*]" '"const"'
|
||||
// @has - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header[*]" '"unsafe"'
|
||||
pub const unsafe fn const_unsafe_fn() {}
|
||||
|
||||
// It's impossible for a function to be both const and async, so no test for that
|
26
src/test/rustdoc-json/methods/header.rs
Normal file
26
src/test/rustdoc-json/methods/header.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// edition:2018
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
impl Foo {
|
||||
// @has header.json "$.index[*][?(@.name=='nothing_meth')].inner.header" "[]"
|
||||
pub fn nothing_meth() {}
|
||||
|
||||
// @has - "$.index[*][?(@.name=='const_meth')].inner.header" '["const"]'
|
||||
pub const fn const_meth() {}
|
||||
|
||||
// @has - "$.index[*][?(@.name=='async_meth')].inner.header" '["async"]'
|
||||
pub async fn async_meth() {}
|
||||
|
||||
// @count - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header[*]" 2
|
||||
// @has - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header[*]" '"async"'
|
||||
// @has - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header[*]" '"unsafe"'
|
||||
pub async unsafe fn async_unsafe_meth() {}
|
||||
|
||||
// @count - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header[*]" 2
|
||||
// @has - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header[*]" '"const"'
|
||||
// @has - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header[*]" '"unsafe"'
|
||||
pub const unsafe fn const_unsafe_meth() {}
|
||||
|
||||
// It's impossible for a method to be both const and async, so no test for that
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user