Skip to content

Commit 8882dac

Browse files
authored
Rollup merge of rust-lang#137956 - compiler-errors:rtn-rustdoc, r=fmease
Add RTN support to rustdoc This adds support to rustdoc and rustdoc-json for rendering `(..)` RTN (return type notation) style generics. --- Cleaning `rustc_middle::ty::Ty` is not correct still, though, and ends up rendering a function like: ```rust pub fn foreign<T: Foreign<bar(..): Send>>() where <T as Foreign>::bar(..): 'static, T::bar(..): Sync, ``` Into this: ```rust pub fn foreign<T>() where T: Foreign, impl Future<Output = ()>: Send + 'static + Sync, ``` This is because `clean_middle_ty` doesn't actually have sufficient context about whether the RPITIT is in its "defining scope" or not, so we don't know if the type was originally written like `-> impl Trait` or with RTN like `T::method(..)`. Partially addresses rust-lang#123996 (i.e., HIR side, not middle::ty one)
2 parents f16ce2a + e3ac1fa commit 8882dac

File tree

10 files changed

+98
-32
lines changed

10 files changed

+98
-32
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

+39-30
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,9 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
14881488
// The only time this happens is if we're inside the rustdoc for Fn(),
14891489
// which only has one associated type, which is not a GAT, so whatever.
14901490
}
1491+
GenericArgs::ReturnTypeNotation => {
1492+
// Never move these.
1493+
}
14911494
}
14921495
bounds.extend(mem::take(pred_bounds));
14931496
false
@@ -2553,36 +2556,42 @@ fn clean_generic_args<'tcx>(
25532556
generic_args: &hir::GenericArgs<'tcx>,
25542557
cx: &mut DocContext<'tcx>,
25552558
) -> GenericArgs {
2556-
// FIXME(return_type_notation): Fix RTN parens rendering
2557-
if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() {
2558-
let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect();
2559-
let output = match output.kind {
2560-
hir::TyKind::Tup(&[]) => None,
2561-
_ => Some(Box::new(clean_ty(output, cx))),
2562-
};
2563-
GenericArgs::Parenthesized { inputs, output }
2564-
} else {
2565-
let args = generic_args
2566-
.args
2567-
.iter()
2568-
.map(|arg| match arg {
2569-
hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => {
2570-
GenericArg::Lifetime(clean_lifetime(lt, cx))
2571-
}
2572-
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
2573-
hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty.as_unambig_ty(), cx)),
2574-
hir::GenericArg::Const(ct) => {
2575-
GenericArg::Const(Box::new(clean_const(ct.as_unambig_ct(), cx)))
2576-
}
2577-
hir::GenericArg::Infer(_inf) => GenericArg::Infer,
2578-
})
2579-
.collect();
2580-
let constraints = generic_args
2581-
.constraints
2582-
.iter()
2583-
.map(|c| clean_assoc_item_constraint(c, cx))
2584-
.collect::<ThinVec<_>>();
2585-
GenericArgs::AngleBracketed { args, constraints }
2559+
match generic_args.parenthesized {
2560+
hir::GenericArgsParentheses::No => {
2561+
let args = generic_args
2562+
.args
2563+
.iter()
2564+
.map(|arg| match arg {
2565+
hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => {
2566+
GenericArg::Lifetime(clean_lifetime(lt, cx))
2567+
}
2568+
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
2569+
hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty.as_unambig_ty(), cx)),
2570+
hir::GenericArg::Const(ct) => {
2571+
GenericArg::Const(Box::new(clean_const(ct.as_unambig_ct(), cx)))
2572+
}
2573+
hir::GenericArg::Infer(_inf) => GenericArg::Infer,
2574+
})
2575+
.collect();
2576+
let constraints = generic_args
2577+
.constraints
2578+
.iter()
2579+
.map(|c| clean_assoc_item_constraint(c, cx))
2580+
.collect::<ThinVec<_>>();
2581+
GenericArgs::AngleBracketed { args, constraints }
2582+
}
2583+
hir::GenericArgsParentheses::ParenSugar => {
2584+
let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() else {
2585+
bug!();
2586+
};
2587+
let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect();
2588+
let output = match output.kind {
2589+
hir::TyKind::Tup(&[]) => None,
2590+
_ => Some(Box::new(clean_ty(output, cx))),
2591+
};
2592+
GenericArgs::Parenthesized { inputs, output }
2593+
}
2594+
hir::GenericArgsParentheses::ReturnTypeNotation => GenericArgs::ReturnTypeNotation,
25862595
}
25872596
}
25882597

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
@@ -2259,8 +2259,12 @@ impl GenericArg {
22592259

22602260
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
22612261
pub(crate) enum GenericArgs {
2262+
/// `<args, constraints = ..>`
22622263
AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2264+
/// `(inputs) -> output`
22632265
Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2266+
/// `(..)`
2267+
ReturnTypeNotation,
22642268
}
22652269

22662270
impl GenericArgs {
@@ -2270,6 +2274,7 @@ impl GenericArgs {
22702274
args.is_empty() && constraints.is_empty()
22712275
}
22722276
GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2277+
GenericArgs::ReturnTypeNotation => false,
22732278
}
22742279
}
22752280
pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
@@ -2294,6 +2299,7 @@ impl GenericArgs {
22942299
})
22952300
.into_iter(),
22962301
),
2302+
GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
22972303
}
22982304
}
22992305
}
@@ -2305,8 +2311,10 @@ impl<'a> IntoIterator for &'a GenericArgs {
23052311
match self {
23062312
GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
23072313
GenericArgs::Parenthesized { inputs, .. } => {
2314+
// FIXME: This isn't really right, since `Fn(A, B)` is `Fn<(A, B)>`
23082315
Box::new(inputs.iter().cloned().map(GenericArg::Type))
23092316
}
2317+
GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
23102318
}
23112319
}
23122320
}

src/librustdoc/html/format.rs

+3
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,9 @@ impl clean::GenericArgs {
332332
}
333333
}
334334
}
335+
clean::GenericArgs::ReturnTypeNotation => {
336+
f.write_str("(..)")?;
337+
}
335338
}
336339
Ok(())
337340
})

src/librustdoc/json/conversions.rs

+1
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ impl FromClean<clean::GenericArgs> for GenericArgs {
176176
inputs: inputs.into_json(renderer),
177177
output: output.map(|a| (*a).into_json(renderer)),
178178
},
179+
ReturnTypeNotation => GenericArgs::ReturnTypeNotation,
179180
}
180181
}
181182
}

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 = 41;
33+
pub const FORMAT_VERSION: u32 = 42;
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)