From a4995fc8bd9febe40119b2294716ab87b1de62e5 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 17 Aug 2020 18:03:38 -0400 Subject: [PATCH 1/8] Refactor `impl_for_type` into a separate function --- src/librustdoc/clean/utils.rs | 63 +++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index a7d03fcabf546..0c6234f69ed6d 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -15,7 +15,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::mir::interpret::{sign_extend, ConstValue, Scalar}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, DefIdTree, Ty}; +use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt}; use rustc_span::symbol::{kw, sym, Symbol}; use std::mem; @@ -349,8 +349,39 @@ pub fn qpath_to_string(p: &hir::QPath<'_>) -> String { s } -pub fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut Vec) { +pub fn impl_for_type(tcx: TyCtxt<'_>, primitive: PrimitiveType) -> Option { use self::PrimitiveType::*; + + match primitive { + Isize => tcx.lang_items().isize_impl(), + I8 => tcx.lang_items().i8_impl(), + I16 => tcx.lang_items().i16_impl(), + I32 => tcx.lang_items().i32_impl(), + I64 => tcx.lang_items().i64_impl(), + I128 => tcx.lang_items().i128_impl(), + Usize => tcx.lang_items().usize_impl(), + U8 => tcx.lang_items().u8_impl(), + U16 => tcx.lang_items().u16_impl(), + U32 => tcx.lang_items().u32_impl(), + U64 => tcx.lang_items().u64_impl(), + U128 => tcx.lang_items().u128_impl(), + F32 => tcx.lang_items().f32_impl(), + F64 => tcx.lang_items().f64_impl(), + Char => tcx.lang_items().char_impl(), + Bool => tcx.lang_items().bool_impl(), + Str => tcx.lang_items().str_impl(), + Slice => tcx.lang_items().slice_impl(), + Array => tcx.lang_items().array_impl(), + Tuple => None, + Unit => None, + RawPointer => tcx.lang_items().const_ptr_impl(), + Reference => None, + Fn => None, + Never => None, + } +} + +pub fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut Vec) { let tcx = cx.tcx; for item in items { @@ -369,33 +400,7 @@ pub fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut V None => continue, }, }; - let did = match primitive { - Isize => tcx.lang_items().isize_impl(), - I8 => tcx.lang_items().i8_impl(), - I16 => tcx.lang_items().i16_impl(), - I32 => tcx.lang_items().i32_impl(), - I64 => tcx.lang_items().i64_impl(), - I128 => tcx.lang_items().i128_impl(), - Usize => tcx.lang_items().usize_impl(), - U8 => tcx.lang_items().u8_impl(), - U16 => tcx.lang_items().u16_impl(), - U32 => tcx.lang_items().u32_impl(), - U64 => tcx.lang_items().u64_impl(), - U128 => tcx.lang_items().u128_impl(), - F32 => tcx.lang_items().f32_impl(), - F64 => tcx.lang_items().f64_impl(), - Char => tcx.lang_items().char_impl(), - Bool => tcx.lang_items().bool_impl(), - Str => tcx.lang_items().str_impl(), - Slice => tcx.lang_items().slice_impl(), - Array => tcx.lang_items().array_impl(), - Tuple => None, - Unit => None, - RawPointer => tcx.lang_items().const_ptr_impl(), - Reference => None, - Fn => None, - Never => None, - }; + let did = impl_for_type(tcx, primitive); if let Some(did) = did { if !did.is_local() { inline::build_impl(cx, did, None, ret); From 833bbb197f49838d0afe34b9faf59392b18531ca Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 17 Aug 2020 18:06:46 -0400 Subject: [PATCH 2/8] Say `tcx.lang_items()` less --- src/librustdoc/clean/utils.rs | 41 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 0c6234f69ed6d..e911a406d6cae 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -352,29 +352,30 @@ pub fn qpath_to_string(p: &hir::QPath<'_>) -> String { pub fn impl_for_type(tcx: TyCtxt<'_>, primitive: PrimitiveType) -> Option { use self::PrimitiveType::*; + let lang_items = tcx.lang_items(); match primitive { - Isize => tcx.lang_items().isize_impl(), - I8 => tcx.lang_items().i8_impl(), - I16 => tcx.lang_items().i16_impl(), - I32 => tcx.lang_items().i32_impl(), - I64 => tcx.lang_items().i64_impl(), - I128 => tcx.lang_items().i128_impl(), - Usize => tcx.lang_items().usize_impl(), - U8 => tcx.lang_items().u8_impl(), - U16 => tcx.lang_items().u16_impl(), - U32 => tcx.lang_items().u32_impl(), - U64 => tcx.lang_items().u64_impl(), - U128 => tcx.lang_items().u128_impl(), - F32 => tcx.lang_items().f32_impl(), - F64 => tcx.lang_items().f64_impl(), - Char => tcx.lang_items().char_impl(), - Bool => tcx.lang_items().bool_impl(), - Str => tcx.lang_items().str_impl(), - Slice => tcx.lang_items().slice_impl(), - Array => tcx.lang_items().array_impl(), + 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 => lang_items.f32_impl(), + F64 => lang_items.f64_impl(), + Char => lang_items.char_impl(), + Bool => lang_items.bool_impl(), + Str => lang_items.str_impl(), + Slice => lang_items.slice_impl(), + Array => lang_items.array_impl(), Tuple => None, Unit => None, - RawPointer => tcx.lang_items().const_ptr_impl(), + RawPointer => lang_items.const_ptr_impl(), Reference => None, Fn => None, Never => None, From dae3a4fe6adb4e6180c462803b223134715274d4 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 17 Aug 2020 18:21:31 -0400 Subject: [PATCH 3/8] Return all impls, not just the primary one --- Cargo.lock | 1 + src/librustdoc/Cargo.toml | 1 + src/librustdoc/clean/utils.rs | 41 ++++++++++++++++++++++++++--------- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1fa3bef07c7e..3c46cba4c0760 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4052,6 +4052,7 @@ dependencies = [ "rustc-rayon", "serde", "serde_json", + "smallvec 1.4.0", "tempfile", ] diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 4af13e4cd587a..1354ef5cbdeb4 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -14,5 +14,6 @@ minifier = "0.0.33" rayon = { version = "0.3.0", package = "rustc-rayon" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +smallvec = "1.0" tempfile = "3" itertools = "0.8" diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index e911a406d6cae..cd022491095a7 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -17,6 +17,7 @@ use rustc_middle::mir::interpret::{sign_extend, ConstValue, Scalar}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt}; use rustc_span::symbol::{kw, sym, Symbol}; +use smallvec::SmallVec; use std::mem; pub fn krate(mut cx: &mut DocContext<'_>) -> Crate { @@ -349,11 +350,14 @@ pub fn qpath_to_string(p: &hir::QPath<'_>) -> String { s } -pub fn impl_for_type(tcx: TyCtxt<'_>, primitive: PrimitiveType) -> Option { +pub fn impl_for_type(tcx: TyCtxt<'_>, primitive: PrimitiveType) -> SmallVec<[DefId; 4]> { use self::PrimitiveType::*; + let both = + |a: Option, b: Option| -> SmallVec<_> { a.into_iter().chain(b).collect() }; + let lang_items = tcx.lang_items(); - match primitive { + let primary_impl = match primitive { Isize => lang_items.isize_impl(), I8 => lang_items.i8_impl(), I16 => lang_items.i16_impl(), @@ -366,20 +370,38 @@ pub fn impl_for_type(tcx: TyCtxt<'_>, primitive: PrimitiveType) -> Option U32 => lang_items.u32_impl(), U64 => lang_items.u64_impl(), U128 => lang_items.u128_impl(), - F32 => lang_items.f32_impl(), - F64 => lang_items.f64_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 => lang_items.str_impl(), - Slice => lang_items.slice_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(); + } Array => lang_items.array_impl(), Tuple => None, Unit => None, - RawPointer => lang_items.const_ptr_impl(), + 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() } pub fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut Vec) { @@ -401,8 +423,7 @@ pub fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut V None => continue, }, }; - let did = impl_for_type(tcx, primitive); - if let Some(did) = did { + for did in impl_for_type(tcx, primitive) { if !did.is_local() { inline::build_impl(cx, did, None, ret); } From c6ac860b32fd2b295342b5964c71ea4da77c0cb1 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 17 Aug 2020 18:26:10 -0400 Subject: [PATCH 4/8] impl_for_type -> PrimitiveType::impls --- src/librustdoc/clean/types.rs | 57 +++++++++++++++++++++++++++++++++ src/librustdoc/clean/utils.rs | 59 ++--------------------------------- 2 files changed, 59 insertions(+), 57 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 627f88df45c9f..a3c56fcb0b0b8 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -19,12 +19,14 @@ use rustc_hir::lang_items; use rustc_hir::Mutability; use rustc_index::vec::IndexVec; use rustc_middle::middle::stability; +use rustc_middle::ty::TyCtxt; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::DUMMY_SP; 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 crate::clean::cfg::Cfg; use crate::clean::external_path; @@ -1264,6 +1266,61 @@ impl PrimitiveType { } } + pub fn impls(&self, tcx: TyCtxt<'_>) -> SmallVec<[DefId; 4]> { + use self::PrimitiveType::*; + + let both = + |a: Option, b: Option| -> 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(); + } + 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() + } + + 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 cd022491095a7..b1d56631c2051 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -15,9 +15,8 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::mir::interpret::{sign_extend, ConstValue, Scalar}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt}; +use rustc_middle::ty::{self, DefIdTree, Ty}; use rustc_span::symbol::{kw, sym, Symbol}; -use smallvec::SmallVec; use std::mem; pub fn krate(mut cx: &mut DocContext<'_>) -> Crate { @@ -350,60 +349,6 @@ pub fn qpath_to_string(p: &hir::QPath<'_>) -> String { s } -pub fn impl_for_type(tcx: TyCtxt<'_>, primitive: PrimitiveType) -> SmallVec<[DefId; 4]> { - use self::PrimitiveType::*; - - let both = - |a: Option, b: Option| -> SmallVec<_> { a.into_iter().chain(b).collect() }; - - let lang_items = tcx.lang_items(); - let primary_impl = match primitive { - 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(); - } - 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() -} - pub fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut Vec) { let tcx = cx.tcx; @@ -423,7 +368,7 @@ pub fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut V None => continue, }, }; - for did in impl_for_type(tcx, primitive) { + for did in primitive.impls(tcx) { if !did.is_local() { inline::build_impl(cx, did, None, ret); } From 3b1d2e37a784d6eb578195d3bf34f2b541f4d73e Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 17 Aug 2020 18:45:18 -0400 Subject: [PATCH 5/8] Allow reusing the code in `collect_trait_impls` --- src/librustdoc/clean/types.rs | 129 +++++++++++-------- src/librustdoc/clean/utils.rs | 2 +- src/librustdoc/lib.rs | 1 + src/librustdoc/passes/collect_trait_impls.rs | 35 +---- 4 files changed, 80 insertions(+), 87 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a3c56fcb0b0b8..eabe60c14cfdf 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::ast::{self, AttrStyle}; use rustc_ast::attr; @@ -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, b: Option| -> 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> { + static CELL: OnceCell>> = 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| a.into_iter().collect(); + let both = + |a: Option, b: Option| -> 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 b1d56631c2051..8d06469311829 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -368,7 +368,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 d5f7ddcbdfbde..3dfa7b529e34c 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 a40b45f9a7e2c..24baff46dcfa5 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); From 1b74f04409c167f27e3bee2141fe78d492769967 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 17 Aug 2020 18:54:29 -0400 Subject: [PATCH 6/8] Use `impls` for intra doc links as well --- src/librustdoc/clean/types.rs | 2 +- .../passes/collect_intra_doc_links.rs | 52 +++++++------------ 2 files changed, 19 insertions(+), 35 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index eabe60c14cfdf..5f262d061fa44 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1267,7 +1267,7 @@ impl PrimitiveType { } } - pub fn impls(&self, tcx: TyCtxt<'_>) -> &SmallVec<[DefId; 4]> { + pub fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> { Self::all_impls(tcx).get(self).expect("missing impl for primitive type") } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index f7fc3579d67a7..84d429cc6a8b8 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -16,6 +16,7 @@ use rustc_span::hygiene::MacroKind; use rustc_span::symbol::Ident; use rustc_span::symbol::Symbol; use rustc_span::DUMMY_SP; +use smallvec::SmallVec; use std::cell::Cell; use std::ops::Range; @@ -270,18 +271,21 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .ok_or(ErrorKind::ResolutionFailure)?; if let Some(prim) = is_primitive(&path, TypeNS) { - let did = primitive_impl(cx, &path).ok_or(ErrorKind::ResolutionFailure)?; - return cx - .tcx - .associated_items(did) - .filter_by_name_unhygienic(item_name) - .next() - .and_then(|item| match item.kind { - ty::AssocKind::Fn => Some("method"), - _ => None, - }) - .map(|out| (prim, Some(format!("{}#{}.{}", path, out, item_name)))) - .ok_or(ErrorKind::ResolutionFailure); + for &impl_ in primitive_impl(cx, &path).ok_or(ErrorKind::ResolutionFailure)? { + let link = cx + .tcx + .associated_items(impl_) + .find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, impl_) + .and_then(|item| match item.kind { + ty::AssocKind::Fn => Some("method"), + _ => None, + }) + .map(|out| (prim, Some(format!("{}#{}.{}", path, out, item_name)))); + if let Some(link) = link { + return Ok(link); + } + } + return Err(ErrorKind::ResolutionFailure); } let (_, ty_res) = cx @@ -1227,26 +1231,6 @@ fn is_primitive(path_str: &str, ns: Namespace) -> Option { if ns == TypeNS { PRIMITIVES.iter().find(|x| x.0 == path_str).map(|x| x.1) } else { None } } -fn primitive_impl(cx: &DocContext<'_>, path_str: &str) -> Option { - let tcx = cx.tcx; - match path_str { - "u8" => tcx.lang_items().u8_impl(), - "u16" => tcx.lang_items().u16_impl(), - "u32" => tcx.lang_items().u32_impl(), - "u64" => tcx.lang_items().u64_impl(), - "u128" => tcx.lang_items().u128_impl(), - "usize" => tcx.lang_items().usize_impl(), - "i8" => tcx.lang_items().i8_impl(), - "i16" => tcx.lang_items().i16_impl(), - "i32" => tcx.lang_items().i32_impl(), - "i64" => tcx.lang_items().i64_impl(), - "i128" => tcx.lang_items().i128_impl(), - "isize" => tcx.lang_items().isize_impl(), - "f32" => tcx.lang_items().f32_impl(), - "f64" => tcx.lang_items().f64_impl(), - "str" => tcx.lang_items().str_impl(), - "bool" => tcx.lang_items().bool_impl(), - "char" => tcx.lang_items().char_impl(), - _ => None, - } +fn primitive_impl(cx: &DocContext<'_>, path_str: &str) -> Option<&'static SmallVec<[DefId; 4]>> { + Some(PrimitiveType::from_symbol(Symbol::intern(path_str))?.impls(cx.tcx)) } From 28580749ccab89f7a81c206263790f6135eac234 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 17 Aug 2020 19:36:29 -0400 Subject: [PATCH 7/8] xpy fmt --- src/librustdoc/clean/types.rs | 9 +++++---- src/librustdoc/passes/collect_intra_doc_links.rs | 7 ++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5f262d061fa44..094a3954067c4 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -3,11 +3,11 @@ use std::default::Default; use std::fmt; use std::hash::{Hash, Hasher}; use std::iter::FromIterator; +use std::lazy::SyncOnceCell as OnceCell; 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::ast::{self, AttrStyle}; use rustc_ast::attr; @@ -27,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, smallvec}; +use smallvec::{smallvec, SmallVec}; use crate::clean::cfg::Cfg; use crate::clean::external_path; @@ -1296,8 +1296,9 @@ impl PrimitiveType { } let single = |a: Option| a.into_iter().collect(); - let both = - |a: Option, b: Option| -> SmallVec<_> { a.into_iter().chain(b).collect() }; + let both = |a: Option, b: Option| -> SmallVec<_> { + a.into_iter().chain(b).collect() + }; let lang_items = tcx.lang_items(); map! { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 84d429cc6a8b8..f79639b35d89f 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -275,7 +275,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { let link = cx .tcx .associated_items(impl_) - .find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, impl_) + .find_by_name_and_namespace( + cx.tcx, + Ident::with_dummy_span(item_name), + ns, + impl_, + ) .and_then(|item| match item.kind { ty::AssocKind::Fn => Some("method"), _ => None, From 7be824e7eacf96227ac12527d6ac309c40404f2c Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 17 Aug 2020 19:42:39 -0400 Subject: [PATCH 8/8] Add a test --- .../intra-link-primitive-non-default-impl.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/test/rustdoc/intra-link-primitive-non-default-impl.rs diff --git a/src/test/rustdoc/intra-link-primitive-non-default-impl.rs b/src/test/rustdoc/intra-link-primitive-non-default-impl.rs new file mode 100644 index 0000000000000..427cd2124a926 --- /dev/null +++ b/src/test/rustdoc/intra-link-primitive-non-default-impl.rs @@ -0,0 +1,14 @@ +#![deny(broken_intra_doc_links)] + +// ignore-tidy-linelength + +// @has intra_link_primitive_non_default_impl/fn.f.html +/// [`str::trim`] +// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim"]' 'str::trim' +/// [`str::to_lowercase`] +// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_lowercase"]' 'str::to_lowercase' +/// [`str::into_boxed_bytes`] +// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.into_boxed_bytes"]' 'str::into_boxed_bytes' +/// [`str::replace`] +// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.replace"]' 'str::replace' +pub fn f() {}