about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoshua Nelson <jyn514@gmail.com>2020-08-17 18:45:18 -0400
committerJoshua Nelson <jyn514@gmail.com>2020-08-19 08:18:25 -0400
commit9cf2fa84e8dfbbeb01d4d06fabd921300c58ade0 (patch)
tree33d3725e460489df02fa7194e41be7dd6e37878f
parent06d6d3dff5f95c7ef24954cc3c6c1b8010705378 (diff)
downloadrust-9cf2fa84e8dfbbeb01d4d06fabd921300c58ade0.tar.gz
rust-9cf2fa84e8dfbbeb01d4d06fabd921300c58ade0.zip
Allow reusing the code in `collect_trait_impls`
-rw-r--r--src/librustdoc/clean/types.rs129
-rw-r--r--src/librustdoc/clean/utils.rs2
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs35
4 files changed, 80 insertions, 87 deletions
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 5b9f4830261..62f71514fcf 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -7,6 +7,7 @@ use std::num::NonZeroU32;
 use std::rc::Rc;
 use std::sync::Arc;
 use std::{slice, vec};
+use std::lazy::SyncOnceCell as OnceCell;
 
 use rustc_ast::attr;
 use rustc_ast::util::comments::beautify_doc_string;
@@ -26,7 +27,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{self, FileName};
 use rustc_target::abi::VariantIdx;
 use rustc_target::spec::abi::Abi;
-use smallvec::SmallVec;
+use smallvec::{SmallVec, smallvec};
 
 use crate::clean::cfg::Cfg;
 use crate::clean::external_path;
@@ -1266,61 +1267,85 @@ impl PrimitiveType {
         }
     }
 
-    pub fn impls(&self, tcx: TyCtxt<'_>) -> SmallVec<[DefId; 4]> {
-        use self::PrimitiveType::*;
-
-        let both =
-            |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> { a.into_iter().chain(b).collect() };
-
-        let lang_items = tcx.lang_items();
-        let primary_impl = match self {
-            Isize => lang_items.isize_impl(),
-            I8 => lang_items.i8_impl(),
-            I16 => lang_items.i16_impl(),
-            I32 => lang_items.i32_impl(),
-            I64 => lang_items.i64_impl(),
-            I128 => lang_items.i128_impl(),
-            Usize => lang_items.usize_impl(),
-            U8 => lang_items.u8_impl(),
-            U16 => lang_items.u16_impl(),
-            U32 => lang_items.u32_impl(),
-            U64 => lang_items.u64_impl(),
-            U128 => lang_items.u128_impl(),
-            F32 => return both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
-            F64 => return both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
-            Char => lang_items.char_impl(),
-            Bool => lang_items.bool_impl(),
-            Str => return both(lang_items.str_impl(), lang_items.str_alloc_impl()),
-            Slice => {
-                return lang_items
-                    .slice_impl()
-                    .into_iter()
-                    .chain(lang_items.slice_u8_impl())
-                    .chain(lang_items.slice_alloc_impl())
-                    .chain(lang_items.slice_u8_alloc_impl())
-                    .collect();
+    pub fn impls(&self, tcx: TyCtxt<'_>) -> &SmallVec<[DefId; 4]> {
+        Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
+    }
+
+    pub fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
+        static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
+
+        CELL.get_or_init(move || {
+            use self::PrimitiveType::*;
+
+            /// A macro to create a FxHashMap.
+            ///
+            /// Example:
+            ///
+            /// ```
+            /// let letters = map!{"a" => "b", "c" => "d"};
+            /// ```
+            ///
+            /// Trailing commas are allowed.
+            /// Commas between elements are required (even if the expression is a block).
+            macro_rules! map {
+                ($( $key: expr => $val: expr ),* $(,)*) => {{
+                    let mut map = ::rustc_data_structures::fx::FxHashMap::default();
+                    $( map.insert($key, $val); )*
+                    map
+                }}
             }
-            Array => lang_items.array_impl(),
-            Tuple => None,
-            Unit => None,
-            RawPointer => {
-                return lang_items
-                    .const_ptr_impl()
-                    .into_iter()
-                    .chain(lang_items.mut_ptr_impl())
-                    .chain(lang_items.const_slice_ptr_impl())
-                    .chain(lang_items.mut_slice_ptr_impl())
-                    .collect();
-            }
-            Reference => None,
-            Fn => None,
-            Never => None,
-        };
 
-        primary_impl.into_iter().collect()
+            let single = |a: Option<DefId>| a.into_iter().collect();
+            let both =
+                |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> { a.into_iter().chain(b).collect() };
+
+            let lang_items = tcx.lang_items();
+            map! {
+                Isize => single(lang_items.isize_impl()),
+                I8 => single(lang_items.i8_impl()),
+                I16 => single(lang_items.i16_impl()),
+                I32 => single(lang_items.i32_impl()),
+                I64 => single(lang_items.i64_impl()),
+                I128 => single(lang_items.i128_impl()),
+                Usize => single(lang_items.usize_impl()),
+                U8 => single(lang_items.u8_impl()),
+                U16 => single(lang_items.u16_impl()),
+                U32 => single(lang_items.u32_impl()),
+                U64 => single(lang_items.u64_impl()),
+                U128 => single(lang_items.u128_impl()),
+                F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
+                F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
+                Char => single(lang_items.char_impl()),
+                Bool => single(lang_items.bool_impl()),
+                Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
+                Slice => {
+                    lang_items
+                        .slice_impl()
+                        .into_iter()
+                        .chain(lang_items.slice_u8_impl())
+                        .chain(lang_items.slice_alloc_impl())
+                        .chain(lang_items.slice_u8_alloc_impl())
+                        .collect()
+                },
+                Array => single(lang_items.array_impl()),
+                Tuple => smallvec![],
+                Unit => smallvec![],
+                RawPointer => {
+                    lang_items
+                        .const_ptr_impl()
+                        .into_iter()
+                        .chain(lang_items.mut_ptr_impl())
+                        .chain(lang_items.const_slice_ptr_impl())
+                        .chain(lang_items.mut_slice_ptr_impl())
+                        .collect()
+                },
+                Reference => smallvec![],
+                Fn => smallvec![],
+                Never => smallvec![],
+            }
+        })
     }
 
-
     pub fn to_url_str(&self) -> &'static str {
         self.as_str()
     }
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index b80ac0384fd..75fdcd5ec1c 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -369,7 +369,7 @@ pub fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut V
                 None => continue,
             },
         };
