Skip to content

Commit a856e57

Browse files
committed
Rustdoc-Json: Document HRTB's on DynTrait
Closes #99118
1 parent 2143e48 commit a856e57

File tree

4 files changed

+91
-49
lines changed

4 files changed

+91
-49
lines changed

src/librustdoc/json/conversions.rs

+22-26
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
244244
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
245245
MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, header.unwrap(), tcx)),
246246
TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, header.unwrap(), tcx)),
247-
ImplItem(i) => ItemEnum::Impl(i.into_tcx(tcx)),
247+
ImplItem(i) => ItemEnum::Impl((*i).into_tcx(tcx)),
248248
StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
249249
ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
250250
ForeignTypeItem => ItemEnum::ForeignType,
@@ -447,8 +447,8 @@ pub(crate) fn from_trait_bound_modifier(
447447
impl FromWithTcx<clean::Type> for Type {
448448
fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
449449
use clean::Type::{
450-
Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive,
451-
QPath, RawPointer, Slice, Tuple,
450+
Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
451+
RawPointer, Slice, Tuple,
452452
};
453453

454454
match ty {
@@ -458,26 +458,10 @@ impl FromWithTcx<clean::Type> for Type {
458458
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
459459
param_names: Vec::new(),
460460
},
461-
DynTrait(mut bounds, lt) => {
462-
let first_trait = bounds.remove(0).trait_;
463-
464-
Type::ResolvedPath {
465-
name: first_trait.whole_name(),
466-
id: from_item_id(first_trait.def_id().into(), tcx),
467-
args: first_trait
468-
.segments
469-
.last()
470-
.map(|args| Box::new(args.clone().args.into_tcx(tcx))),
471-
param_names: bounds
472-
.into_iter()
473-
.map(|t| {
474-
clean::GenericBound::TraitBound(t, rustc_hir::TraitBoundModifier::None)
475-
})
476-
.chain(lt.map(clean::GenericBound::Outlives))
477-
.map(|bound| bound.into_tcx(tcx))
478-
.collect(),
479-
}
480-
}
461+
clean::Type::DynTrait(bounds, lt) => Type::DynTrait(DynTrait {
462+
lifetime: lt.map(|lt| lt.0.to_string()),
463+
traits: bounds.into_iter().map(|t| t.into_tcx(tcx)).collect(),
464+
}),
481465
Generic(s) => Type::Generic(s.to_string()),
482466
Primitive(p) => Type::Primitive(p.as_sym().to_string()),
483467
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
@@ -568,10 +552,22 @@ impl FromWithTcx<clean::Trait> for Trait {
568552
}
569553
}
570554

571-
impl FromWithTcx<Box<clean::Impl>> for Impl {
572-
fn from_tcx(impl_: Box<clean::Impl>, tcx: TyCtxt<'_>) -> Self {
555+
impl FromWithTcx<clean::PolyTrait> for PolyTrait {
556+
fn from_tcx(
557+
clean::PolyTrait { trait_, generic_params }: clean::PolyTrait,
558+
tcx: TyCtxt<'_>,
559+
) -> Self {
560+
PolyTrait {
561+
trait_: clean::Type::Path { path: trait_ }.into_tcx(tcx),
562+
generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
563+
}
564+
}
565+
}
566+
567+
impl FromWithTcx<clean::Impl> for Impl {
568+
fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
573569
let provided_trait_methods = impl_.provided_trait_methods(tcx);
574-
let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = *impl_;
570+
let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_;
575571
// FIXME: should `trait_` be a clean::Path equivalent in JSON?
576572
let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
577573
// FIXME: use something like ImplKind in JSON?

src/rustdoc-json-types/lib.rs

+34-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::path::PathBuf;
99
use serde::{Deserialize, Serialize};
1010

1111
/// rustdoc format-version.
12-
pub const FORMAT_VERSION: u32 = 16;
12+
pub const FORMAT_VERSION: u32 = 17;
1313

1414
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
1515
/// about the language items in the local crate, as well as info about external items to allow
@@ -115,6 +115,35 @@ pub enum Visibility {
115115
},
116116
}
117117

118+
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
119+
pub struct DynTrait {
120+
/// All the traits implemented. One of them is the vtable, and the rest must be auto traits.
121+
pub traits: Vec<PolyTrait>,
122+
/// The lifetime of the whole dyn object
123+
/// ```text
124+
/// dyn Debug + 'static
125+
/// ^^^^^^^
126+
/// |
127+
/// this part
128+
/// ```
129+
pub lifetime: Option<String>,
130+
}
131+
132+
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
133+
/// A trait and potential HRTBs
134+
pub struct PolyTrait {
135+
#[serde(rename = "trait")]
136+
pub trait_: Type,
137+
/// Used for Higher-Rank Trait Bounds (HRTBs)
138+
/// ```text
139+
/// dyn for<'a> Fn() -> &'a i32"
140+
/// ^^^^^^^
141+
/// |
142+
/// this part
143+
/// ```
144+
pub generic_params: Vec<GenericParamDef>,
145+
}
146+
118147
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
119148
#[serde(rename_all = "snake_case")]
120149
pub enum GenericArgs {
@@ -395,7 +424,7 @@ pub enum WherePredicate {
395424
type_: Type,
396425
bounds: Vec<GenericBound>,
397426
/// Used for Higher-Rank Trait Bounds (HRTBs)
398-
/// ```plain
427+
/// ```text
399428
/// where for<'a> &'a T: Iterator,"
400429
/// ^^^^^^^
401430
/// |
@@ -420,7 +449,7 @@ pub enum GenericBound {
420449
#[serde(rename = "trait")]
421450
trait_: Type,
422451
/// Used for Higher-Rank Trait Bounds (HRTBs)
423-
/// ```plain
452+
/// ```text
424453
/// where F: for<'a, 'b> Fn(&'a u8, &'b u8)
425454
/// ^^^^^^^^^^^
426455
/// |
@@ -458,6 +487,7 @@ pub enum Type {
458487
args: Option<Box<GenericArgs>>,
459488
param_names: Vec<GenericBound>,
460489
},
490+
DynTrait(DynTrait),
461491
/// Parameterized types
462492
Generic(String),
463493
/// Fixed-size numeric types (plus int/usize/float), char, arrays, slices, and tuples
@@ -505,7 +535,7 @@ pub enum Type {
505535
pub struct FunctionPointer {
506536
pub decl: FnDecl,
507537
/// Used for Higher-Rank Trait Bounds (HRTBs)
508-
/// ```plain
538+
/// ```text
509539
/// for<'c> fn(val: &'c i32) -> i32
510540
/// ^^^^^^^
511541
/// |

src/test/rustdoc-json/type/dyn.rs

+29-16
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,49 @@
11
// ignore-tidy-linelength
2+
use std::fmt::Debug;
23

3-
// @count dyn.json "$.index[*][?(@.name=='dyn')].inner.items[*]" 2
4+
// @count dyn.json "$.index[*][?(@.name=='dyn')].inner.items[*]" 3
45
// @set sync_int_gen = - "$.index[*][?(@.name=='SyncIntGen')].id"
5-
// @set ref_fn = - "$.index[*][?(@.name=='RefFn')].id"
6+
// @set ref_fn = - "$.index[*][?(@.name=='RefFn')].id"
7+
// @set weird_order = - "$.index[*][?(@.name=='WeirdOrder')].id"
68
// @has - "$.index[*][?(@.name=='dyn')].inner.items[*]" $sync_int_gen
79
// @has - "$.index[*][?(@.name=='dyn')].inner.items[*]" $ref_fn
10+
// @has - "$.index[*][?(@.name=='dyn')].inner.items[*]" $weird_order
811

912
// @is - "$.index[*][?(@.name=='SyncIntGen')].kind" \"typedef\"
1013
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.generics" '{"params": [], "where_predicates": []}'
1114
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.kind" \"resolved_path\"
1215
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.name" \"Box\"
1316
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.bindings" []
1417
// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args" 1
15-
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\"
16-
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\"
17-
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.name" \"Fn\"
18-
// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[*]" 3
19-
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[0].trait_bound.trait.inner.name" \"Send\"
20-
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[1].trait_bound.trait.inner.name" \"Sync\"
21-
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[2]" "{\"outlives\": \"'static\"}"
22-
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}'
18+
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"dyn_trait\"
19+
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.lifetime" \"\'static\"
20+
// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[*]" 3
21+
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].generic_params" []
22+
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].generic_params" []
23+
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].generic_params" []
24+
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.name" '"Fn"'
25+
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.inner.name" '"Send"'
26+
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].trait.inner.name" '"Sync"'
27+
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}'
2328
pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
2429

2530
// @is - "$.index[*][?(@.name=='RefFn')].kind" \"typedef\"
2631
// @is - "$.index[*][?(@.name=='RefFn')].inner.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}'
2732
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.kind" '"borrowed_ref"'
2833
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.mutable" 'false'
2934
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.lifetime" "\"'a\""
30-
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.kind" '"resolved_path"'
31-
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.name" '"Fn"'
32-
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.args.parenthesized.inputs[0].kind" '"borrowed_ref"'
33-
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.args.parenthesized.inputs[0].inner.lifetime" "\"'b\""
34-
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.args.parenthesized.output.kind" '"borrowed_ref"'
35-
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.args.parenthesized.output.inner.lifetime" "\"'b\""
35+
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.kind" '"dyn_trait"'
36+
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.lifetime" null
37+
// @count - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[*]" 1
38+
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
39+
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.kind" '"resolved_path"'
40+
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.name" '"Fn"'
41+
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.inputs[0].kind" '"borrowed_ref"'
42+
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.inputs[0].inner.lifetime" "\"'b\""
43+
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.output.kind" '"borrowed_ref"'
44+
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.output.inner.lifetime" "\"'b\""
3645
pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32;
46+
47+
// @is - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.name" '"Send"'
48+
// @is - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.inner.name" '"Debug"'
49+
pub type WeirdOrder = Box<dyn Send + Debug>;

src/test/rustdoc-json/type/hrtb.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// ignore-tidy-linelength
12

23
// @has hrtb.json
34

@@ -14,9 +15,11 @@ where
1415
// @is - "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}'
1516
// @is - "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}'
1617
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].kind" '"borrowed_ref"'
17-
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].kind" '"borrowed_ref"'
18-
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.kind" '"resolved_path"'
19-
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.name" '"Fn"'
18+
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.kind" '"dyn_trait"'
19+
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.lifetime" null
20+
// @count - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[*]" 1
21+
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
22+
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].trait.inner.name" '"Fn"'
2023
pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) {
2124
let zero = 0;
2225
f(&zero, &zero);

0 commit comments

Comments
 (0)