Skip to content

Commit cdbd07c

Browse files
authoredFeb 10, 2019
Rollup merge of rust-lang#58203 - euclio:rustdoc-async, r=GuillaumeGomez
rustdoc: display sugared return types for async functions Fixes rust-lang#58027.
2 parents a74e4f7 + 4deb595 commit cdbd07c

File tree

4 files changed

+88
-17
lines changed

4 files changed

+88
-17
lines changed
 

‎src/librustdoc/clean/mod.rs

+39
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,30 @@ impl FnDecl {
17241724
pub fn self_type(&self) -> Option<SelfTy> {
17251725
self.inputs.values.get(0).and_then(|v| v.to_self())
17261726
}
1727+
1728+
/// Returns the sugared return type for an async function.
1729+
///
1730+
/// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1731+
/// will return `i32`.
1732+
///
1733+
/// # Panics
1734+
///
1735+
/// This function will panic if the return type does not match the expected sugaring for async
1736+
/// functions.
1737+
pub fn sugared_async_return_type(&self) -> FunctionRetTy {
1738+
match &self.output {
1739+
FunctionRetTy::Return(Type::ImplTrait(bounds)) => {
1740+
match &bounds[0] {
1741+
GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1742+
let bindings = trait_.bindings().unwrap();
1743+
FunctionRetTy::Return(bindings[0].ty.clone())
1744+
}
1745+
_ => panic!("unexpected desugaring of async function"),
1746+
}
1747+
}
1748+
_ => panic!("unexpected desugaring of async function"),
1749+
}
1750+
}
17271751
}
17281752

17291753
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
@@ -2282,6 +2306,21 @@ impl Type {
22822306
_ => None,
22832307
}
22842308
}
2309+
2310+
pub fn bindings(&self) -> Option<&[TypeBinding]> {
2311+
match *self {
2312+
ResolvedPath { ref path, .. } => {
2313+
path.segments.last().and_then(|seg| {
2314+
if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
2315+
Some(&**bindings)
2316+
} else {
2317+
None
2318+
}
2319+
})
2320+
}
2321+
_ => None
2322+
}
2323+
}
22852324
}
22862325

22872326
impl GetDefId for Type {

‎src/librustdoc/html/format.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//! assume that HTML output is desired, although it may be possible to redesign
66
//! them in the future to instead emit any format desired.
77
8+
use std::borrow::Cow;
89
use std::fmt;
910

1011
use rustc::hir::def_id::DefId;
@@ -44,14 +45,16 @@ pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]);
4445
pub struct CommaSep<'a, T: 'a>(pub &'a [T]);
4546
pub struct AbiSpace(pub Abi);
4647

47-
/// Wrapper struct for properly emitting a method declaration.
48-
pub struct Method<'a> {
48+
/// Wrapper struct for properly emitting a function or method declaration.
49+
pub struct Function<'a> {
4950
/// The declaration to emit.
5051
pub decl: &'a clean::FnDecl,
5152
/// The length of the function's "name", used to determine line-wrapping.
5253
pub name_len: usize,
5354
/// The number of spaces to indent each successive line with, if line-wrapping is necessary.
5455
pub indent: usize,
56+
/// Whether the function is async or not.
57+
pub asyncness: hir::IsAsync,
5558
}
5659

5760
/// Wrapper struct for emitting a where clause from Generics.
@@ -829,9 +832,9 @@ impl fmt::Display for clean::FnDecl {
829832
}
830833
}
831834

832-
impl<'a> fmt::Display for Method<'a> {
835+
impl<'a> fmt::Display for Function<'a> {
833836
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
834-
let &Method { decl, name_len, indent } = self;
837+
let &Function { decl, name_len, indent, asyncness } = self;
835838
let amp = if f.alternate() { "&" } else { "&amp;" };
836839
let mut args = String::new();
837840
let mut args_plain = String::new();
@@ -891,11 +894,17 @@ impl<'a> fmt::Display for Method<'a> {
891894
args_plain.push_str(", ...");
892895
}
893896

894-
let arrow_plain = format!("{:#}", decl.output);
897+
let output = if let hir::IsAsync::Async = asyncness {
898+
Cow::Owned(decl.sugared_async_return_type())
899+
} else {
900+
Cow::Borrowed(&decl.output)
901+
};
902+
903+
let arrow_plain = format!("{:#}", &output);
895904
let arrow = if f.alternate() {
896-
format!("{:#}", decl.output)
905+
format!("{:#}", &output)
897906
} else {
898-
decl.output.to_string()
907+
output.to_string()
899908
};
900909

901910
let pad = " ".repeat(name_len);

‎src/librustdoc/html/render.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ use fold::DocFolder;
6262
use html::escape::Escape;
6363
use html::format::{AsyncSpace, ConstnessSpace};
6464
use html::format::{GenericBounds, WhereClause, href, AbiSpace};
65-
use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
65+
use html::format::{VisSpace, Function, UnsafetySpace, MutableSpace};
6666
use html::format::fmt_impl_for_trait_page;
6767
use html::item_type::ItemType;
6868
use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes, IdMap};
@@ -2977,10 +2977,11 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
29772977
name = it.name.as_ref().unwrap(),
29782978
generics = f.generics,
29792979
where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true },
2980-
decl = Method {
2980+
decl = Function {
29812981
decl: &f.decl,
29822982
name_len,
29832983
indent: 0,
2984+
asyncness: f.header.asyncness,
29842985
})?;
29852986
document(w, cx, it)
29862987
}
@@ -3424,10 +3425,11 @@ fn render_assoc_item(w: &mut fmt::Formatter,
34243425
href = href,
34253426
name = name,
34263427
generics = *g,
3427-
decl = Method {
3428+
decl = Function {
34283429
decl: d,
34293430
name_len: head_len,
34303431
indent,
3432+
asyncness: header.asyncness,
34313433
},
34323434
where_clause = WhereClause {
34333435
gens: g,

‎src/test/rustdoc/async-fn.rs

+28-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,35 @@
11
// edition:2018
2-
// compile-flags:-Z unstable-options
3-
4-
// FIXME: once `--edition` is stable in rustdoc, remove that `compile-flags` directive
52

63
#![feature(async_await, futures_api)]
74

8-
// @has async_fn/struct.S.html
9-
// @has - '//code' 'pub async fn f()'
10-
pub struct S;
5+
// @has async_fn/fn.foo.html '//pre[@class="rust fn"]' 'pub async fn foo() -> Option<Foo>'
6+
pub async fn foo() -> Option<Foo> {
7+
None
8+
}
9+
10+
// @has async_fn/fn.bar.html '//pre[@class="rust fn"]' 'pub async fn bar(a: i32, b: i32) -> i32'
11+
pub async fn bar(a: i32, b: i32) -> i32 {
12+
0
13+
}
14+
15+
// @has async_fn/fn.baz.html '//pre[@class="rust fn"]' 'pub async fn baz<T>(a: T) -> T'
16+
pub async fn baz<T>(a: T) -> T {
17+
a
18+
}
19+
20+
trait Bar {}
21+
22+
impl Bar for () {}
23+
24+
// @has async_fn/fn.quux.html '//pre[@class="rust fn"]' 'pub async fn quux() -> impl Bar'
25+
pub async fn quux() -> impl Bar {
26+
()
27+
}
28+
29+
// @has async_fn/struct.Foo.html
30+
// @matches - '//code' 'pub async fn f\(\)$'
31+
pub struct Foo;
1132

12-
impl S {
33+
impl Foo {
1334
pub async fn f() {}
1435
}

0 commit comments

Comments
 (0)
Please sign in to comment.