Skip to content

Commit c95ee4d

Browse files
Add RTN support to rustdoc
1 parent 81d8edc commit c95ee4d

File tree

10 files changed

+99
-33
lines changed

10 files changed

+99
-33
lines changed

compiler/rustc_hir_analysis/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
252252
// def-ID that will be used to determine the traits/predicates in
253253
// scope. This is derived from the enclosing item-like thing.
254254
let env_def_id = tcx.hir_get_parent_item(hir_ty.hir_id);
255-
collect::ItemCtxt::new(tcx, env_def_id.def_id).lower_ty(hir_ty)
255+
collect::ItemCtxt::new(tcx, env_def_id.def_id)
256+
.lowerer()
257+
.lower_ty_maybe_return_type_notation(hir_ty)
256258
}
257259

258260
/// This is for rustdoc.

src/librustdoc/clean/mod.rs

+40-31
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,9 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
14801480
// The only time this happens is if we're inside the rustdoc for Fn(),
14811481
// which only has one associated type, which is not a GAT, so whatever.
14821482
}
1483+
GenericArgs::ReturnTypeNotation => {
1484+
// Never move these.
1485+
}
14831486
}
14841487
bounds.extend(mem::take(pred_bounds));
14851488
false
@@ -2537,37 +2540,43 @@ fn clean_generic_args<'tcx>(
25372540
generic_args: &hir::GenericArgs<'tcx>,
25382541
cx: &mut DocContext<'tcx>,
25392542
) -> GenericArgs {
2540-
// FIXME(return_type_notation): Fix RTN parens rendering
2541-
if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() {
2542-
let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect::<ThinVec<_>>().into();
2543-
let output = match output.kind {
2544-
hir::TyKind::Tup(&[]) => None,
2545-
_ => Some(Box::new(clean_ty(output, cx))),
2546-
};
2547-
GenericArgs::Parenthesized { inputs, output }
2548-
} else {
2549-
let args = generic_args
2550-
.args
2551-
.iter()
2552-
.map(|arg| match arg {
2553-
hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => {
2554-
GenericArg::Lifetime(clean_lifetime(lt, cx))
2555-
}
2556-
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
2557-
hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty.as_unambig_ty(), cx)),
2558-
hir::GenericArg::Const(ct) => {
2559-
GenericArg::Const(Box::new(clean_const(ct.as_unambig_ct(), cx)))
2560-
}
2561-
hir::GenericArg::Infer(_inf) => GenericArg::Infer,
2562-
})
2563-
.collect::<ThinVec<_>>()
2564-
.into();
2565-
let constraints = generic_args
2566-
.constraints
2567-
.iter()
2568-
.map(|c| clean_assoc_item_constraint(c, cx))
2569-
.collect::<ThinVec<_>>();
2570-
GenericArgs::AngleBracketed { args, constraints }
2543+
match generic_args.parenthesized {
2544+
hir::GenericArgsParentheses::No => {
2545+
let args = generic_args
2546+
.args
2547+
.iter()
2548+
.map(|arg| match arg {
2549+
hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => {
2550+
GenericArg::Lifetime(clean_lifetime(lt, cx))
2551+
}
2552+
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
2553+
hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty.as_unambig_ty(), cx)),
2554+
hir::GenericArg::Const(ct) => {
2555+
GenericArg::Const(Box::new(clean_const(ct.as_unambig_ct(), cx)))
2556+
}
2557+
hir::GenericArg::Infer(_inf) => GenericArg::Infer,
2558+
})
2559+
.collect::<ThinVec<_>>()
2560+
.into();
2561+
let constraints = generic_args
2562+
.constraints
2563+
.iter()
2564+
.map(|c| clean_assoc_item_constraint(c, cx))
2565+
.collect::<ThinVec<_>>();
2566+
GenericArgs::AngleBracketed { args, constraints }
2567+
}
2568+
hir::GenericArgsParentheses::ParenSugar => {
2569+
let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() else {
2570+
bug!();
2571+
};
2572+
let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect::<ThinVec<_>>().into();
2573+
let output = match output.kind {
2574+
hir::TyKind::Tup(&[]) => None,
2575+
_ => Some(Box::new(clean_ty(output, cx))),
2576+
};
2577+
GenericArgs::Parenthesized { inputs, output }
2578+
}
2579+
hir::GenericArgsParentheses::ReturnTypeNotation => GenericArgs::ReturnTypeNotation,
25712580
}
25722581
}
25732582

src/librustdoc/clean/simplify.rs

+4
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ pub(crate) fn merge_bounds(
102102
}
103103
}
104104
},
105+
PP::ReturnTypeNotation => {
106+
// Cannot merge bounds with RTN.
107+
return false;
108+
}
105109
};
106110
true
107111
})

