about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorShotaro Yamada <sinkuu@sinkuu.xyz>2018-05-14 12:07:34 +0900
committerShotaro Yamada <sinkuu@sinkuu.xyz>2018-05-16 11:03:02 +0900
commit7eefe2b4735b018efa50fa1e5ebfaf4db868ba22 (patch)
treebb3c4126187f25cc7d5c7479b6031b1dd3f3410e /src
parente44fc6c52d9674ed09958512e3bf09bc55bccecf (diff)
downloadrust-7eefe2b4735b018efa50fa1e5ebfaf4db868ba22.tar.gz
rust-7eefe2b4735b018efa50fa1e5ebfaf4db868ba22.zip
Fix rustdoc panic with `impl Trait` in type parameters
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/clean/mod.rs35
-rw-r--r--src/test/rustdoc/universal-impl-trait.rs14
2 files changed, 42 insertions, 7 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a1d77f4145b..c233e57a801 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1754,16 +1754,39 @@ pub struct Generics {
 
 impl Clean<Generics> for hir::Generics {
     fn clean(&self, cx: &DocContext) -> Generics {
+        // Synthetic type-parameters are inserted after normal ones.
+        // In order for normal parameters to be able to refer to synthetic ones,
+        // scans them first.
+        fn is_impl_trait(param: &hir::GenericParam) -> bool {
+            if let hir::GenericParam::Type(ref tp) = param {
+                tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
+            } else {
+                false
+            }
+        }
+        let impl_trait_params = self.params
+            .iter()
+            .filter(|p| is_impl_trait(p))
+            .map(|p| {
+                let p = p.clean(cx);
+                if let GenericParamDef::Type(ref tp) = p {
+                    cx.impl_trait_bounds
+                        .borrow_mut()
+                        .insert(tp.did, tp.bounds.clone());
+                } else {
+                    unreachable!()
+                }
+                p
+            })
+            .collect::<Vec<_>>();
+
         let mut params = Vec::with_capacity(self.params.len());
-        for p in &self.params {
+        for p in self.params.iter().filter(|p| !is_impl_trait(p)) {
             let p = p.clean(cx);
-            if let GenericParamDef::Type(ref tp) = p {
-                if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
-                    cx.impl_trait_bounds.borrow_mut().insert(tp.did, tp.bounds.clone());
-                }
-            }
             params.push(p);
         }
+        params.extend(impl_trait_params);
+
         let mut g = Generics {
             params,
             where_predicates: self.where_clause.predicates.clean(cx)
diff --git a/src/test/rustdoc/universal-impl-trait.rs b/src/test/rustdoc/universal-impl-trait.rs
index af51ff3d941..1c1124282d4 100644
--- a/src/test/rustdoc/universal-impl-trait.rs
+++ b/src/test/rustdoc/universal-impl-trait.rs
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(universal_impl_trait)]
 #![crate_name = "foo"]
 
 use std::io::Read;
+use std::borrow::Borrow;
 
 // @has foo/fn.foo.html
 // @has - //pre 'foo('
@@ -51,3 +51,15 @@ impl<T> S<T> {
 // @has - 'method</a>('
 // @matches - '_x: impl <a class="trait" href="[^"]+/trait\.Debug\.html"'
 impl<T> Trait for S<T> {}
+
+// @has foo/fn.much_universe.html
+// @matches - 'T:.+Borrow.+impl .+trait\.Trait\.html'
+// @matches - 'U:.+IntoIterator.+= impl.+Iterator\.html.+= impl.+Clone\.html'
+// @matches - '_: impl .+trait\.Read\.html.+ \+ .+trait\.Clone\.html'
+pub fn much_universe<
+    T: Borrow<impl Trait>,
+    U: IntoIterator<Item = impl Iterator<Item = impl Clone>>,
+>(
+    _: impl Read + Clone,
+) {
+}