From 18d211e93f3f43a04d2bae88eef60ffce182b0c8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 7 Jan 2020 14:38:23 +0100 Subject: [PATCH 1/2] Fix panic when reexporting primitive type in rustdoc --- src/librustc_hir/def.rs | 7 +++ src/librustdoc/clean/inline.rs | 10 +++- src/librustdoc/clean/utils.rs | 57 +++++++++++++++++++ .../passes/collect_intra_doc_links.rs | 51 ++--------------- .../rustdoc/auxiliary/reexport-primitive.rs | 7 +++ src/test/rustdoc/reexport-primitive.rs | 6 ++ 6 files changed, 92 insertions(+), 46 deletions(-) create mode 100644 src/test/rustdoc/auxiliary/reexport-primitive.rs create mode 100644 src/test/rustdoc/reexport-primitive.rs diff --git a/src/librustc_hir/def.rs b/src/librustc_hir/def.rs index 83e30d85c5a67..6ea7ceb173708 100644 --- a/src/librustc_hir/def.rs +++ b/src/librustc_hir/def.rs @@ -427,4 +427,11 @@ impl Res { Res::Err => true, } } + + pub fn is_primitive(&self) -> bool { + match self { + Res::PrimTy(..) => true, + _ => false, + } + } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 2400dded66668..c21f4a80b9354 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -428,12 +428,20 @@ fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet) // two namespaces, so the target may be listed twice. Make sure we only // visit each node at most once. for &item in cx.tcx.item_children(did).iter() { - let def_id = item.res.def_id(); + eprintln!("==> {:?}", item.res); + let def_id = match clean::utils::res_to_def_id(cx, &item.res) { + Some(did) => did, + None => continue, + }; + eprintln!("TOUDOUM ==> {:?} {:?}", item.res, item.vis); if item.vis == ty::Visibility::Public { if did == def_id || !visited.insert(def_id) { + eprintln!("1"); continue; } + eprintln!("2"); if let Some(i) = try_inline(cx, item.res, item.ident.name, None, visited) { + eprintln!("3"); items.extend(i) } } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 874cb9b8a5c9e..2a44d0cb1d2ae 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -652,3 +652,60 @@ where *cx.impl_trait_bounds.borrow_mut() = old_bounds; r } + +pub const PRIMITIVES: &[(&str, Res)] = &[ + ("u8", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U8))), + ("u16", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U16))), + ("u32", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U32))), + ("u64", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U64))), + ("u128", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U128))), + ("usize", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::Usize))), + ("i8", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I8))), + ("i16", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I16))), + ("i32", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I32))), + ("i64", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I64))), + ("i128", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I128))), + ("isize", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::Isize))), + ("f32", Res::PrimTy(hir::PrimTy::Float(syntax::ast::FloatTy::F32))), + ("f64", Res::PrimTy(hir::PrimTy::Float(syntax::ast::FloatTy::F64))), + ("str", Res::PrimTy(hir::PrimTy::Str)), + ("bool", Res::PrimTy(hir::PrimTy::Bool)), + ("char", Res::PrimTy(hir::PrimTy::Char)), +]; + +pub fn res_to_def_id(cx: &DocContext<'_>, res: &Res) -> Option { + if res.is_primitive() { + for (path, primitive) in PRIMITIVES.iter() { + if primitive == res { + return primitive_path_impl(cx, path); + } + } + None + } else { + Some(res.def_id()) + } +} + +pub fn primitive_path_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, + } +} diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 8a3966c320b8e..84f4d5d69de5e 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -203,7 +203,8 @@ 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)?; + let did = + utils::primitive_path_impl(cx, &path).ok_or(ErrorKind::ResolutionFailure)?; return cx .tcx .associated_items(did) @@ -888,50 +889,10 @@ fn handle_variant( Ok((parent_def, Some(format!("{}.v", variant.ident.name)))) } -const PRIMITIVES: &[(&str, Res)] = &[ - ("u8", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U8))), - ("u16", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U16))), - ("u32", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U32))), - ("u64", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U64))), - ("u128", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U128))), - ("usize", Res::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::Usize))), - ("i8", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I8))), - ("i16", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I16))), - ("i32", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I32))), - ("i64", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I64))), - ("i128", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I128))), - ("isize", Res::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::Isize))), - ("f32", Res::PrimTy(hir::PrimTy::Float(syntax::ast::FloatTy::F32))), - ("f64", Res::PrimTy(hir::PrimTy::Float(syntax::ast::FloatTy::F64))), - ("str", Res::PrimTy(hir::PrimTy::Str)), - ("bool", Res::PrimTy(hir::PrimTy::Bool)), - ("char", Res::PrimTy(hir::PrimTy::Char)), -]; - 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, + if ns == TypeNS { + utils::PRIMITIVES.iter().find(|x| x.0 == path_str).map(|x| x.1) + } else { + None } } diff --git a/src/test/rustdoc/auxiliary/reexport-primitive.rs b/src/test/rustdoc/auxiliary/reexport-primitive.rs new file mode 100644 index 0000000000000..47da337010895 --- /dev/null +++ b/src/test/rustdoc/auxiliary/reexport-primitive.rs @@ -0,0 +1,7 @@ +// compile-flags: --emit metadata --crate-type lib --edition 2018 + +#![crate_name = "foo"] + +pub mod bar { + pub use bool; +} diff --git a/src/test/rustdoc/reexport-primitive.rs b/src/test/rustdoc/reexport-primitive.rs new file mode 100644 index 0000000000000..421e5f6ae8e66 --- /dev/null +++ b/src/test/rustdoc/reexport-primitive.rs @@ -0,0 +1,6 @@ +// aux-build: reexport-primitive.rs +// compile-flags:--extern foo --edition 2018 + +pub mod p { + pub use foo::bar::*; +} From 21e69e61ecd1e16765846045d0667c222662f126 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 8 Jan 2020 00:32:36 +0100 Subject: [PATCH 2/2] Make reexported primitive types appear in modules --- src/librustdoc/clean/inline.rs | 32 +++++++++++-------- src/librustdoc/clean/types.rs | 25 +++++++++++++++ src/librustdoc/html/item_type.rs | 1 + .../passes/collect_intra_doc_links.rs | 1 - src/test/rustdoc/reexport-primitive.rs | 4 +++ 5 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c21f4a80b9354..eed88c2090d02 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -427,23 +427,29 @@ fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet) // If we're re-exporting a re-export it may actually re-export something in // two namespaces, so the target may be listed twice. Make sure we only // visit each node at most once. - for &item in cx.tcx.item_children(did).iter() { - eprintln!("==> {:?}", item.res); + for &item in cx.tcx.item_children(did).iter().filter(|item| item.vis == ty::Visibility::Public) { let def_id = match clean::utils::res_to_def_id(cx, &item.res) { Some(did) => did, None => continue, }; - eprintln!("TOUDOUM ==> {:?} {:?}", item.res, item.vis); - if item.vis == ty::Visibility::Public { - if did == def_id || !visited.insert(def_id) { - eprintln!("1"); - continue; - } - eprintln!("2"); - if let Some(i) = try_inline(cx, item.res, item.ident.name, None, visited) { - eprintln!("3"); - items.extend(i) - } + if did == def_id || !visited.insert(def_id) { + continue; + } + if let Res::PrimTy(ref primitive) = item.res { + record_extern_fqn(cx, def_id, TypeKind::Primitive); + cx.renderinfo.borrow_mut().inlined.insert(def_id); + items.push(clean::Item { + source: cx.tcx.def_span(def_id).clean(cx), + name: Some(item.ident.clean(cx)), + attrs: cx.tcx.get_attrs(def_id).clean(cx), + inner: clean::ItemEnum::PrimitiveItem(clean::PrimitiveType::from(primitive)), + visibility: clean::Public, + stability: cx.tcx.lookup_stability(def_id).clean(cx), + deprecation: cx.tcx.lookup_deprecation(def_id).clean(cx), + def_id, + }); + } else if let Some(i) = try_inline(cx, item.res, item.ident.name, None, visited) { + items.extend(i); } } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index c8f1dff703fb4..205ad6a6e197e 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1044,6 +1044,30 @@ pub enum PrimitiveType { Never, } +impl From<&hir::PrimTy> for PrimitiveType { + fn from(other: &hir::PrimTy) -> PrimitiveType { + match other { + hir::PrimTy::Uint(syntax::ast::UintTy::U8) => PrimitiveType::U8, + hir::PrimTy::Uint(syntax::ast::UintTy::U16) => PrimitiveType::U16, + hir::PrimTy::Uint(syntax::ast::UintTy::U32) => PrimitiveType::U32, + hir::PrimTy::Uint(syntax::ast::UintTy::U64) => PrimitiveType::U64, + hir::PrimTy::Uint(syntax::ast::UintTy::U128) => PrimitiveType::U128, + hir::PrimTy::Uint(syntax::ast::UintTy::Usize) => PrimitiveType::Usize, + hir::PrimTy::Int(syntax::ast::IntTy::I8) => PrimitiveType::I8, + hir::PrimTy::Int(syntax::ast::IntTy::I16) => PrimitiveType::I16, + hir::PrimTy::Int(syntax::ast::IntTy::I32) => PrimitiveType::I32, + hir::PrimTy::Int(syntax::ast::IntTy::I64) => PrimitiveType::I64, + hir::PrimTy::Int(syntax::ast::IntTy::I128) => PrimitiveType::I128, + hir::PrimTy::Int(syntax::ast::IntTy::Isize) => PrimitiveType::Isize, + hir::PrimTy::Float(syntax::ast::FloatTy::F32) => PrimitiveType::F32, + hir::PrimTy::Float(syntax::ast::FloatTy::F64) => PrimitiveType::F64, + hir::PrimTy::Str => PrimitiveType::Str, + hir::PrimTy::Bool => PrimitiveType::Bool, + hir::PrimTy::Char => PrimitiveType::Char, + } + } +} + #[derive(Clone, Copy, Debug)] pub enum TypeKind { Enum, @@ -1060,6 +1084,7 @@ pub enum TypeKind { Attr, Derive, TraitAlias, + Primitive, } pub trait GetDefId { diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index 4a0f4e5a4c9c8..ab9aeb5c8533e 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -119,6 +119,7 @@ impl From for ItemType { clean::TypeKind::Attr => ItemType::ProcAttribute, clean::TypeKind::Derive => ItemType::ProcDerive, clean::TypeKind::TraitAlias => ItemType::TraitAlias, + clean::TypeKind::Primitive => ItemType::Primitive, } } } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 84f4d5d69de5e..68e9e564ce947 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -9,7 +9,6 @@ use rustc_hir::def::{ Namespace::{self, *}, PerNS, Res, }; -use rustc_hir::def_id::DefId; use rustc_resolve::ParentScope; use rustc_span::symbol::Symbol; use rustc_span::DUMMY_SP; diff --git a/src/test/rustdoc/reexport-primitive.rs b/src/test/rustdoc/reexport-primitive.rs index 421e5f6ae8e66..5043321ba4ca5 100644 --- a/src/test/rustdoc/reexport-primitive.rs +++ b/src/test/rustdoc/reexport-primitive.rs @@ -1,6 +1,10 @@ // aux-build: reexport-primitive.rs // compile-flags:--extern foo --edition 2018 +#![crate_name = "bar"] + +// @has bar/p/index.html +// @has - 'bool' pub mod p { pub use foo::bar::*; }