about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/clean/mod.rs17
-rw-r--r--src/librustdoc/clean/utils.rs45
-rw-r--r--src/test/rustdoc/generic-associated-types/issue-94683.rs13
3 files changed, 40 insertions, 35 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0d1482ce470..eba31a17cf4 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -402,16 +402,7 @@ fn projection_to_path_segment(ty: ty::ProjectionTy<'_>, cx: &mut DocContext<'_>)
     PathSegment {
         name: item.name,
         args: GenericArgs::AngleBracketed {
-            args: ty.substs[generics.parent_count..]
-                .iter()
-                .map(|ty| match ty.unpack() {
-                    ty::subst::GenericArgKind::Lifetime(lt) => {
-                        GenericArg::Lifetime(lt.clean(cx).unwrap())
-                    }
-                    ty::subst::GenericArgKind::Type(ty) => GenericArg::Type(ty.clean(cx)),
-                    ty::subst::GenericArgKind::Const(c) => GenericArg::Const(Box::new(c.clean(cx))),
-                })
-                .collect(),
+            args: substs_to_args(cx, &ty.substs[generics.parent_count..], false),
             bindings: Default::default(),
         },
     }
@@ -1379,11 +1370,7 @@ fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>
                 });
                 if let Some(lt) = lifetime.cloned() {
                     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()
-                    };
+                    let cleaned = if !lt.is_elided() { lt.clean(cx) } else { Lifetime::elided() };
                     substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
                 }
                 indices.lifetimes += 1;
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 20eea32560b..7861b915e96 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -77,16 +77,12 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
     Crate { module, primitives, external_traits: cx.external_traits.clone() }
 }
 
-fn external_generic_args(
+crate fn substs_to_args(
     cx: &mut DocContext<'_>,
-    did: DefId,
-    has_self: bool,
-    bindings: Vec<TypeBinding>,
-    substs: SubstsRef<'_>,
-) -> GenericArgs {
-    let mut skip_self = has_self;
-    let mut ty_kind = None;
-    let args: Vec<_> = substs
+    substs: &[ty::subst::GenericArg<'_>],
+    mut skip_first: bool,
+) -> Vec<GenericArg> {
+    substs
         .iter()
         .filter_map(|kind| match kind.unpack() {
             GenericArgKind::Lifetime(lt) => match *lt {
@@ -95,23 +91,32 @@ fn external_generic_args(
                 }
                 _ => lt.clean(cx).map(GenericArg::Lifetime),
             },
-            GenericArgKind::Type(_) if skip_self => {
-                skip_self = false;
+            GenericArgKind::Type(_) if skip_first => {
+                skip_first = false;
                 None
             }
-            GenericArgKind::Type(ty) => {
-                ty_kind = Some(ty.kind());
-                Some(GenericArg::Type(ty.clean(cx)))
-            }
+            GenericArgKind::Type(ty) => Some(GenericArg::Type(ty.clean(cx))),
             GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(ct.clean(cx)))),
         })
-        .collect();
+        .collect()
+}
+
+fn external_generic_args(
+    cx: &mut DocContext<'_>,
+    did: DefId,
+    has_self: bool,
+    bindings: Vec<TypeBinding>,
+    substs: SubstsRef<'_>,
+) -> GenericArgs {
+    let args = substs_to_args(cx, &substs, has_self);
 
     if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() {
-        let inputs = match ty_kind.unwrap() {
-            ty::Tuple(tys) => tys.iter().map(|t| t.clean(cx)).collect(),
-            _ => return GenericArgs::AngleBracketed { args, bindings: bindings.into() },
-        };
+        let inputs =
+            // The trait's first substitution is the one after self, if there is one.
+            match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() {
+                ty::Tuple(tys) => tys.iter().map(|t| t.clean(cx)).collect(),
+                _ => return GenericArgs::AngleBracketed { args, bindings: bindings.into() },
+            };
         let output = None;
         // FIXME(#20299) return type comes from a projection now
         // match types[1].kind {
diff --git a/src/test/rustdoc/generic-associated-types/issue-94683.rs b/src/test/rustdoc/generic-associated-types/issue-94683.rs
new file mode 100644
index 00000000000..38ecf528310
--- /dev/null
+++ b/src/test/rustdoc/generic-associated-types/issue-94683.rs
@@ -0,0 +1,13 @@
+#![crate_name = "foo"]
+#![feature(generic_associated_types)]
+
+pub trait Trait {
+    type Gat<'a>;
+}
+
+// Make sure that the elided lifetime shows up
+
+// @has foo/type.T.html
+// @has - "pub type T = "
+// @has - "&lt;'_&gt;"
+pub type T = fn(&<() as Trait>::Gat<'_>);