src/librustdoc/clean/types.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2246,8 +2246,12 @@ impl GenericArg {
22462246

22472247
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
22482248
pub(crate) enum GenericArgs {
2249+
/// `<args, constraints = ..>`
22492250
AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2251+
/// `(inputs) -> output`
22502252
Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2253+
/// `(..)`
2254+
ReturnTypeNotation,
22512255
}
22522256

22532257
impl GenericArgs {
@@ -2257,6 +2261,7 @@ impl GenericArgs {
22572261
args.is_empty() && constraints.is_empty()
22582262
}
22592263
GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2264+
GenericArgs::ReturnTypeNotation => false,
22602265
}
22612266
}
22622267
pub(crate) fn constraints<'a>(&'a self) -> Box<dyn Iterator<Item = AssocItemConstraint> + 'a> {
@@ -2281,6 +2286,7 @@ impl GenericArgs {
22812286
})
22822287
.into_iter(),
22832288
),
2289+
GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
22842290
}
22852291
}
22862292
}
@@ -2292,8 +2298,10 @@ impl<'a> IntoIterator for &'a GenericArgs {
22922298
match self {
22932299
GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
22942300
GenericArgs::Parenthesized { inputs, .. } => {
2301+
// FIXME: This isn't really right, since `Fn(A, B)` is `Fn<(A, B)>`
22952302
Box::new(inputs.iter().cloned().map(GenericArg::Type))
22962303
}
2304+
GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
22972305
}
22982306
}
22992307
}

src/librustdoc/html/format.rs

+3
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,9 @@ impl clean::GenericArgs {
345345
}
346346
}
347347
}
348+
clean::GenericArgs::ReturnTypeNotation => {
349+
f.write_str("(..)")?;
350+
}
348351
}
349352
Ok(())
350353
})

src/librustdoc/json/conversions.rs

+1
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ impl FromClean<clean::GenericArgs> for GenericArgs {
238238
inputs: inputs.into_json(renderer),
239239
output: output.map(|a| (*a).into_json(renderer)),
240240
},
241+
ReturnTypeNotation => GenericArgs::ReturnTypeNotation,
241242
}
242243
}
243244
}

src/rustdoc-json-types/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
3030
/// This integer is incremented with every breaking change to the API,
3131
/// and is returned along with the JSON blob as [`Crate::format_version`].
3232
/// Consuming code should assert that this value matches the format version(s) that it supports.
33-
pub const FORMAT_VERSION: u32 = 40;
33+
pub const FORMAT_VERSION: u32 = 41;
3434

3535
/// The root of the emitted JSON blob.
3636
///
@@ -229,6 +229,8 @@ pub enum GenericArgs {
229229
/// The output type provided after the `->`, if present.
230230
output: Option<Type>,
231231
},
232+
/// `T::method(..)`
233+
ReturnTypeNotation,
232234
}
233235

234236
/// One argument in a list of generic arguments to a path segment.

src/tools/jsondoclint/src/validator.rs

+1
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ impl<'a> Validator<'a> {
326326
self.check_type(o);
327327
}
328328
}
329+
GenericArgs::ReturnTypeNotation => {}
329330
}
330331
}
331332

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//@ edition: 2021
2+
// ignore-tidy-linelength
3+
4+
#![crate_type = "lib"]
5+
#![feature(return_type_notation)]
6+
7+
pub trait Foo {
8+
async fn bar();
9+
}
10+
11+
//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.args.angle_bracketed.constraints[0].args" '"return_type_notation"'
12+
//@ ismany "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[*].bound_predicate.type.qualified_path.args" '"return_type_notation"' '"return_type_notation"'
13+
pub fn foo<T: Foo<bar(..): Send>>()
14+
where
15+
<T as Foo>::bar(..): 'static,
16+
T::bar(..): Sync,
17+
{
18+
}

tests/rustdoc/return-type-notation.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//@ edition: 2021
2+
3+
#![crate_type = "lib"]
4+
#![feature(return_type_notation)]
5+
6+
pub trait Foo {
7+
async fn bar();
8+
}
9+
10+
//@ has "return_type_notation/fn.foo.html"
11+
//@ has - '//pre[@class="rust item-decl"]' "pub fn foo<T: Foo<bar(..): Send>>()"
12+
//@ has - '//pre[@class="rust item-decl"]' "where <T as Foo>::bar(..): 'static, T::bar(..): Sync"
13+
pub fn foo<T: Foo<bar(..): Send>>()
14+
where
15+
<T as Foo>::bar(..): 'static,
16+
T::bar(..): Sync,
17+
{
18+
}

0 commit comments

Comments
 (0)