From 4c8d00a3ec9cecfdff7b5da5a7157cc532e78ee2 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Fri, 26 Apr 2019 01:16:57 +0300 Subject: [PATCH] rustdoc: generate implementors for all auto traits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 | 4 +- src/librustdoc/clean/mod.rs | 70 +------------------ src/librustdoc/core.rs | 15 ++-- src/test/rustdoc/empty-section.rs | 3 + src/test/rustdoc/issue-50159.rs | 2 +- src/test/rustdoc/synthetic_auto/basic.rs | 2 +- .../rustdoc/synthetic_auto/crate-local.rs | 9 +++ src/test/rustdoc/synthetic_auto/manual.rs | 2 +- 8 files changed, 24 insertions(+), 83 deletions(-) create mode 100644 src/test/rustdoc/synthetic_auto/crate-local.rs diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 3dcf77e6d7d54..5a4dc7be326d2 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -27,9 +27,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { 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, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b489ccf179c0e..41a56756a1480 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -17,8 +17,8 @@ use rustc::middle::resolve_lifetime as rl; 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 @@ where r } -// Start of code copied from rust-clippy - -pub fn path_to_def_local(tcx: TyCtxt<'_>, path: &[Symbol]) -> Option { - 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 { - 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>), diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 20a4f86aedb90..7da501ef6cb74 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -67,13 +67,13 @@ pub struct DocContext<'tcx> { pub ct_substs: RefCell>, /// Table DefId of `impl Trait` in argument position -> bounds pub impl_trait_bounds: RefCell>>, - pub send_trait: Option, pub fake_def_ids: RefCell>, pub all_fake_def_ids: RefCell>, /// 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, DefId)>>, pub all_traits: Vec, + pub auto_traits: Vec, } 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()); diff --git a/src/test/rustdoc/empty-section.rs b/src/test/rustdoc/empty-section.rs index 619f2d688a1b0..d95f3a80365cd 100644 --- a/src/test/rustdoc/empty-section.rs +++ b/src/test/rustdoc/empty-section.rs @@ -8,3 +8,6 @@ pub struct Foo; // @!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 {} diff --git a/src/test/rustdoc/issue-50159.rs b/src/test/rustdoc/issue-50159.rs index d175c82ec87be..74502be622a4f 100644 --- a/src/test/rustdoc/issue-50159.rs +++ b/src/test/rustdoc/issue-50159.rs @@ -14,7 +14,7 @@ impl Signal2 for B where B: Signal { // @has - '//code' 'impl Send for Switch where ::Item: Send' // @has - '//code' 'impl Sync for Switch where ::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 { pub inner: ::Item2, } diff --git a/src/test/rustdoc/synthetic_auto/basic.rs b/src/test/rustdoc/synthetic_auto/basic.rs index d5f1269d08a4c..38de5316b6cf5 100644 --- a/src/test/rustdoc/synthetic_auto/basic.rs +++ b/src/test/rustdoc/synthetic_auto/basic.rs @@ -2,7 +2,7 @@ // @has - '//code' 'impl Send for Foo where T: Send' // @has - '//code' 'impl Sync for Foo 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 { 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 index 0000000000000..341dd572f81c8 --- /dev/null +++ b/src/test/rustdoc/synthetic_auto/crate-local.rs @@ -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; diff --git a/src/test/rustdoc/synthetic_auto/manual.rs b/src/test/rustdoc/synthetic_auto/manual.rs index 413ba187f4556..458403462d64a 100644 --- a/src/test/rustdoc/synthetic_auto/manual.rs +++ b/src/test/rustdoc/synthetic_auto/manual.rs @@ -6,7 +6,7 @@ // 'impl Send for Foo' // // @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 { field: T, }