about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2018-08-16 15:14:11 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2018-08-16 15:14:11 +0200
commit985da801b07ec997e3eb6d735a0dfd041728623e (patch)
tree473d38651d27ff22b5aad9217d02a896f15dceb7 /src
parentafd0a2f2499ff66e74236c5b06d3ab9ab87dd3d3 (diff)
downloadrust-985da801b07ec997e3eb6d735a0dfd041728623e.tar.gz
rust-985da801b07ec997e3eb6d735a0dfd041728623e.zip
Generate blanket implementations for reexported items as well
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/clean/blanket_impl.rs178
-rw-r--r--src/test/rustdoc/blanket-reexport-item.rs18
2 files changed, 106 insertions, 90 deletions
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 83e0827340d..b95b3ca8e11 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -65,98 +65,96 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> {
             return impls;
         }
         let ty = self.cx.tcx.type_of(def_id);
-        if self.cx.access_levels.borrow().is_doc_reachable(def_id) || ty.is_primitive() {
-            let generics = self.cx.tcx.generics_of(def_id);
-            let real_name = name.clone().map(|name| Ident::from_str(&name));
-            let param_env = self.cx.tcx.param_env(def_id);
-            for &trait_def_id in self.cx.all_traits.iter() {
-                if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) ||
-                   self.cx.generated_synthetics
-                          .borrow_mut()
-                          .get(&(def_id, trait_def_id))
-                          .is_some() {
-                    continue
-                }
-                self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
-                    self.cx.tcx.infer_ctxt().enter(|infcx| {
-                        let t_generics = infcx.tcx.generics_of(impl_def_id);
-                        let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id)
-                                                 .expect("Cannot get impl trait");
-
-                        match trait_ref.self_ty().sty {
-                            ty::TypeVariants::TyParam(_) => {},
-                            _ => return,
-                        }
-
-                        let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id);
-                        let ty = ty.subst(infcx.tcx, substs);
-                        let param_env = param_env.subst(infcx.tcx, substs);
-
-                        let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
-                        let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
-
-                        // Require the type the impl is implemented on to match
-                        // our type, and ignore the impl if there was a mismatch.
-                        let cause = traits::ObligationCause::dummy();
-                        let eq_result = infcx.at(&cause, param_env)
-                                             .eq(trait_ref.self_ty(), ty);
-                        if let Ok(InferOk { value: (), obligations }) = eq_result {
-                            // FIXME(eddyb) ignoring `obligations` might cause false positives.
-                            drop(obligations);
-
-                            let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
-                                cause.clone(),
-                                param_env,
-                                trait_ref.to_predicate(),
-                            ));
-                            if !may_apply {
-                                return
-                            }
-                            self.cx.generated_synthetics.borrow_mut()
-                                                        .insert((def_id, trait_def_id));
-                            let trait_ = hir::TraitRef {
-                                path: get_path_for_type(infcx.tcx,
-                                                        trait_def_id,
-                                                        hir::def::Def::Trait),
-                                ref_id: ast::DUMMY_NODE_ID,
-                                hir_ref_id: hir::DUMMY_HIR_ID,
-                            };
-                            let provided_trait_methods =
-                                infcx.tcx.provided_trait_methods(trait_def_id)
-                                         .into_iter()
-                                         .map(|meth| meth.ident.to_string())
-                                         .collect();
-
-                            let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, generics);
-                            let predicates = infcx.tcx.predicates_of(impl_def_id);
-
-                            impls.push(Item {
-                                source: infcx.tcx.def_span(impl_def_id).clean(self.cx),
-                                name: None,
-                                attrs: Default::default(),
-                                visibility: None,
-                                def_id: self.cx.next_def_id(impl_def_id.krate),
-                                stability: None,
-                                deprecation: None,
-                                inner: ImplItem(Impl {
-                                    unsafety: hir::Unsafety::Normal,
-                                    generics: (t_generics, &predicates).clean(self.cx),
-                                    provided_trait_methods,
-                                    trait_: Some(trait_.clean(self.cx)),
-                                    for_: ty.clean(self.cx),
-                                    items: infcx.tcx.associated_items(impl_def_id)
-                                                    .collect::<Vec<_>>()
-                                                    .clean(self.cx),
-                                    polarity: None,
-                                    synthetic: false,
-                                    blanket_impl: Some(infcx.tcx.type_of(impl_def_id)
-                                                                .clean(self.cx)),
-                                }),
-                            });
+        let generics = self.cx.tcx.generics_of(def_id);
+        let real_name = name.clone().map(|name| Ident::from_str(&name));
+        let param_env = self.cx.tcx.param_env(def_id);
+        for &trait_def_id in self.cx.all_traits.iter() {
+            if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) ||
+               self.cx.generated_synthetics
+                      .borrow_mut()
+                      .get(&(def_id, trait_def_id))
+                      .is_some() {
+                continue
+            }
+            self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
+                self.cx.tcx.infer_ctxt().enter(|infcx| {
+                    let t_generics = infcx.tcx.generics_of(impl_def_id);
+                    let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id)
+                                             .expect("Cannot get impl trait");
+
+                    match trait_ref.self_ty().sty {
+                        ty::TypeVariants::TyParam(_) => {},
+                        _ => return,
+                    }
+
+                    let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id);
+                    let ty = ty.subst(infcx.tcx, substs);
+                    let param_env = param_env.subst(infcx.tcx, substs);
+
+                    let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+                    let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
+
+                    // Require the type the impl is implemented on to match
+                    // our type, and ignore the impl if there was a mismatch.
+                    let cause = traits::ObligationCause::dummy();
+                    let eq_result = infcx.at(&cause, param_env)
+                                         .eq(trait_ref.self_ty(), ty);
+                    if let Ok(InferOk { value: (), obligations }) = eq_result {
+                        // FIXME(eddyb) ignoring `obligations` might cause false positives.
+                        drop(obligations);
+
+                        let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
+                            cause.clone(),
+                            param_env,
+                            trait_ref.to_predicate(),
+                        ));
+                        if !may_apply {
+                            return
                         }
