about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2020-08-08 11:36:03 +0900
committerGitHub <noreply@github.com>2020-08-08 11:36:03 +0900
commit255434d83cab2dab5ab5c7d942a5dbfcda3db894 (patch)
tree4c5e58c791bbd52482f65f5733e168ec396e6d2d
parentf5d2ffd7fb94807555cc370eb0ec01822f04abe3 (diff)
parent541fbbb6fab4afdeea48fdb9e94cee48991b3333 (diff)
downloadrust-255434d83cab2dab5ab5c7d942a5dbfcda3db894.tar.gz
rust-255434d83cab2dab5ab5c7d942a5dbfcda3db894.zip
Rollup merge of #75237 - nbdd0121:rustdoc, r=jyn514
Display elided lifetime for non-reference type in doc

In edition 2018 we encourage writing `<'_>` explicitly, so rustdoc should display like such as well.

Fixes #75225

~~Somehow when I run the compiled rustdoc using `cargo +stage2 doc` on other crates, it correctly produces `<'_>`, but I couldn't get the std doc to do the same with `./x.py doc --stage 2`. Might this be related to the recent change to x.py about how the doc is built?~~
-rw-r--r--src/librustdoc/clean/mod.rs27
-rw-r--r--src/librustdoc/clean/types.rs4
-rw-r--r--src/librustdoc/clean/utils.rs11
-rw-r--r--src/test/rustdoc/auxiliary/elided-lifetime.rs11
-rw-r--r--src/test/rustdoc/elided-lifetime.rs43
5 files changed, 78 insertions, 18 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2a090d6efa5..7b1dd5b11ed 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1395,10 +1395,13 @@ impl Clean<Type> for hir::Ty<'_> {
                                             _ => None,
                                         });
                                     if let Some(lt) = lifetime.cloned() {
-                                        if !lt.is_elided() {
-                                            let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                            lt_substs.insert(lt_def_id.to_def_id(), lt.clean(cx));
-                                        }
+                                        let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                                        let cleaned = if !lt.is_elided() {
+                                            lt.clean(cx)
+                                        } else {
+                                            self::types::Lifetime::elided()
+                                        };
+                                        lt_substs.insert(lt_def_id.to_def_id(), cleaned);
                                     }
                                     indices.lifetimes += 1;
                                 }
@@ -1957,21 +1960,17 @@ impl Clean<GenericArgs> for hir::GenericArgs<'_> {
                 output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None },
             }
         } else {
-            let elide_lifetimes = self.args.iter().all(|arg| match arg {
-                hir::GenericArg::Lifetime(lt) => lt.is_elided(),
-                _ => true,
-            });
             GenericArgs::AngleBracketed {
                 args: self
                     .args
                     .iter()
-                    .filter_map(|arg| match arg {
-                        hir::GenericArg::Lifetime(lt) if !elide_lifetimes => {
-                            Some(GenericArg::Lifetime(lt.clean(cx)))
+                    .map(|arg| match arg {
+                        hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
+                            GenericArg::Lifetime(lt.clean(cx))
                         }
-                        hir::GenericArg::Lifetime(_) => None,
-                        hir::GenericArg::Type(ty) => Some(GenericArg::Type(ty.clean(cx))),
-                        hir::GenericArg::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
+                        hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
+                        hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
+                        hir::GenericArg::Const(ct) => GenericArg::Const(ct.clean(cx)),
                     })
                     .collect(),
                 bindings: self.bindings.clean(cx),
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 44dd329d9ce..50eca75d7ca 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -750,6 +750,10 @@ impl Lifetime {
     pub fn statik() -> Lifetime {
         Lifetime("'static".to_string())
     }
+
+    pub fn elided() -> Lifetime {
+        Lifetime("'_".to_string())
+    }
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 069d333de18..c22538f21f6 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -2,9 +2,9 @@ use crate::clean::auto_trait::AutoTraitFinder;
 use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::{
     inline, Clean, Crate, Deprecation, ExternalCrate, FnDecl, FnRetTy, Generic, GenericArg,
-    GenericArgs, GenericBound, Generics, GetDefId, ImportSource, Item, ItemEnum, MacroKind, Path,
-    PathSegment, Primitive, PrimitiveType, ResolvedPath, Span, Stability, Type, TypeBinding,
-    TypeKind, Visibility, WherePredicate,
+    GenericArgs, GenericBound, Generics, GetDefId, ImportSource, Item, ItemEnum, Lifetime,
+    MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Span, Stability, Type,
+    TypeBinding, TypeKind, Visibility, WherePredicate,
 };
 use crate::core::DocContext;
 
@@ -121,7 +121,10 @@ pub fn external_generic_args(
     let args: Vec<_> = substs
         .iter()
         .filter_map(|kind| match kind.unpack() {
-            GenericArgKind::Lifetime(lt) => lt.clean(cx).map(GenericArg::Lifetime),
+            GenericArgKind::Lifetime(lt) => match lt {
+                ty::ReLateBound(_, ty::BrAnon(_)) => Some(GenericArg::Lifetime(Lifetime::elided())),
+                _ => lt.clean(cx).map(GenericArg::Lifetime),
+            },
             GenericArgKind::Type(_) if skip_self => {
                 skip_self = false;
                 None
diff --git a/src/test/rustdoc/auxiliary/elided-lifetime.rs b/src/test/rustdoc/auxiliary/elided-lifetime.rs
new file mode 100644
index 00000000000..4f2c93379d8
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/elided-lifetime.rs
@@ -0,0 +1,11 @@
+#![crate_name = "bar"]
+
+pub struct Ref<'a>(&'a u32);
+
+pub fn test5(a: &u32) -> Ref {
+    Ref(a)
+}
+
+pub fn test6(a: &u32) -> Ref<'_> {
+    Ref(a)
+}
diff --git a/src/test/rustdoc/elided-lifetime.rs b/src/test/rustdoc/elided-lifetime.rs
new file mode 100644
index 00000000000..5a32554f972
--- /dev/null
+++ b/src/test/rustdoc/elided-lifetime.rs
@@ -0,0 +1,43 @@
+// aux-build:elided-lifetime.rs
+//
+// rust-lang/rust#75225
+//
+// Since Rust 2018 we encourage writing out <'_> explicitly to make it clear
+// that borrowing is occuring. Make sure rustdoc is following the same idiom.
+
+#![crate_name = "foo"]
+
+pub struct Ref<'a>(&'a u32);
+type ARef<'a> = Ref<'a>;
+
+// @has foo/fn.test1.html
+// @matches - "Ref</a>&lt;'_&gt;"
+pub fn test1(a: &u32) -> Ref {
+    Ref(a)
+}
+
+// @has foo/fn.test2.html
+// @matches - "Ref</a>&lt;'_&gt;"
+pub fn test2(a: &u32) -> Ref<'_> {
+    Ref(a)
+}
+
+// @has foo/fn.test3.html
+// @matches - "Ref</a>&lt;'_&gt;"
+pub fn test3(a: &u32) -> ARef {
+    Ref(a)
+}
+
+// @has foo/fn.test4.html
+// @matches - "Ref</a>&lt;'_&gt;"
+pub fn test4(a: &u32) -> ARef<'_> {
+    Ref(a)
+}
+
+// Ensure external paths in inlined docs also display elided lifetime
+// @has foo/bar/fn.test5.html
+// @matches - "Ref</a>&lt;'_&gt;"
+// @has foo/bar/fn.test6.html
+// @matches - "Ref</a>&lt;'_&gt;"
+#[doc(inline)]
+pub extern crate bar;