]> git.lizzy.rs Git - rust.git/commitdiff
rustdoc: Resolve nested `impl Trait`s
authorShotaro Yamada <sinkuu@sinkuu.xyz>
Thu, 3 May 2018 13:24:50 +0000 (22:24 +0900)
committerShotaro Yamada <sinkuu@sinkuu.xyz>
Thu, 3 May 2018 13:34:10 +0000 (22:34 +0900)
src/librustdoc/clean/mod.rs
src/test/rustdoc/universal-impl-trait.rs

index bd64ac67ac93eaa789529951a941ef05ad1580ea..ffba91c924830fbfb3ee0f2f65d505a8ce2bc531 100644 (file)
@@ -1755,8 +1755,18 @@ pub struct Generics {
 
 impl Clean<Generics> for hir::Generics {
     fn clean(&self, cx: &DocContext) -> Generics {
+        let mut params = Vec::with_capacity(self.params.len());
+        for p in &self.params {
+            let p = p.clean(cx);
+            if let GenericParam::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);
+        }
         let mut g = Generics {
-            params: self.params.clean(cx),
+            params,
             where_predicates: self.where_clause.predicates.clean(cx)
         };
 
@@ -1869,9 +1879,11 @@ pub struct Method {
 
 impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) {
     fn clean(&self, cx: &DocContext) -> Method {
-        let generics = self.1.clean(cx);
+        let (generics, decl) = enter_impl_trait(cx, || {
+            (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))
+        });
         Method {
-            decl: enter_impl_trait(cx, &generics.params, || (&*self.0.decl, self.2).clean(cx)),
+            decl,
             generics,
             unsafety: self.0.unsafety,
             constness: self.0.constness,
@@ -1899,8 +1911,9 @@ pub struct Function {
 
 impl Clean<Item> for doctree::Function {
     fn clean(&self, cx: &DocContext) -> Item {
-        let generics = self.generics.clean(cx);
-        let decl = enter_impl_trait(cx, &generics.params, || (&self.decl, self.body).clean(cx));
+        let (generics, decl) = enter_impl_trait(cx, || {
+            (self.generics.clean(cx), (&self.decl, self.body).clean(cx))
+        });
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -2139,12 +2152,12 @@ fn clean(&self, cx: &DocContext) -> Item {
                 MethodItem((sig, &self.generics, body).clean(cx))
             }
             hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
-                let generics = self.generics.clean(cx);
+                let (generics, decl) = enter_impl_trait(cx, || {
+                    (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
+                });
                 TyMethodItem(TyMethod {
                     unsafety: sig.unsafety.clone(),
-                    decl: enter_impl_trait(cx, &generics.params, || {
-                        (&*sig.decl, &names[..]).clean(cx)
-                    }),
+                    decl,
                     generics,
                     abi: sig.abi
                 })
@@ -3415,12 +3428,12 @@ pub struct BareFunctionDecl {
 
 impl Clean<BareFunctionDecl> for hir::BareFnTy {
     fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
-        let generic_params = self.generic_params.clean(cx);
+        let (generic_params, decl) = enter_impl_trait(cx, || {
+            (self.generic_params.clean(cx), (&*self.decl, &self.arg_names[..]).clean(cx))
+        });
         BareFunctionDecl {
             unsafety: self.unsafety,
-            decl: enter_impl_trait(cx, &generic_params, || {
-                (&*self.decl, &self.arg_names[..]).clean(cx)
-            }),
+            decl,
             generic_params,
             abi: self.abi,
         }
@@ -3722,11 +3735,11 @@ impl Clean<Item> for hir::ForeignItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
             hir::ForeignItemFn(ref decl, ref names, ref generics) => {
-                let generics = generics.clean(cx);
+                let (generics, decl) = enter_impl_trait(cx, || {
+                    (generics.clean(cx), (&**decl, &names[..]).clean(cx))
+                });
                 ForeignFunctionItem(Function {
-                    decl: enter_impl_trait(cx, &generics.params, || {
-                        (&**decl, &names[..]).clean(cx)
-                    }),
+                    decl,
                     generics,
                     unsafety: hir::Unsafety::Unsafe,
                     abi: Abi::Rust,
@@ -4030,23 +4043,11 @@ pub fn def_id_to_path(cx: &DocContext, did: DefId, name: Option<String>) -> Vec<
     once(crate_name).chain(relative).collect()
 }
 
-pub fn enter_impl_trait<F, R>(cx: &DocContext, gps: &[GenericParam], f: F) -> R
+pub fn enter_impl_trait<F, R>(cx: &DocContext, f: F) -> R
 where
     F: FnOnce() -> R,
 {
-    let bounds = gps.iter()
-        .filter_map(|p| {
-            if let GenericParam::Type(ref tp) = *p {
-                if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
-                    return Some((tp.did, tp.bounds.clone()));
-                }
-            }
-
-            None
-        })
-        .collect::<FxHashMap<DefId, Vec<TyParamBound>>>();
-
-    let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), bounds);
+    let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), Default::default());
     let r = f();
     assert!(cx.impl_trait_bounds.borrow().is_empty());
     *cx.impl_trait_bounds.borrow_mut() = old_bounds;
index 4cf99562c52992ba389fb8332a1d3a1b40ab2461..af51ff3d9419e909e2d37b320e3e026d29264427 100644 (file)
@@ -11,6 +11,8 @@
 #![feature(universal_impl_trait)]
 #![crate_name = "foo"]
 
+use std::io::Read;
+
 // @has foo/fn.foo.html
 // @has - //pre 'foo('
 // @matches - '_x: impl <a class="trait" href="[^"]+/trait\.Clone\.html"'
@@ -39,6 +41,11 @@ pub fn bar(_bar: impl Copy) {
     // @matches - '_baz:.+struct\.S\.html.+impl .+trait\.Clone\.html'
     pub fn baz(_baz: S<impl Clone>) {
     }
+
+    // @has - 'qux</a>('
+    // @matches - 'trait\.Read\.html'
+    pub fn qux(_qux: impl IntoIterator<Item = S<impl Read>>) {
+    }
 }
 
 // @has - 'method</a>('