mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Rollup merge of #58203 - euclio:rustdoc-async, r=GuillaumeGomez
rustdoc: display sugared return types for async functions Fixes #58027.
This commit is contained in:
commit
cdbd07cc40
@ -1724,6 +1724,30 @@ impl FnDecl {
|
||||
pub fn self_type(&self) -> Option<SelfTy> {
|
||||
self.inputs.values.get(0).and_then(|v| v.to_self())
|
||||
}
|
||||
|
||||
/// Returns the sugared return type for an async function.
|
||||
///
|
||||
/// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
|
||||
/// will return `i32`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if the return type does not match the expected sugaring for async
|
||||
/// functions.
|
||||
pub fn sugared_async_return_type(&self) -> FunctionRetTy {
|
||||
match &self.output {
|
||||
FunctionRetTy::Return(Type::ImplTrait(bounds)) => {
|
||||
match &bounds[0] {
|
||||
GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
|
||||
let bindings = trait_.bindings().unwrap();
|
||||
FunctionRetTy::Return(bindings[0].ty.clone())
|
||||
}
|
||||
_ => panic!("unexpected desugaring of async function"),
|
||||
}
|
||||
}
|
||||
_ => panic!("unexpected desugaring of async function"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
@ -2282,6 +2306,21 @@ impl Type {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bindings(&self) -> Option<&[TypeBinding]> {
|
||||
match *self {
|
||||
ResolvedPath { ref path, .. } => {
|
||||
path.segments.last().and_then(|seg| {
|
||||
if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
|
||||
Some(&**bindings)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetDefId for Type {
|
||||
|
@ -5,6 +5,7 @@
|
||||
//! assume that HTML output is desired, although it may be possible to redesign
|
||||
//! them in the future to instead emit any format desired.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
|
||||
use rustc::hir::def_id::DefId;
|
||||
@ -44,14 +45,16 @@ pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]);
|
||||
pub struct CommaSep<'a, T: 'a>(pub &'a [T]);
|
||||
pub struct AbiSpace(pub Abi);
|
||||
|
||||
/// Wrapper struct for properly emitting a method declaration.
|
||||
pub struct Method<'a> {
|
||||
/// Wrapper struct for properly emitting a function or method declaration.
|
||||
pub struct Function<'a> {
|
||||
/// The declaration to emit.
|
||||
pub decl: &'a clean::FnDecl,
|
||||
/// The length of the function's "name", used to determine line-wrapping.
|
||||
pub name_len: usize,
|
||||
/// The number of spaces to indent each successive line with, if line-wrapping is necessary.
|
||||
pub indent: usize,
|
||||
/// Whether the function is async or not.
|
||||
pub asyncness: hir::IsAsync,
|
||||
}
|
||||
|
||||
/// Wrapper struct for emitting a where clause from Generics.
|
||||
@ -829,9 +832,9 @@ impl fmt::Display for clean::FnDecl {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for Method<'a> {
|
||||
impl<'a> fmt::Display for Function<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let &Method { decl, name_len, indent } = self;
|
||||
let &Function { decl, name_len, indent, asyncness } = self;
|
||||
let amp = if f.alternate() { "&" } else { "&" };
|
||||
let mut args = String::new();
|
||||
let mut args_plain = String::new();
|
||||
@ -891,11 +894,17 @@ impl<'a> fmt::Display for Method<'a> {
|
||||
args_plain.push_str(", ...");
|
||||
}
|
||||
|
||||
let arrow_plain = format!("{:#}", decl.output);
|
||||
let arrow = if f.alternate() {
|
||||
format!("{:#}", decl.output)
|
||||
let output = if let hir::IsAsync::Async = asyncness {
|
||||
Cow::Owned(decl.sugared_async_return_type())
|
||||
} else {
|
||||
decl.output.to_string()
|
||||
Cow::Borrowed(&decl.output)
|
||||
};
|
||||
|
||||
let arrow_plain = format!("{:#}", &output);
|
||||
let arrow = if f.alternate() {
|
||||
format!("{:#}", &output)
|
||||
} else {
|
||||
output.to_string()
|
||||
};
|
||||
|
||||
let pad = " ".repeat(name_len);
|
||||
|
@ -62,7 +62,7 @@ use fold::DocFolder;
|
||||
use html::escape::Escape;
|
||||
use html::format::{AsyncSpace, ConstnessSpace};
|
||||
use html::format::{GenericBounds, WhereClause, href, AbiSpace};
|
||||
use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
|
||||
use html::format::{VisSpace, Function, UnsafetySpace, MutableSpace};
|
||||
use html::format::fmt_impl_for_trait_page;
|
||||
use html::item_type::ItemType;
|
||||
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,
|
||||
name = it.name.as_ref().unwrap(),
|
||||
generics = f.generics,
|
||||
where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true },
|
||||
decl = Method {
|
||||
decl = Function {
|
||||
decl: &f.decl,
|
||||
name_len,
|
||||
indent: 0,
|
||||
asyncness: f.header.asyncness,
|
||||
})?;
|
||||
document(w, cx, it)
|
||||
}
|
||||
@ -3424,10 +3425,11 @@ fn render_assoc_item(w: &mut fmt::Formatter,
|
||||
href = href,
|
||||
name = name,
|
||||
generics = *g,
|
||||
decl = Method {
|
||||
decl = Function {
|
||||
decl: d,
|
||||
name_len: head_len,
|
||||
indent,
|
||||
asyncness: header.asyncness,
|
||||
},
|
||||
where_clause = WhereClause {
|
||||
gens: g,
|
||||
|
@ -1,14 +1,35 @@
|
||||
// edition:2018
|
||||
// compile-flags:-Z unstable-options
|
||||
|
||||
// FIXME: once `--edition` is stable in rustdoc, remove that `compile-flags` directive
|
||||
|
||||
#![feature(async_await, futures_api)]
|
||||
|
||||
// @has async_fn/struct.S.html
|
||||
// @has - '//code' 'pub async fn f()'
|
||||
pub struct S;
|
||||
// @has async_fn/fn.foo.html '//pre[@class="rust fn"]' 'pub async fn foo() -> Option<Foo>'
|
||||
pub async fn foo() -> Option<Foo> {
|
||||
None
|
||||
}
|
||||
|
||||
impl S {
|
||||
// @has async_fn/fn.bar.html '//pre[@class="rust fn"]' 'pub async fn bar(a: i32, b: i32) -> i32'
|
||||
pub async fn bar(a: i32, b: i32) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
// @has async_fn/fn.baz.html '//pre[@class="rust fn"]' 'pub async fn baz<T>(a: T) -> T'
|
||||
pub async fn baz<T>(a: T) -> T {
|
||||
a
|
||||
}
|
||||
|
||||
trait Bar {}
|
||||
|
||||
impl Bar for () {}
|
||||
|
||||
// @has async_fn/fn.quux.html '//pre[@class="rust fn"]' 'pub async fn quux() -> impl Bar'
|
||||
pub async fn quux() -> impl Bar {
|
||||
()
|
||||
}
|
||||
|
||||
// @has async_fn/struct.Foo.html
|
||||
// @matches - '//code' 'pub async fn f\(\)$'
|
||||
pub struct Foo;
|
||||
|
||||
impl Foo {
|
||||
pub async fn f() {}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user