Skip to content

Commit 641c378

Browse files
authored
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`
2 parents e3b2655 + be4ea06 commit 641c378

File tree

7 files changed

+95
-17
lines changed

7 files changed

+95
-17
lines changed

src/etc/check_missing_items.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def check_type(ty):
108108
elif ty["kind"] == "function_pointer":
109109
for param in ty["inner"]["generic_params"]:
110110
check_generic_param(param)
111-
check_decl(ty["inner"]["inner"])
111+
check_decl(ty["inner"]["decl"])
112112
elif ty["kind"] == "qualified_path":
113113
check_type(ty["inner"]["self_type"])
114114
check_type(ty["inner"]["trait"])

src/librustdoc/json/conversions.rs

+26-10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
//! the `clean` types but with some fields removed or stringified to simplify the output and not
33
//! expose unstable compiler internals.
44
5+
#![allow(rustc::default_hash_types)]
6+
57
use std::convert::From;
68

79
use rustc_ast::ast;
@@ -16,6 +18,7 @@ use crate::clean;
1618
use crate::clean::utils::print_const_expr;
1719
use crate::formats::item_type::ItemType;
1820
use crate::json::JsonRenderer;
21+
use std::collections::HashSet;
1922

2023
impl JsonRenderer<'_> {
2124
pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
@@ -225,15 +228,22 @@ crate fn from_ctor_kind(struct_type: CtorKind) -> StructType {
225228
}
226229
}
227230

228-
fn stringify_header(header: &rustc_hir::FnHeader) -> String {
229-
let mut s = String::from(header.unsafety.prefix_str());
230-
if header.asyncness == rustc_hir::IsAsync::Async {
231-
s.push_str("async ")
231+
crate fn from_fn_header(header: &rustc_hir::FnHeader) -> HashSet<Qualifiers> {
232+
let mut v = HashSet::new();
233+
234+
if let rustc_hir::Unsafety::Unsafe = header.unsafety {
235+
v.insert(Qualifiers::Unsafe);
236+
}
237+
238+
if let rustc_hir::IsAsync::Async = header.asyncness {
239+
v.insert(Qualifiers::Async);
232240
}
233-
if header.constness == rustc_hir::Constness::Const {
234-
s.push_str("const ")
241+
242+
if let rustc_hir::Constness::Const = header.constness {
243+
v.insert(Qualifiers::Const);
235244
}
236-
s
245+
246+
v
237247
}
238248

239249
impl From<clean::Function> for Function {
@@ -242,7 +252,7 @@ impl From<clean::Function> for Function {
242252
Function {
243253
decl: decl.into(),
244254
generics: generics.into(),
245-
header: stringify_header(&header),
255+
header: from_fn_header(&header),
246256
abi: header.abi.to_string(),
247257
}
248258
}
@@ -364,7 +374,13 @@ impl From<clean::BareFunctionDecl> for FunctionPointer {
364374
fn from(bare_decl: clean::BareFunctionDecl) -> Self {
365375
let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl;
366376
FunctionPointer {
367-
is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
377+
header: if let rustc_hir::Unsafety::Unsafe = unsafety {
378+
let mut hs = HashSet::new();
379+
hs.insert(Qualifiers::Unsafe);
380+
hs
381+
} else {
382+
HashSet::new()
383+
},
368384
generic_params: generic_params.into_iter().map(Into::into).collect(),
369385
decl: decl.into(),
370386
abi: abi.to_string(),
@@ -439,7 +455,7 @@ crate fn from_function_method(function: clean::Function, has_body: bool) -> Meth
439455
Method {
440456
decl: decl.into(),
441457
generics: generics.into(),
442-
header: stringify_header(&header),
458+
header: from_fn_header(&header),
443459
abi: header.abi.to_string(),
444460
has_body,
445461
}

src/librustdoc/json/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
243243
)
244244
})
245245
.collect(),
246-
format_version: 3,
246+
format_version: 4,
247247
};
248248
let mut p = self.out_path.clone();
249249
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());

src/rustdoc-json-types/lib.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! These types are the public API exposed through the `--output-format json` flag. The [`Crate`]
44
//! struct is the root of the JSON blob and all other items are contained within.
55
6-
use std::collections::HashMap;
6+
use std::collections::{HashMap, HashSet};
77
use std::path::PathBuf;
88

99
use serde::{Deserialize, Serialize};
@@ -281,19 +281,28 @@ pub enum StructType {
281281
Unit,
282282
}
283283

284+
#[non_exhaustive]
285+
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
286+
#[serde(rename_all = "snake_case")]
287+
pub enum Qualifiers {
288+
Const,
289+
Unsafe,
290+
Async,
291+
}
292+
284293
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
285294
pub struct Function {
286295
pub decl: FnDecl,
287296
pub generics: Generics,
288-
pub header: String,
297+
pub header: HashSet<Qualifiers>,
289298
pub abi: String,
290299
}
291300

292301
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
293302
pub struct Method {
294303
pub decl: FnDecl,
295304
pub generics: Generics,
296-
pub header: String,
305+
pub header: HashSet<Qualifiers>,
297306
pub abi: String,
298307
pub has_body: bool,
299308
}
@@ -404,9 +413,9 @@ pub enum Type {
404413

405414
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
406415
pub struct FunctionPointer {
407-
pub is_unsafe: bool,
408-
pub generic_params: Vec<GenericParamDef>,
409416
pub decl: FnDecl,
417+
pub generic_params: Vec<GenericParamDef>,
418+
pub header: HashSet<Qualifiers>,
410419
pub abi: String,
411420
}
412421

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// @has header.json "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header" "[]"
2+
pub type FnPointer = fn();
3+
4+
// @has - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header" '["unsafe"]'
5+
pub type UnsafePointer = unsafe fn();

src/test/rustdoc-json/fns/header.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// edition:2018
2+
3+
// @has header.json "$.index[*][?(@.name=='nothing_fn')].inner.header" "[]"
4+
pub fn nothing_fn() {}
5+
6+
// @has - "$.index[*][?(@.name=='const_fn')].inner.header" '["const"]'
7+
pub const fn const_fn() {}
8+
9+
// @has - "$.index[*][?(@.name=='async_fn')].inner.header" '["async"]'
10+
pub async fn async_fn() {}
11+
12+
// @count - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header[*]" 2
13+
// @has - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header[*]" '"async"'
14+
// @has - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header[*]" '"unsafe"'
15+
pub async unsafe fn async_unsafe_fn() {}
16+
17+
// @count - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header[*]" 2
18+
// @has - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header[*]" '"const"'
19+
// @has - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header[*]" '"unsafe"'
20+
pub const unsafe fn const_unsafe_fn() {}
21+
22+
// It's impossible for a function to be both const and async, so no test for that
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// edition:2018
2+
3+
pub struct Foo;
4+
5+
impl Foo {
6+
// @has header.json "$.index[*][?(@.name=='nothing_meth')].inner.header" "[]"
7+
pub fn nothing_meth() {}
8+
9+
// @has - "$.index[*][?(@.name=='const_meth')].inner.header" '["const"]'
10+
pub const fn const_meth() {}
11+
12+
// @has - "$.index[*][?(@.name=='async_meth')].inner.header" '["async"]'
13+
pub async fn async_meth() {}
14+
15+
// @count - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header[*]" 2
16+
// @has - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header[*]" '"async"'
17+
// @has - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header[*]" '"unsafe"'
18+
pub async unsafe fn async_unsafe_meth() {}
19+
20+
// @count - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header[*]" 2
21+
// @has - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header[*]" '"const"'
22+
// @has - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header[*]" '"unsafe"'
23+
pub const unsafe fn const_unsafe_meth() {}
24+
25+
// It's impossible for a method to be both const and async, so no test for that
26+
}

0 commit comments

Comments
 (0)