]> git.lizzy.rs Git - rust.git/commitdiff
Resolve `impl Trait` in argument position
authorShotaro Yamada <sinkuu@sinkuu.xyz>
Sat, 24 Mar 2018 05:12:08 +0000 (14:12 +0900)
committerShotaro Yamada <sinkuu@sinkuu.xyz>
Sat, 24 Mar 2018 05:18:06 +0000 (14:18 +0900)
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs

index 7701dd2fd9909c75ce7d0dfa53c60bfd2d67c475..0154c6a08557cec87ede7b870467bc89a622003f 100644 (file)
@@ -1774,11 +1774,12 @@ 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);
         Method {
-            generics: self.1.clean(cx),
+            decl: enter_impl_trait(cx, &generics.params, || (&*self.0.decl, self.2).clean(cx)),
+            generics,
             unsafety: self.0.unsafety,
             constness: self.0.constness,
-            decl: (&*self.0.decl, self.2).clean(cx),
             abi: self.0.abi
         }
     }
@@ -1803,6 +1804,8 @@ 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));
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -1812,8 +1815,8 @@ fn clean(&self, cx: &DocContext) -> Item {
             deprecation: self.depr.clean(cx),
             def_id: cx.tcx.hir.local_def_id(self.id),
             inner: FunctionItem(Function {
-                decl: (&self.decl, self.body).clean(cx),
-                generics: self.generics.clean(cx),
+                decl,
+                generics,
                 unsafety: self.unsafety,
                 constness: self.constness,
                 abi: self.abi,
@@ -2040,10 +2043,13 @@ 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);
                 TyMethodItem(TyMethod {
                     unsafety: sig.unsafety.clone(),
-                    decl: (&*sig.decl, &names[..]).clean(cx),
-                    generics: self.generics.clean(cx),
+                    decl: enter_impl_trait(cx, &generics.params, || {
+                        (&*sig.decl, &names[..]).clean(cx)
+                    }),
+                    generics,
                     abi: sig.abi
                 })
             }
@@ -2547,6 +2553,12 @@ fn clean(&self, cx: &DocContext) -> Type {
                     return new_ty;
                 }
 
+                if let Def::TyParam(did) = path.def {
+                    if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) {
+                        return ImplTrait(bounds);
+                    }
+                }
+
                 let mut alias = None;
                 if let Def::TyAlias(def_id) = path.def {
                     // Substitute private type aliases
@@ -3259,10 +3271,13 @@ pub struct BareFunctionDecl {
 
 impl Clean<BareFunctionDecl> for hir::BareFnTy {
     fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
+        let generic_params = self.generic_params.clean(cx);
         BareFunctionDecl {
             unsafety: self.unsafety,
-            generic_params: self.generic_params.clean(cx),
-            decl: (&*self.decl, &self.arg_names[..]).clean(cx),
+            decl: enter_impl_trait(cx, &generic_params, || {
+                (&*self.decl, &self.arg_names[..]).clean(cx)
+            }),
+            generic_params,
             abi: self.abi,
         }
     }
@@ -3563,9 +3578,12 @@ 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);
                 ForeignFunctionItem(Function {
-                    decl: (&**decl, &names[..]).clean(cx),
-                    generics: generics.clean(cx),
+                    decl: enter_impl_trait(cx, &generics.params, || {
+                        (&**decl, &names[..]).clean(cx)
+                    }),
+                    generics,
                     unsafety: hir::Unsafety::Unsafe,
                     abi: Abi::Rust,
                     constness: hir::Constness::NotConst,
@@ -3867,6 +3885,29 @@ 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
+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 r = f();
+    assert!(cx.impl_trait_bounds.borrow().is_empty());
+    *cx.impl_trait_bounds.borrow_mut() = old_bounds;
+    r
+}
+
 // Start of code copied from rust-clippy
 
 pub fn get_trait_def_id(tcx: &TyCtxt, path: &[&str], use_local: bool) -> Option<DefId> {
index 1e0fafc8d9dfd98cf6fe199b6ee2a0e4281b3ca6..749d7ec126be30a8b8fa7dbe07cecb68245addc9 100644 (file)
@@ -72,6 +72,8 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
     pub ty_substs: RefCell<FxHashMap<Def, clean::Type>>,
     /// Table node id of lifetime parameter definition -> substituted lifetime
     pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
+    /// Table DefId of `impl Trait` in argument position -> bounds
+    pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::TyParamBound>>>,
     pub send_trait: Option<DefId>,
     pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
     pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
@@ -261,6 +263,7 @@ pub fn run_core(search_paths: SearchPaths,
             renderinfo: Default::default(),
             ty_substs: Default::default(),
             lt_substs: Default::default(),
+            impl_trait_bounds: Default::default(),
             mod_ids: Default::default(),
             send_trait: send_trait,
             fake_def_ids: RefCell::new(FxHashMap()),