diff options
| author | Justus K <justus.k@protonmail.com> | 2021-05-18 10:06:24 +0200 |
|---|---|---|
| committer | Justus K <justus.k@protonmail.com> | 2021-06-18 21:58:09 +0200 |
| commit | 1f65f56461fa72df809fff43975a7e72f08fda44 (patch) | |
| tree | 3467d490de695f02614249f972a3eba12651738a | |
| parent | e0162a8a56d1c59e185e293f33c38d94a5a2d462 (diff) | |
| download | rust-1f65f56461fa72df809fff43975a7e72f08fda44.tar.gz rust-1f65f56461fa72df809fff43975a7e72f08fda44.zip | |
rustdoc: Render `for<'_>` lifetimes in trait objects
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 21 | ||||
| -rw-r--r-- | src/librustdoc/clean/types.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/html/format.rs | 29 | ||||
| -rw-r--r-- | src/librustdoc/json/conversions.rs | 2 | ||||
| -rw-r--r-- | src/test/rustdoc/for-lifetime.rs | 12 | ||||
| -rw-r--r-- | src/test/rustdoc/higher-ranked-trait-bounds.rs | 22 |
6 files changed, 61 insertions, 29 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 634a8dae763..889e645309c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1378,8 +1378,9 @@ impl Clean<Type> for hir::Ty<'_> { } TyKind::Path(_) => clean_qpath(&self, cx), TyKind::TraitObject(ref bounds, ref lifetime, _) => { - match bounds[0].clean(cx).trait_ { - ResolvedPath { path, param_names: None, did, is_generic } => { + let cleaned = bounds[0].clean(cx); + match cleaned.trait_ { + ResolvedPath { path, param_names: None, did, is_generic, .. } => { let mut bounds: Vec<self::GenericBound> = bounds[1..] .iter() .map(|bound| { @@ -1392,7 +1393,12 @@ impl Clean<Type> for hir::Ty<'_> { if !lifetime.is_elided() { bounds.push(self::GenericBound::Outlives(lifetime.clean(cx))); } - ResolvedPath { path, param_names: Some(bounds), did, is_generic } + ResolvedPath { + path, + param_names: Some((bounds, cleaned.generic_params)), + did, + is_generic, + } } _ => Infer, // shouldn't happen } @@ -1542,7 +1548,12 @@ impl<'tcx> Clean<Type> for Ty<'tcx> { let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs); - ResolvedPath { path, param_names: Some(param_names), did, is_generic: false } + ResolvedPath { + path, + param_names: Some((param_names, vec![])), + did, + is_generic: false, + } } ty::Tuple(ref t) => { Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx)) @@ -2248,7 +2259,7 @@ impl From<GenericBound> for SimpleBound { GenericBound::TraitBound(t, mod_) => match t.trait_ { Type::ResolvedPath { path, param_names, .. } => SimpleBound::TraitBound( path.segments, - param_names.map_or_else(Vec::new, |v| { + param_names.map_or_else(Vec::new, |(v, _)| { v.iter().map(|p| SimpleBound::from(p.clone())).collect() }), t.generic_params, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5d036d4d35b..4c94501b80b 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1407,7 +1407,9 @@ crate enum Type { /// Structs/enums/traits (most that would be an `hir::TyKind::Path`). ResolvedPath { path: Path, - param_names: Option<Vec<GenericBound>>, + /// If `param_names` is `Some`, this path is a trait object and the Vecs repsresent + /// `(generic bounds, generic parameters)` + param_names: Option<(Vec<GenericBound>, Vec<GenericParamDef>)>, did: DefId, /// `true` if is a `T::Name` path for associated types. is_generic: bool, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index a424932d83f..e4fb7384aff 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -646,11 +646,11 @@ fn primitive_link( /// Helper to render type parameters fn tybounds<'a, 'tcx: 'a>( - param_names: &'a Option<Vec<clean::GenericBound>>, + param_names: Option<&'a Vec<clean::GenericBound>>, cx: &'a Context<'tcx>, ) -> impl fmt::Display + 'a + Captures<'tcx> { - display_fn(move |f| match *param_names { - Some(ref params) => { + display_fn(move |f| match param_names { + Some(params) => { for param in params { write!(f, " + ")?; fmt::Display::fmt(¶m.print(cx), f)?; @@ -695,8 +695,27 @@ fn fmt_type<'cx>( match *t { clean::Generic(name) => write!(f, "{}", name), clean::ResolvedPath { did, ref param_names, ref path, is_generic } => { - if param_names.is_some() { + let generic_params = param_names.as_ref().map(|(_, x)| x); + let param_names = param_names.as_ref().map(|(x, _)| x); + + if let Some(generic_params) = generic_params { f.write_str("dyn ")?; + + if !generic_params.is_empty() { + if f.alternate() { + write!( + f, + "for<{:#}> ", + comma_sep(generic_params.iter().map(|g| g.print(cx))) + )?; + } else { + write!( + f, + "for<{}> ", + comma_sep(generic_params.iter().map(|g| g.print(cx))) + )?; + } + } } // Paths like `T::Output` and `Self::Output` should be rendered with all segments. resolved_path(f, did, path, is_generic, use_absolute, cx)?; @@ -835,7 +854,7 @@ fn fmt_type<'cx>( } } } - clean::ResolvedPath { param_names: Some(ref v), .. } if !v.is_empty() => { + clean::ResolvedPath { param_names: Some((ref v, _)), .. } if !v.is_empty() => { write!(f, "{}{}{}(", amp, lt, m)?; fmt_type(&ty, f, use_absolute, cx)?; write!(f, ")") diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index c844d91096a..643c0f82ae9 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -378,7 +378,7 @@ impl FromWithTcx<clean::Type> for Type { id: from_def_id(did.into()), args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))), param_names: param_names - .map(|v| v.into_iter().map(|x| x.into_tcx(tcx)).collect()) + .map(|(v, _)| v.into_iter().map(|x| x.into_tcx(tcx)).collect()) .unwrap_or_default(), }, Generic(s) => Type::Generic(s.to_string()), diff --git a/src/test/rustdoc/for-lifetime.rs b/src/test/rustdoc/for-lifetime.rs deleted file mode 100644 index 34a7eae31c7..00000000000 --- a/src/test/rustdoc/for-lifetime.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![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> {} diff --git a/src/test/rustdoc/higher-ranked-trait-bounds.rs b/src/test/rustdoc/higher-ranked-trait-bounds.rs index b5c55df287b..492a743fbf2 100644 --- a/src/test/rustdoc/higher-ranked-trait-bounds.rs +++ b/src/test/rustdoc/higher-ranked-trait-bounds.rs @@ -1,6 +1,7 @@ #![crate_name = "foo"] -trait A<'x> {} +// @has foo/trait.Trait.html +pub trait Trait<'x> {} // @has foo/fn.test1.html // @has - '//pre' "pub fn test1<T>() where for<'a> &'a T: Iterator," @@ -11,10 +12,10 @@ where } // @has foo/fn.test2.html -// @has - '//pre' "pub fn test2<T>() where for<'a, 'b> &'a T: A<'b>," +// @has - '//pre' "pub fn test2<T>() where for<'a, 'b> &'a T: Trait<'b>," pub fn test2<T>() where - for<'a, 'b> &'a T: A<'b>, + for<'a, 'b> &'a T: Trait<'b>, { } @@ -29,13 +30,24 @@ where // @has foo/struct.Foo.html pub struct Foo<'a> { _x: &'a u8, + pub some_trait: &'a dyn for<'b> Trait<'b>, + pub some_func: for<'c> fn(val: &'c i32) -> i32, } +// @has - '//span[@id="structfield.some_func"]' "some_func: for<'c> fn(val: &'c i32) -> i32" +// @has - '//span[@id="structfield.some_trait"]' "some_trait: &'a dyn for<'b> Trait<'b>" + impl<'a> Foo<'a> { - // @has - '//code' "pub fn bar<T>() where T: A<'a>," + // @has - '//code' "pub fn bar<T>() where T: Trait<'a>," pub fn bar<T>() where - T: A<'a>, + T: Trait<'a>, { } } + +// @has foo/trait.B.html +pub trait B<'x> {} + +// @has - '//code[@class="in-band"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>" +impl<'a> B<'a> for dyn for<'b> Trait<'b> {} |
