From aa601574a5fe861bffd641beccf59c7be3ed16c9 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Fri, 18 Feb 2022 21:58:49 +0000 Subject: [PATCH 1/2] rustdoc-json: Better Header Type - Make ABI an enum, instead of being stringly typed - Replace Qualifier HashSet with 3 bools - Merge ABI field into header, as they always occor together --- compiler/rustc_hir/src/hir.rs | 4 +++ src/librustdoc/json/conversions.rs | 48 ++++++++++++++++-------------- src/rustdoc-json-types/lib.rs | 43 +++++++++++++++++--------- 3 files changed, 58 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 0961d0131d07c..5087bdd37e8bb 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -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)] diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index e77bd5c922313..d4aedb41ddb18 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -12,6 +12,7 @@ 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::*; @@ -19,7 +20,6 @@ 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 { @@ -271,22 +271,28 @@ crate fn from_ctor_kind(struct_type: CtorKind) -> StructType { } } -crate fn from_fn_header(header: &rustc_hir::FnHeader) -> HashSet { - 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 for Function { @@ -296,7 +302,6 @@ impl FromWithTcx for Function { decl: decl.into_tcx(tcx), generics: generics.into_tcx(tcx), header: from_fn_header(&header), - abi: header.abi.to_string(), } } } @@ -465,16 +470,14 @@ impl FromWithTcx 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(), } } } @@ -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, } } diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 600833664be5e..be9bbc7391d75 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -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 @@ -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, - pub abi: String, + pub header: Header, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Method { pub decl: FnDecl, pub generics: Generics, - pub header: HashSet, - pub abi: String, + pub header: Header, pub has_body: bool, } @@ -426,8 +442,7 @@ pub enum Type { pub struct FunctionPointer { pub decl: FnDecl, pub generic_params: Vec, - pub header: HashSet, - pub abi: String, + pub header: Header, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] From fd5adefce11c820b5ee1045058a435aa174bccf4 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Fri, 18 Feb 2022 23:32:37 +0000 Subject: [PATCH 2/2] rustdoc-json: Add tests for fn qualifiers and ABI --- src/test/rustdoc-json/fn_pointer/abi.rs | 25 +++++++++ src/test/rustdoc-json/fn_pointer/header.rs | 5 -- .../rustdoc-json/fn_pointer/qualifiers.rs | 9 +++ src/test/rustdoc-json/fns/abi.rs | 25 +++++++++ src/test/rustdoc-json/fns/header.rs | 22 -------- src/test/rustdoc-json/fns/qualifiers.rs | 33 +++++++++++ src/test/rustdoc-json/method_abi.rs | 25 --------- src/test/rustdoc-json/methods/abi.rs | 55 +++++++++++++++++++ src/test/rustdoc-json/methods/header.rs | 26 --------- src/test/rustdoc-json/methods/qualifiers.rs | 37 +++++++++++++ 10 files changed, 184 insertions(+), 78 deletions(-) create mode 100644 src/test/rustdoc-json/fn_pointer/abi.rs delete mode 100644 src/test/rustdoc-json/fn_pointer/header.rs create mode 100644 src/test/rustdoc-json/fn_pointer/qualifiers.rs create mode 100644 src/test/rustdoc-json/fns/abi.rs delete mode 100644 src/test/rustdoc-json/fns/header.rs create mode 100644 src/test/rustdoc-json/fns/qualifiers.rs delete mode 100644 src/test/rustdoc-json/method_abi.rs create mode 100644 src/test/rustdoc-json/methods/abi.rs delete mode 100644 src/test/rustdoc-json/methods/header.rs create mode 100644 src/test/rustdoc-json/methods/qualifiers.rs diff --git a/src/test/rustdoc-json/fn_pointer/abi.rs b/src/test/rustdoc-json/fn_pointer/abi.rs new file mode 100644 index 0000000000000..eef20e60a6a46 --- /dev/null +++ b/src/test/rustdoc-json/fn_pointer/abi.rs @@ -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(); diff --git a/src/test/rustdoc-json/fn_pointer/header.rs b/src/test/rustdoc-json/fn_pointer/header.rs deleted file mode 100644 index a5038e0cd2aa8..0000000000000 --- a/src/test/rustdoc-json/fn_pointer/header.rs +++ /dev/null @@ -1,5 +0,0 @@ -// @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(); diff --git a/src/test/rustdoc-json/fn_pointer/qualifiers.rs b/src/test/rustdoc-json/fn_pointer/qualifiers.rs new file mode 100644 index 0000000000000..3819220853639 --- /dev/null +++ b/src/test/rustdoc-json/fn_pointer/qualifiers.rs @@ -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(); diff --git a/src/test/rustdoc-json/fns/abi.rs b/src/test/rustdoc-json/fns/abi.rs new file mode 100644 index 0000000000000..16b579130656a --- /dev/null +++ b/src/test/rustdoc-json/fns/abi.rs @@ -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() {} diff --git a/src/test/rustdoc-json/fns/header.rs b/src/test/rustdoc-json/fns/header.rs deleted file mode 100644 index 29741dd50dadc..0000000000000 --- a/src/test/rustdoc-json/fns/header.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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 diff --git a/src/test/rustdoc-json/fns/qualifiers.rs b/src/test/rustdoc-json/fns/qualifiers.rs new file mode 100644 index 0000000000000..5cb3b43e66a96 --- /dev/null +++ b/src/test/rustdoc-json/fns/qualifiers.rs @@ -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 diff --git a/src/test/rustdoc-json/method_abi.rs b/src/test/rustdoc-json/method_abi.rs deleted file mode 100644 index 6fabbc836117b..0000000000000 --- a/src/test/rustdoc-json/method_abi.rs +++ /dev/null @@ -1,25 +0,0 @@ -// @has method_abi.json "$.index[*][?(@.name=='Foo')]" -pub struct Foo; - -impl Foo { - // @has - "$.index[*][?(@.name=='abi_rust')].inner.abi" '"\"Rust\""' - pub fn abi_rust() {} - - // @has - "$.index[*][?(@.name=='abi_c')].inner.abi" '"\"C\""' - pub extern "C" fn abi_c() {} - - // @has - "$.index[*][?(@.name=='abi_system')].inner.abi" '"\"system\""' - pub extern "system" fn abi_system() {} -} - -// @has method_abi.json "$.index[*][?(@.name=='Bar')]" -pub trait Bar { - // @has - "$.index[*][?(@.name=='trait_abi_rust')].inner.abi" '"\"Rust\""' - fn trait_abi_rust(); - - // @has - "$.index[*][?(@.name=='trait_abi_c')].inner.abi" '"\"C\""' - extern "C" fn trait_abi_c(); - - // @has - "$.index[*][?(@.name=='trait_abi_system')].inner.abi" '"\"system\""' - extern "system" fn trait_abi_system(); -} diff --git a/src/test/rustdoc-json/methods/abi.rs b/src/test/rustdoc-json/methods/abi.rs new file mode 100644 index 0000000000000..07b01d03bf6e3 --- /dev/null +++ b/src/test/rustdoc-json/methods/abi.rs @@ -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() {} +} diff --git a/src/test/rustdoc-json/methods/header.rs b/src/test/rustdoc-json/methods/header.rs deleted file mode 100644 index 50a3db75ef395..0000000000000 --- a/src/test/rustdoc-json/methods/header.rs +++ /dev/null @@ -1,26 +0,0 @@ -// 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 -} diff --git a/src/test/rustdoc-json/methods/qualifiers.rs b/src/test/rustdoc-json/methods/qualifiers.rs new file mode 100644 index 0000000000000..af36d36b6607d --- /dev/null +++ b/src/test/rustdoc-json/methods/qualifiers.rs @@ -0,0 +1,37 @@ +// edition:2018 + +pub struct Foo; + +impl Foo { + // @is qualifiers.json "$.index[*][?(@.name=='const_meth')].inner.header.async" false + // @is - "$.index[*][?(@.name=='const_meth')].inner.header.const" true + // @is - "$.index[*][?(@.name=='const_meth')].inner.header.unsafe" false + pub const fn const_meth() {} + + // @is - "$.index[*][?(@.name=='nothing_meth')].inner.header.async" false + // @is - "$.index[*][?(@.name=='nothing_meth')].inner.header.const" false + // @is - "$.index[*][?(@.name=='nothing_meth')].inner.header.unsafe" false + pub fn nothing_meth() {} + + // @is - "$.index[*][?(@.name=='unsafe_meth')].inner.header.async" false + // @is - "$.index[*][?(@.name=='unsafe_meth')].inner.header.const" false + // @is - "$.index[*][?(@.name=='unsafe_meth')].inner.header.unsafe" true + pub unsafe fn unsafe_meth() {} + + // @is - "$.index[*][?(@.name=='async_meth')].inner.header.async" true + // @is - "$.index[*][?(@.name=='async_meth')].inner.header.const" false + // @is - "$.index[*][?(@.name=='async_meth')].inner.header.unsafe" false + pub async fn async_meth() {} + + // @is - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.async" true + // @is - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.const" false + // @is - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.unsafe" true + pub async unsafe fn async_unsafe_meth() {} + + // @is - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.async" false + // @is - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.const" true + // @is - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.unsafe" true + pub const unsafe fn const_unsafe_meth() {} + + // It's impossible for a method to be both const and async, so no test for that +}