-                    });
+                        self.cx.generated_synthetics.borrow_mut()
+                                                    .insert((def_id, trait_def_id));
+                        let trait_ = hir::TraitRef {
+                            path: get_path_for_type(infcx.tcx,
+                                                    trait_def_id,
+                                                    hir::def::Def::Trait),
+                            ref_id: ast::DUMMY_NODE_ID,
+                            hir_ref_id: hir::DUMMY_HIR_ID,
+                        };
+                        let provided_trait_methods =
+                            infcx.tcx.provided_trait_methods(trait_def_id)
+                                     .into_iter()
+                                     .map(|meth| meth.ident.to_string())
+                                     .collect();
+
+                        let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, generics);
+                        let predicates = infcx.tcx.predicates_of(impl_def_id);
+
+                        impls.push(Item {
+                            source: infcx.tcx.def_span(impl_def_id).clean(self.cx),
+                            name: None,
+                            attrs: Default::default(),
+                            visibility: None,
+                            def_id: self.cx.next_def_id(impl_def_id.krate),
+                            stability: None,
+                            deprecation: None,
+                            inner: ImplItem(Impl {
+                                unsafety: hir::Unsafety::Normal,
+                                generics: (t_generics, &predicates).clean(self.cx),
+                                provided_trait_methods,
+                                trait_: Some(trait_.clean(self.cx)),
+                                for_: ty.clean(self.cx),
+                                items: infcx.tcx.associated_items(impl_def_id)
+                                                .collect::<Vec<_>>()
+                                                .clean(self.cx),
+                                polarity: None,
+                                synthetic: false,
+                                blanket_impl: Some(infcx.tcx.type_of(impl_def_id)
+                                                            .clean(self.cx)),
+                            }),
+                        });
+                    }
                 });
-            }
+            });
         }
         impls
     }
diff --git a/src/test/rustdoc/blanket-reexport-item.rs b/src/test/rustdoc/blanket-reexport-item.rs
new file mode 100644
index 00000000000..355bfa0f2f2
--- /dev/null
+++ b/src/test/rustdoc/blanket-reexport-item.rs
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+// @has foo/struct.S.html '//h3[@id="impl-Into"]//code' 'impl<T, U> Into for T'
+pub struct S2 {}
+mod m {
+    pub struct S {}
+}
+pub use m::*;