diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 01915c33a07ad..74b61f1555c6f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -659,6 +659,8 @@ fn fmt_type( use_absolute: bool, cache: &Cache, ) -> fmt::Result { + debug!("fmt_type(t = {:?})", t); + match *t { clean::Generic(name) => write!(f, "{}", name), clean::ResolvedPath { did, ref param_names, ref path, is_generic } => { @@ -675,21 +677,22 @@ fn fmt_type( if f.alternate() { write!( f, - "{}{:#}fn{:#}{:#}", + "{:#}{}{:#}fn{:#}", + decl.print_hrtb_with_space(cache), decl.unsafety.print_with_space(), print_abi_with_space(decl.abi), - decl.print_generic_params(cache), decl.decl.print(cache) ) } else { write!( f, - "{}{}", + "{}{}{}", + decl.print_hrtb_with_space(cache), decl.unsafety.print_with_space(), print_abi_with_space(decl.abi) )?; primitive_link(f, PrimitiveType::Fn, "fn", cache)?; - write!(f, "{}{}", decl.print_generic_params(cache), decl.decl.print(cache)) + write!(f, "{}", decl.decl.print(cache)) } } clean::Tuple(ref typs) => { @@ -992,8 +995,14 @@ impl clean::FnRetTy { } impl clean::BareFunctionDecl { - fn print_generic_params<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { - comma_sep(self.generic_params.iter().map(move |g| g.print(cache))) + fn print_hrtb_with_space<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + display_fn(move |f| { + if !self.generic_params.is_empty() { + write!(f, "for<{}> ", comma_sep(self.generic_params.iter().map(|g| g.print(cache)))) + } else { + Ok(()) + } + }) } } diff --git a/src/test/rustdoc/fn-type.rs b/src/test/rustdoc/fn-type.rs new file mode 100644 index 0000000000000..f5e123aed9c47 --- /dev/null +++ b/src/test/rustdoc/fn-type.rs @@ -0,0 +1,15 @@ +// ignore-tidy-linelength + +#![crate_name = "foo"] +#![crate_type = "lib"] + +pub struct Foo<'a, T> { + pub generic: fn(val: &T) -> T, + + pub lifetime: fn(val: &'a i32) -> i32, + pub hrtb_lifetime: for<'b, 'c> fn(one: &'b i32, two: &'c &'b i32) -> (&'b i32, &'c i32), +} + +// @has 'foo/struct.Foo.html' '//span[@id="structfield.generic"]' "generic: fn(val: &T) -> T" +// @has 'foo/struct.Foo.html' '//span[@id="structfield.lifetime"]' "lifetime: fn(val: &'a i32) -> i32" +// @has 'foo/struct.Foo.html' '//span[@id="structfield.hrtb_lifetime"]' "hrtb_lifetime: for<'b, 'c> fn(one: &'b i32, two: &'c &'b i32) -> (&'b i32, &'c i32)" diff --git a/src/test/rustdoc/for-lifetime.rs b/src/test/rustdoc/for-lifetime.rs new file mode 100644 index 0000000000000..299794b63b2ea --- /dev/null +++ b/src/test/rustdoc/for-lifetime.rs @@ -0,0 +1,14 @@ +// ignore-tidy-linelength + +#![crate_name = "foo"] +#![crate_type = "lib"] + +pub struct Foo { + pub some_func: for<'a> fn(val: &'a i32) -> i32, + pub some_trait: dyn for<'a> Trait<'a>, +} + +// @has foo/struct.Foo.html '//span[@id="structfield.some_func"]' "some_func: for<'a> fn(val: &'a i32) -> i32" +// @has foo/struct.Foo.html '//span[@id="structfield.some_trait"]' "some_trait: dyn Trait<'a>" + +pub trait Trait<'a> {}