diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 327be40a58f..54d693b1965 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -54,15 +54,6 @@ pub use self::types::Visibility::{Public, Inherited}; const FN_OUTPUT_NAME: &'static str = "Output"; -// extract the stability index for a node from tcx, if possible -fn get_stability(cx: &DocContext<'_>, def_id: DefId) -> Option { - cx.tcx.lookup_stability(def_id).clean(cx) -} - -fn get_deprecation(cx: &DocContext<'_>, def_id: DefId) -> Option { - cx.tcx.lookup_deprecation(def_id).clean(cx) -} - pub trait Clean { fn clean(&self, cx: &DocContext<'_>) -> T; } @@ -109,91 +100,6 @@ impl, U> Clean> for P<[T]> { } } -pub fn krate(mut cx: &mut DocContext<'_>) -> Crate { - use crate::visit_lib::LibEmbargoVisitor; - - let krate = cx.tcx.hir().krate(); - let module = crate::visit_ast::RustdocVisitor::new(&mut cx).visit(krate); - - let mut r = cx.renderinfo.get_mut(); - r.deref_trait_did = cx.tcx.lang_items().deref_trait(); - r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait(); - r.owned_box_did = cx.tcx.lang_items().owned_box(); - - let mut externs = Vec::new(); - for &cnum in cx.tcx.crates().iter() { - externs.push((cnum, cnum.clean(cx))); - // Analyze doc-reachability for extern items - LibEmbargoVisitor::new(&mut cx).visit_lib(cnum); - } - externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); - - // Clean the crate, translating the entire libsyntax AST to one that is - // understood by rustdoc. - let mut module = module.clean(cx); - let mut masked_crates = FxHashSet::default(); - - match module.inner { - ModuleItem(ref module) => { - for it in &module.items { - // `compiler_builtins` should be masked too, but we can't apply - // `#[doc(masked)]` to the injected `extern crate` because it's unstable. - if it.is_extern_crate() - && (it.attrs.has_doc_flag(sym::masked) - || cx.tcx.is_compiler_builtins(it.def_id.krate)) - { - masked_crates.insert(it.def_id.krate); - } - } - } - _ => unreachable!(), - } - - let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx); - { - let m = match module.inner { - ModuleItem(ref mut m) => m, - _ => unreachable!(), - }; - m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| { - Item { - source: Span::empty(), - name: Some(prim.to_url_str().to_string()), - attrs: attrs.clone(), - visibility: Public, - stability: get_stability(cx, def_id), - deprecation: get_deprecation(cx, def_id), - def_id, - inner: PrimitiveItem(prim), - } - })); - m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| { - Item { - source: Span::empty(), - name: Some(kw.clone()), - attrs, - visibility: Public, - stability: get_stability(cx, def_id), - deprecation: get_deprecation(cx, def_id), - def_id, - inner: KeywordItem(kw), - } - })); - } - - Crate { - name, - version: None, - src, - module: Some(module), - externs, - primitives, - external_traits: cx.external_traits.clone(), - masked_crates, - collapsed: false, - } -} - impl Clean for CrateNum { fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate { let root = DefId { krate: *self, index: CRATE_DEF_INDEX }; @@ -394,66 +300,6 @@ impl Clean for hir::GenericBound { } } -fn external_generic_args( - cx: &DocContext<'_>, - trait_did: Option, - has_self: bool, - bindings: Vec, - substs: SubstsRef<'_>, -) -> GenericArgs { - let mut skip_self = has_self; - let mut ty_kind = None; - let args: Vec<_> = substs.iter().filter_map(|kind| match kind.unpack() { - GenericArgKind::Lifetime(lt) => { - lt.clean(cx).and_then(|lt| Some(GenericArg::Lifetime(lt))) - } - GenericArgKind::Type(_) if skip_self => { - skip_self = false; - None - } - GenericArgKind::Type(ty) => { - ty_kind = Some(&ty.kind); - Some(GenericArg::Type(ty.clean(cx))) - } - GenericArgKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))), - }).collect(); - - match trait_did { - // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C - Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => { - assert!(ty_kind.is_some()); - let inputs = match ty_kind { - Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(), - _ => return GenericArgs::AngleBracketed { args, bindings }, - }; - let output = None; - // FIXME(#20299) return type comes from a projection now - // match types[1].kind { - // ty::Tuple(ref v) if v.is_empty() => None, // -> () - // _ => Some(types[1].clean(cx)) - // }; - GenericArgs::Parenthesized { inputs, output } - }, - _ => { - GenericArgs::AngleBracketed { args, bindings } - } - } -} - -// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar -// from Fn<(A, B,), C> to Fn(A, B) -> C -fn external_path(cx: &DocContext<'_>, name: Symbol, trait_did: Option, has_self: bool, - bindings: Vec, substs: SubstsRef<'_>) -> Path { - Path { - global: false, - res: Res::Err, - segments: vec![PathSegment { - name: name.to_string(), - args: external_generic_args(cx, trait_did, has_self, bindings, substs) - }], - } -} - impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec) { fn clean(&self, cx: &DocContext<'_>) -> GenericBound { let (trait_ref, ref bounds) = *self; @@ -1036,118 +882,6 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx } } -/// The point of this function is to replace bounds with types. -/// -/// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option` will return -/// `[Display, Option]` (we just returns the list of the types, we don't care about the -/// wrapped types in here). -fn get_real_types( - generics: &Generics, - arg: &Type, - cx: &DocContext<'_>, - recurse: i32, -) -> FxHashSet { - let arg_s = arg.print().to_string(); - let mut res = FxHashSet::default(); - if recurse >= 10 { // FIXME: remove this whole recurse thing when the recursion bug is fixed - return res; - } - if arg.is_full_generic() { - if let Some(where_pred) = generics.where_predicates.iter().find(|g| { - match g { - &WherePredicate::BoundPredicate { ref ty, .. } => ty.def_id() == arg.def_id(), - _ => false, - } - }) { - let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); - for bound in bounds.iter() { - match *bound { - GenericBound::TraitBound(ref poly_trait, _) => { - for x in poly_trait.generic_params.iter() { - if !x.is_type() { - continue - } - if let Some(ty) = x.get_type() { - let adds = get_real_types(generics, &ty, cx, recurse + 1); - if !adds.is_empty() { - res.extend(adds); - } else if !ty.is_full_generic() { - res.insert(ty); - } - } - } - } - _ => {} - } - } - } - if let Some(bound) = generics.params.iter().find(|g| { - g.is_type() && g.name == arg_s - }) { - for bound in bound.get_bounds().unwrap_or_else(|| &[]) { - if let Some(ty) = bound.get_trait_type() { - let adds = get_real_types(generics, &ty, cx, recurse + 1); - if !adds.is_empty() { - res.extend(adds); - } else if !ty.is_full_generic() { - res.insert(ty.clone()); - } - } - } - } - } else { - res.insert(arg.clone()); - if let Some(gens) = arg.generics() { - for gen in gens.iter() { - if gen.is_full_generic() { - let adds = get_real_types(generics, gen, cx, recurse + 1); - if !adds.is_empty() { - res.extend(adds); - } - } else { - res.insert(gen.clone()); - } - } - } - } - res -} - -/// Return the full list of types when bounds have been resolved. -/// -/// i.e. `fn foo>(x: u32, y: B)` will return -/// `[u32, Display, Option]`. -pub fn get_all_types( - generics: &Generics, - decl: &FnDecl, - cx: &DocContext<'_>, -) -> (Vec, Vec) { - let mut all_types = FxHashSet::default(); - for arg in decl.inputs.values.iter() { - if arg.type_.is_self_type() { - continue; - } - let args = get_real_types(generics, &arg.type_, cx, 0); - if !args.is_empty() { - all_types.extend(args); - } else { - all_types.insert(arg.type_.clone()); - } - } - - let ret_types = match decl.output { - FunctionRetTy::Return(ref return_type) => { - let mut ret = get_real_types(generics, &return_type, cx, 0); - if ret.is_empty() { - ret.insert(return_type.clone()); - } - ret.into_iter().collect() - } - _ => Vec::new(), - }; - (all_types.into_iter().collect(), ret_types) -} - impl<'a> Clean for (&'a hir::FnSig, &'a hir::Generics, hir::BodyId, Option) { fn clean(&self, cx: &DocContext<'_>) -> Method { @@ -2262,66 +1996,6 @@ impl Clean for hir::PathSegment { } } -fn strip_type(ty: Type) -> Type { - match ty { - Type::ResolvedPath { path, param_names, did, is_generic } => { - Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic } - } - Type::Tuple(inner_tys) => { - Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect()) - } - Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))), - Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s), - Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))), - Type::BorrowedRef { lifetime, mutability, type_ } => { - Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) } - } - Type::QPath { name, self_type, trait_ } => { - Type::QPath { - name, - self_type: Box::new(strip_type(*self_type)), trait_: Box::new(strip_type(*trait_)) - } - } - _ => ty - } -} - -fn strip_path(path: &Path) -> Path { - let segments = path.segments.iter().map(|s| { - PathSegment { - name: s.name.clone(), - args: GenericArgs::AngleBracketed { - args: vec![], - bindings: vec![], - } - } - }).collect(); - - Path { - global: path.global, - res: path.res.clone(), - segments, - } -} - -fn qpath_to_string(p: &hir::QPath) -> String { - let segments = match *p { - hir::QPath::Resolved(_, ref path) => &path.segments, - hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(), - }; - - let mut s = String::new(); - for (i, seg) in segments.iter().enumerate() { - if i > 0 { - s.push_str("::"); - } - if seg.ident.name != kw::PathRoot { - s.push_str(&seg.ident.as_str()); - } - } - s -} - impl Clean for Ident { #[inline] fn clean(&self, cx: &DocContext<'_>) -> String { @@ -2444,15 +2118,6 @@ impl Clean for ty::ImplPolarity { } } -pub fn get_auto_trait_and_blanket_impls( - cx: &DocContext<'tcx>, - ty: Ty<'tcx>, - param_env_def_id: DefId, -) -> impl Iterator { - AutoTraitFinder::new(cx).get_auto_trait_impls(ty, param_env_def_id).into_iter() - .chain(BlanketImplFinder::new(cx).get_blanket_impls(ty, param_env_def_id)) -} - impl Clean> for doctree::Impl<'_> { fn clean(&self, cx: &DocContext<'_>) -> Vec { let mut ret = Vec::new(); @@ -2497,63 +2162,6 @@ impl Clean> for doctree::Impl<'_> { } } -fn build_deref_target_impls(cx: &DocContext<'_>, - items: &[Item], - ret: &mut Vec) { - use self::PrimitiveType::*; - let tcx = cx.tcx; - - for item in items { - let target = match item.inner { - TypedefItem(ref t, true) => &t.type_, - _ => continue, - }; - let primitive = match *target { - ResolvedPath { did, .. } if did.is_local() => continue, - ResolvedPath { did, .. } => { - ret.extend(inline::build_impls(cx, did, None)); - continue - } - _ => match target.primitive_type() { - Some(prim) => prim, - 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().slice_impl(), - Tuple => None, - Unit => None, - RawPointer => tcx.lang_items().const_ptr_impl(), - Reference => None, - Fn => None, - Never => None, - }; - if let Some(did) = did { - if !did.is_local() { - inline::build_impl(cx, did, None, ret); - } - } - } -} - impl Clean> for doctree::ExternCrate<'_> { fn clean(&self, cx: &DocContext<'_>) -> Vec { @@ -2710,170 +2318,6 @@ impl Clean for doctree::ForeignItem<'_> { } } -// Utilities - -pub trait ToSource { - fn to_src(&self, cx: &DocContext<'_>) -> String; -} - -impl ToSource for syntax_pos::Span { - fn to_src(&self, cx: &DocContext<'_>) -> String { - debug!("converting span {:?} to snippet", self.clean(cx)); - let sn = match cx.sess().source_map().span_to_snippet(*self) { - Ok(x) => x, - Err(_) => String::new() - }; - debug!("got snippet {}", sn); - sn - } -} - -fn name_from_pat(p: &hir::Pat) -> String { - use rustc::hir::*; - debug!("trying to get a name from pattern: {:?}", p); - - match p.kind { - PatKind::Wild => "_".to_string(), - PatKind::Binding(_, _, ident, _) => ident.to_string(), - PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), - PatKind::Struct(ref name, ref fields, etc) => { - format!("{} {{ {}{} }}", qpath_to_string(name), - fields.iter().map(|fp| format!("{}: {}", fp.ident, name_from_pat(&fp.pat))) - .collect::>().join(", "), - if etc { ", .." } else { "" } - ) - } - PatKind::Or(ref pats) => { - pats.iter().map(|p| name_from_pat(&**p)).collect::>().join(" | ") - } - PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) - .collect::>().join(", ")), - PatKind::Box(ref p) => name_from_pat(&**p), - PatKind::Ref(ref p, _) => name_from_pat(&**p), - PatKind::Lit(..) => { - warn!("tried to get argument name from PatKind::Lit, \ - which is silly in function arguments"); - "()".to_string() - }, - PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \ - which is not allowed in function arguments"), - PatKind::Slice(ref begin, ref mid, ref end) => { - let begin = begin.iter().map(|p| name_from_pat(&**p)); - let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter(); - let end = end.iter().map(|p| name_from_pat(&**p)); - format!("[{}]", begin.chain(mid).chain(end).collect::>().join(", ")) - }, - } -} - -fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String { - match n.val { - ty::ConstKind::Unevaluated(def_id, _) => { - if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) { - print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id)) - } else { - inline::print_inlined_const(cx, def_id) - } - }, - _ => { - let mut s = n.to_string(); - // array lengths are obviously usize - if s.ends_with("usize") { - let n = s.len() - "usize".len(); - s.truncate(n); - if s.ends_with(": ") { - let n = s.len() - ": ".len(); - s.truncate(n); - } - } - s - }, - } -} - -fn print_const_expr(cx: &DocContext<'_>, body: hir::BodyId) -> String { - cx.tcx.hir().hir_to_pretty_string(body.hir_id) -} - -/// Given a type Path, resolve it to a Type using the TyCtxt -fn resolve_type(cx: &DocContext<'_>, - path: Path, - id: hir::HirId) -> Type { - if id == hir::DUMMY_HIR_ID { - debug!("resolve_type({:?})", path); - } else { - debug!("resolve_type({:?},{:?})", path, id); - } - - let is_generic = match path.res { - Res::PrimTy(p) => match p { - hir::Str => return Primitive(PrimitiveType::Str), - hir::Bool => return Primitive(PrimitiveType::Bool), - hir::Char => return Primitive(PrimitiveType::Char), - hir::Int(int_ty) => return Primitive(int_ty.into()), - hir::Uint(uint_ty) => return Primitive(uint_ty.into()), - hir::Float(float_ty) => return Primitive(float_ty.into()), - }, - Res::SelfTy(..) if path.segments.len() == 1 => { - return Generic(kw::SelfUpper.to_string()); - } - Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => { - return Generic(format!("{:#}", path.print())); - } - Res::SelfTy(..) - | Res::Def(DefKind::TyParam, _) - | Res::Def(DefKind::AssocTy, _) => true, - _ => false, - }; - let did = register_res(&*cx, path.res); - ResolvedPath { path, param_names: None, did, is_generic } -} - -pub fn register_res(cx: &DocContext<'_>, res: Res) -> DefId { - debug!("register_res({:?})", res); - - let (did, kind) = match res { - Res::Def(DefKind::Fn, i) => (i, TypeKind::Function), - Res::Def(DefKind::TyAlias, i) => (i, TypeKind::Typedef), - Res::Def(DefKind::Enum, i) => (i, TypeKind::Enum), - Res::Def(DefKind::Trait, i) => (i, TypeKind::Trait), - Res::Def(DefKind::Struct, i) => (i, TypeKind::Struct), - Res::Def(DefKind::Union, i) => (i, TypeKind::Union), - Res::Def(DefKind::Mod, i) => (i, TypeKind::Module), - Res::Def(DefKind::ForeignTy, i) => (i, TypeKind::Foreign), - Res::Def(DefKind::Const, i) => (i, TypeKind::Const), - Res::Def(DefKind::Static, i) => (i, TypeKind::Static), - Res::Def(DefKind::Variant, i) => (cx.tcx.parent(i).expect("cannot get parent def id"), - TypeKind::Enum), - Res::Def(DefKind::Macro(mac_kind), i) => match mac_kind { - MacroKind::Bang => (i, TypeKind::Macro), - MacroKind::Attr => (i, TypeKind::Attr), - MacroKind::Derive => (i, TypeKind::Derive), - }, - Res::Def(DefKind::TraitAlias, i) => (i, TypeKind::TraitAlias), - Res::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait), - Res::SelfTy(_, Some(impl_def_id)) => return impl_def_id, - _ => return res.def_id() - }; - if did.is_local() { return did } - inline::record_extern_fqn(cx, did, kind); - if let TypeKind::Trait = kind { - inline::record_extern_trait(cx, did); - } - did -} - -fn resolve_use_source(cx: &DocContext<'_>, path: Path) -> ImportSource { - ImportSource { - did: if path.res.opt_def_id().is_none() { - None - } else { - Some(register_res(cx, path.res)) - }, - path, - } -} - impl Clean for doctree::Macro<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let name = self.name.clean(cx); @@ -2981,17 +2425,6 @@ impl Clean for hir::TypeBindingKind { } } -pub fn enter_impl_trait(cx: &DocContext<'_>, f: F) -> R -where - F: FnOnce() -> R, -{ - let old_bounds = mem::take(&mut *cx.impl_trait_bounds.borrow_mut()); - let r = f(); - assert!(cx.impl_trait_bounds.borrow().is_empty()); - *cx.impl_trait_bounds.borrow_mut() = old_bounds; - r -} - #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)] enum RegionTarget<'tcx> { Region(Region<'tcx>),