-        for did in primitive.impls(tcx) {
+        for &did in primitive.impls(tcx) {
             if !did.is_local() {
                 inline::build_impl(cx, did, None, ret);
             }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index d5f7ddcbdfb..3dfa7b529e3 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -12,6 +12,7 @@
 #![feature(ptr_offset_from)]
 #![feature(crate_visibility_modifier)]
 #![feature(never_type)]
+#![feature(once_cell)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index a40b45f9a7e..24baff46dcf 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -34,40 +34,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
     }
 
     // Also try to inline primitive impls from other crates.
-    let lang_items = cx.tcx.lang_items();
-    let primitive_impls = [
-        lang_items.isize_impl(),
-        lang_items.i8_impl(),
-        lang_items.i16_impl(),
-        lang_items.i32_impl(),
-        lang_items.i64_impl(),
-        lang_items.i128_impl(),
-        lang_items.usize_impl(),
-        lang_items.u8_impl(),
-        lang_items.u16_impl(),
-        lang_items.u32_impl(),
-        lang_items.u64_impl(),
-        lang_items.u128_impl(),
-        lang_items.f32_impl(),
-        lang_items.f64_impl(),
-        lang_items.f32_runtime_impl(),
-        lang_items.f64_runtime_impl(),
-        lang_items.bool_impl(),
-        lang_items.char_impl(),
-        lang_items.str_impl(),
-        lang_items.array_impl(),
-        lang_items.slice_impl(),
-        lang_items.slice_u8_impl(),
-        lang_items.str_alloc_impl(),
-        lang_items.slice_alloc_impl(),
-        lang_items.slice_u8_alloc_impl(),
-        lang_items.const_ptr_impl(),
-        lang_items.mut_ptr_impl(),
-        lang_items.const_slice_ptr_impl(),
-        lang_items.mut_slice_ptr_impl(),
-    ];
-
-    for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
+    for &def_id in PrimitiveType::all_impls(cx.tcx).values().flatten() {
         if !def_id.is_local() {
             inline::build_impl(cx, def_id, None, &mut new_items);