]> git.lizzy.rs Git - rust.git/commitdiff
rustdoc: generate implementors for all auto traits
authorSimonas Kazlauskas <git@kazlauskas.me>
Thu, 25 Apr 2019 22:16:57 +0000 (01:16 +0300)
committerSimonas Kazlauskas <git@kazlauskas.me>
Thu, 20 Jun 2019 14:36:43 +0000 (17:36 +0300)
Previously we would only generate a list of synthetic implementations
for two well known traits – Send and Sync. With this patch all the auto
traits known to rustc are considered. This includes such traits like
Unpin and user’s own traits.

Sadly the implementation still iterates through the list of crate items
and checks them against the traits, which for non-std crates containing
their own auto-traits will still not include types defined in std/core.

It is an improvement nontheless.

src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/test/rustdoc/empty-section.rs
src/test/rustdoc/issue-50159.rs
src/test/rustdoc/synthetic_auto/basic.rs
src/test/rustdoc/synthetic_auto/crate-local.rs [new file with mode: 0644]
src/test/rustdoc/synthetic_auto/manual.rs

index 3dcf77e6d7d542876fa43c050a816e8dd7fc0dbf..5a4dc7be326d2a5a125d4aa67c0b656b503c277b 100644 (file)
@@ -27,9 +27,7 @@ pub fn get_auto_trait_impls(
         let param_env = self.cx.tcx.param_env(param_env_def_id);
 
         debug!("get_auto_trait_impls({:?})", ty);
-        let auto_traits = self.cx.send_trait.into_iter().chain(
-            Some(self.cx.tcx.require_lang_item(lang_items::SyncTraitLangItem))
-        );
+        let auto_traits = self.cx.auto_traits.iter().cloned();
         auto_traits.filter_map(|trait_def_id| {
             let trait_ref = ty::TraitRef {
                 def_id: trait_def_id,
index b489ccf179c0e274ffa8c12f7f0cd88fb8383751..41a56756a1480c5fb6affb69a0969377c6b1189e 100644 (file)
@@ -17,8 +17,8 @@
 use rustc::middle::lang_items;
 use rustc::middle::stability;
 use rustc::mir::interpret::{GlobalId, ConstValue};
-use rustc::hir::{self, HirVec};
-use rustc::hir::def::{self, Res, DefKind, CtorKind};
+use rustc::hir;
+use rustc::hir::def::{CtorKind, DefKind, Res};
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::ty::subst::{InternalSubsts, SubstsRef, UnpackedKind};
 use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind};
@@ -4418,72 +4418,6 @@ pub fn enter_impl_trait<F, R>(cx: &DocContext<'_>, f: F) -> R
     r
 }
 
-// Start of code copied from rust-clippy
-
-pub fn path_to_def_local(tcx: TyCtxt<'_>, path: &[Symbol]) -> Option<DefId> {
-    let krate = tcx.hir().krate();
-    let mut items = krate.module.item_ids.clone();
-    let mut path_it = path.iter().peekable();
-
-    loop {
-        let segment = path_it.next()?;
-
-        for item_id in mem::replace(&mut items, HirVec::new()).iter() {
-            let item = tcx.hir().expect_item(item_id.id);
-            if item.ident.name == *segment {
-                if path_it.peek().is_none() {
-                    return Some(tcx.hir().local_def_id_from_hir_id(item_id.id))
-                }
-
-                items = match &item.node {
-                    &hir::ItemKind::Mod(ref m) => m.item_ids.clone(),
-                    _ => panic!("Unexpected item {:?} in path {:?} path")
-                };
-                break;
-            }
-        }
-    }
-}
-
-pub fn path_to_def(tcx: TyCtxt<'_>, path: &[Symbol]) -> Option<DefId> {
-    let crates = tcx.crates();
-
-    let krate = crates
-        .iter()
-        .find(|&&krate| tcx.crate_name(krate) == path[0]);
-
-    if let Some(krate) = krate {
-        let krate = DefId {
-            krate: *krate,
-            index: CRATE_DEF_INDEX,
-        };
-        let mut items = tcx.item_children(krate);
-        let mut path_it = path.iter().skip(1).peekable();
-
-        loop {
-            let segment = path_it.next()?;
-
-            for item in mem::replace(&mut items, &[]).iter() {
-                if item.ident.name == *segment {
-                    if path_it.peek().is_none() {
-                        return match item.res {
-                            def::Res::Def(DefKind::Trait, did) => Some(did),
-                            _ => None,
-                        }
-                    }
-
-                    items = tcx.item_children(item.res.def_id());
-                    break;
-                }
-            }
-        }
-    } else {
-        None
-    }
-}
-
-// End of code copied from rust-clippy
-
 #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
 enum RegionTarget<'tcx> {
     Region(Region<'tcx>),
index 20a4f86aedb902e10de0fd8f69af97c68068f609..7da501ef6cb7412943201f6baae81de558d2120d 100644 (file)
@@ -67,13 +67,13 @@ pub struct DocContext<'tcx> {
     pub ct_substs: RefCell<FxHashMap<DefId, clean::Constant>>,
     /// Table DefId of `impl Trait` in argument position -> bounds
     pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::GenericBound>>>,
-    pub send_trait: Option<DefId>,
     pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
     pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
     /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
     // FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set.
     pub generated_synthetics: RefCell<FxHashSet<(Ty<'tcx>, DefId)>>,
     pub all_traits: Vec<DefId>,
+    pub auto_traits: Vec<DefId>,
 }
 
 impl<'tcx> DocContext<'tcx> {
@@ -367,15 +367,10 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
                                     .collect()
             };
 
-            let send_trait = if crate_name == Some("core".to_string()) {
-                clean::path_to_def_local(tcx, &[sym::marker, sym::Send])
-            } else {
-                clean::path_to_def(tcx, &[sym::core, sym::marker, sym::Send])
-            };
-
             let mut renderinfo = RenderInfo::default();
             renderinfo.access_levels = access_levels;
 
+            let all_traits = tcx.all_traits(LOCAL_CRATE).to_vec();
             let ctxt = DocContext {
                 tcx,
                 resolver,
@@ -388,11 +383,13 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
                 lt_substs: Default::default(),
                 ct_substs: Default::default(),
                 impl_trait_bounds: Default::default(),
-                send_trait: send_trait,
                 fake_def_ids: Default::default(),
                 all_fake_def_ids: Default::default(),
                 generated_synthetics: Default::default(),
-                all_traits: tcx.all_traits(LOCAL_CRATE).to_vec(),
+                auto_traits: all_traits.iter().cloned().filter(|trait_def_id| {
+                    tcx.trait_is_auto(*trait_def_id)
+                }).collect(),
+                all_traits,
             };
             debug!("crate: {:?}", tcx.hir().krate());
 
index 619f2d688a1b0c286cec4ff5ba9b4c0235fc27a5..d95f3a80365cd32afd3726a71a0f5d7aee3cdd1f 100644 (file)
@@ -8,3 +8,6 @@
 // @!has - 'Auto Trait Implementations'
 impl !Send for Foo {}
 impl !Sync for Foo {}
+impl !std::marker::Unpin for Foo {}
+impl !std::panic::RefUnwindSafe for Foo {}
+impl !std::panic::UnwindSafe for Foo {}
index d175c82ec87bece7a43b11e87922996679b7685f..74502be622a4f0659f8c7309a21f9703640394b2 100644 (file)
@@ -14,7 +14,7 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> {
 // @has - '//code' 'impl<B> Send for Switch<B> where <B as Signal>::Item: Send'
 // @has - '//code' 'impl<B> Sync for Switch<B> where <B as Signal>::Item: Sync'
 // @count - '//*[@id="implementations-list"]/*[@class="impl"]' 0
-// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 2
+// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 5
 pub struct Switch<B: Signal> {
     pub inner: <B as Signal2>::Item2,
 }
index d5f1269d08a4c9d73f17b1a2b9572ef13064d725..38de5316b6cf55276451f87e2b852081ace7f1d5 100644 (file)
@@ -2,7 +2,7 @@
 // @has - '//code' 'impl<T> Send for Foo<T> where T: Send'
 // @has - '//code' 'impl<T> Sync for Foo<T> where T: Sync'
 // @count - '//*[@id="implementations-list"]/*[@class="impl"]' 0
-// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 2
+// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 5
 pub struct Foo<T> {
     field: T,
 }
diff --git a/src/test/rustdoc/synthetic_auto/crate-local.rs b/src/test/rustdoc/synthetic_auto/crate-local.rs
new file mode 100644 (file)
index 0000000..341dd57
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(optin_builtin_traits)]
+
+pub auto trait Banana {}
+
+// @has crate_local/struct.Peach.html
+// @has - '//code' 'impl Banana for Peach'
+// @has - '//code' 'impl Send for Peach'
+// @has - '//code' 'impl Sync for Peach'
+pub struct Peach;
index 413ba187f4556410a3267dd1b3b3bc168783d408..458403462d64a9053ad9e0fb7a0716f3d9e53f14 100644 (file)
@@ -6,7 +6,7 @@
 // 'impl<T> Send for Foo<T>'
 //
 // @count - '//*[@id="implementations-list"]/*[@class="impl"]' 1
-// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 1
+// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 4
 pub struct Foo<T> {
     field: T,
 }