rustdoc: Fix re-exporting primitive types

* Generate links to the primitive type docs for re-exports.
* Don't ICE on cross crate primitive type re-exports.
* Make primitive type re-exports show up cross crate.
This commit is contained in:
Oliver Middleton 2020-01-26 21:28:09 +00:00
parent 80a65bcaf2
commit bbc2ae7590
6 changed files with 91 additions and 17 deletions

View File

@ -445,12 +445,41 @@ fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet<DefId>)
// 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();
if item.vis == ty::Visibility::Public {
if did == def_id || !visited.insert(def_id) {
continue;
if let Some(def_id) = item.res.mod_def_id() {
if did == def_id || !visited.insert(def_id) {
continue;
}
}
if let Some(i) = try_inline(cx, item.res, item.ident.name, None, visited) {
if let Res::PrimTy(p) = item.res {
// Primitive types can't be inlined so generate an import instead.
items.push(clean::Item {
name: None,
attrs: clean::Attributes::default(),
source: clean::Span::empty(),
def_id: cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID),
visibility: clean::Public,
stability: None,
deprecation: None,
inner: clean::ImportItem(clean::Import::Simple(
item.ident.to_string(),
clean::ImportSource {
path: clean::Path {
global: false,
res: item.res,
segments: vec![clean::PathSegment {
name: clean::PrimitiveType::from(p).as_str().to_string(),
args: clean::GenericArgs::AngleBracketed {
args: Vec::new(),
bindings: Vec::new(),
},
}],
},
did: None,
},
)),
});
} else if let Some(i) = try_inline(cx, item.res, item.ident.name, None, visited) {
items.extend(i)
}
}

View File

@ -1290,6 +1290,19 @@ impl From<ast::FloatTy> for PrimitiveType {
}
}
impl From<hir::PrimTy> for PrimitiveType {
fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
match prim_ty {
hir::PrimTy::Int(int_ty) => int_ty.into(),
hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
hir::PrimTy::Float(float_ty) => float_ty.into(),
hir::PrimTy::Str => PrimitiveType::Str,
hir::PrimTy::Bool => PrimitiveType::Bool,
hir::PrimTy::Char => PrimitiveType::Char,
}
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Visibility {
Public,

View File

@ -570,14 +570,7 @@ pub fn resolve_type(cx: &DocContext<'_>, path: Path, id: hir::HirId) -> Type {
}
let is_generic = match path.res {
Res::PrimTy(p) => match p {
hir::PrimTy::Str => return Primitive(PrimitiveType::Str),
hir::PrimTy::Bool => return Primitive(PrimitiveType::Bool),
hir::PrimTy::Char => return Primitive(PrimitiveType::Char),
hir::PrimTy::Int(int_ty) => return Primitive(int_ty.into()),
hir::PrimTy::Uint(uint_ty) => return Primitive(uint_ty.into()),
hir::PrimTy::Float(float_ty) => return Primitive(float_ty.into()),
},
Res::PrimTy(p) => return Primitive(PrimitiveType::from(p)),
Res::SelfTy(..) if path.segments.len() == 1 => {
return Generic(kw::SelfUpper.to_string());
}

View File

@ -1171,11 +1171,14 @@ impl clean::ImportSource {
display_fn(move |f| match self.did {
Some(did) => resolved_path(f, did, &self.path, true, false),
_ => {
for (i, seg) in self.path.segments.iter().enumerate() {
if i > 0 {
write!(f, "::")?
}
write!(f, "{}", seg.name)?;
for seg in &self.path.segments[..self.path.segments.len() - 1] {
write!(f, "{}::", seg.name)?;
}
let name = self.path.last_name();
if let hir::def::Res::PrimTy(p) = self.path.res {
primitive_link(f, PrimitiveType::from(p), name)?;
} else {
write!(f, "{}", name)?;
}
Ok(())
}

View File

@ -0,0 +1,8 @@
// compile-flags: --emit metadata --crate-type lib --edition 2018
#![crate_name = "foo"]
pub mod bar {
pub use bool;
pub use char as my_char;
}

View File

@ -0,0 +1,28 @@
// aux-build: primitive-reexport.rs
// compile-flags:--extern foo --edition 2018
#![crate_name = "bar"]
// @has bar/p/index.html
// @has - '//code' 'pub use bool;'
// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'bool'
// @has - '//code' 'pub use char as my_char;'
// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
pub mod p {
pub use foo::bar::*;
}
// @has bar/baz/index.html
// @has - '//code' 'pub use bool;'
// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'bool'
// @has - '//code' 'pub use char as my_char;'
// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
pub use foo::bar as baz;
// @has bar/index.html
// @has - '//code' 'pub use str;'
// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'str'
// @has - '//code' 'pub use i32 as my_i32;'
// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html"]' 'i32'
pub use str;
pub use i32 as my_i32;