2019-12-22 17:42:04 -05:00
|
|
|
use crate::clean::auto_trait::AutoTraitFinder;
|
|
|
|
use crate::clean::blanket_impl::BlanketImplFinder;
|
2022-01-14 14:28:20 -08:00
|
|
|
use crate::clean::render_macro_matchers::render_macro_matcher;
|
2019-12-09 17:53:42 +01:00
|
|
|
use crate::clean::{
|
2021-07-05 12:35:02 -04:00
|
|
|
inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item,
|
2021-11-24 12:27:37 -08:00
|
|
|
ItemKind, Lifetime, Path, PathSegment, Primitive, PrimitiveType, Type, TypeBinding, Visibility,
|
2019-12-09 17:53:42 +01:00
|
|
|
};
|
2019-12-22 17:42:04 -05:00
|
|
|
use crate::core::DocContext;
|
2021-04-22 21:23:11 -04:00
|
|
|
use crate::formats::item_type::ItemType;
|
2021-11-19 22:00:37 -05:00
|
|
|
use crate::visit_lib::LibEmbargoVisitor;
|
2019-12-09 17:46:20 +01:00
|
|
|
|
2021-07-05 11:00:27 +02:00
|
|
|
use rustc_ast as ast;
|
2022-01-14 14:28:20 -08:00
|
|
|
use rustc_ast::tokenstream::TokenTree;
|
2021-12-31 11:10:27 +01:00
|
|
|
use rustc_data_structures::thin_vec::ThinVec;
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir as hir;
|
|
|
|
use rustc_hir::def::{DefKind, Res};
|
|
|
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
2020-11-04 13:41:58 +00:00
|
|
|
use rustc_middle::mir::interpret::ConstValue;
|
2020-03-29 17:19:48 +02:00
|
|
|
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
2021-01-24 13:42:14 -05:00
|
|
|
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::symbol::{kw, sym, Symbol};
|
2021-06-13 15:30:05 -07:00
|
|
|
use std::fmt::Write as _;
|
2019-12-11 14:50:19 +01:00
|
|
|
use std::mem;
|
2019-12-09 17:53:42 +01:00
|
|
|
|
2021-04-08 17:18:25 -04:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests;
|
|
|
|
|
2021-02-11 21:29:22 -05:00
|
|
|
crate fn krate(cx: &mut DocContext<'_>) -> Crate {
|
2021-09-12 01:11:22 +02:00
|
|
|
let module = crate::visit_ast::RustdocVisitor::new(cx).visit();
|
2019-12-09 17:46:20 +01:00
|
|
|
|
2021-11-19 22:00:37 -05:00
|
|
|
for &cnum in cx.tcx.crates(()) {
|
|
|
|
// Analyze doc-reachability for extern items
|
|
|
|
LibEmbargoVisitor::new(cx).visit_lib(cnum);
|
|
|
|
}
|
|
|
|
|
2020-02-29 20:16:26 +03:00
|
|
|
// Clean the crate, translating the entire librustc_ast AST to one that is
|
2019-12-09 17:46:20 +01:00
|
|
|
// understood by rustdoc.
|
|
|
|
let mut module = module.clean(cx);
|
|
|
|
|
2020-12-13 11:32:57 -05:00
|
|
|
match *module.kind {
|
2020-11-14 03:45:10 -05:00
|
|
|
ItemKind::ModuleItem(ref module) => {
|
2019-12-09 17:46:20 +01:00
|
|
|
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)
|
2021-04-29 21:36:54 +02:00
|
|
|
|| cx.tcx.is_compiler_builtins(it.def_id.krate()))
|
2019-12-09 17:46:20 +01:00
|
|
|
{
|
2021-04-29 21:36:54 +02:00
|
|
|
cx.cache.masked_crates.insert(it.def_id.krate());
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
|
2021-07-05 12:36:32 -04:00
|
|
|
let local_crate = ExternalCrate { crate_num: LOCAL_CRATE };
|
2021-04-22 19:10:22 -04:00
|
|
|
let primitives = local_crate.primitives(cx.tcx);
|
2021-04-22 19:16:41 -04:00
|
|
|
let keywords = local_crate.keywords(cx.tcx);
|
2019-12-09 17:46:20 +01:00
|
|
|
{
|
2020-12-13 11:32:57 -05:00
|
|
|
let m = match *module.kind {
|
2020-11-14 03:45:10 -05:00
|
|
|
ItemKind::ModuleItem(ref mut m) => m,
|
2019-12-09 17:46:20 +01:00
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
2020-11-23 22:33:10 -05:00
|
|
|
m.items.extend(primitives.iter().map(|&(def_id, prim)| {
|
|
|
|
Item::from_def_id_and_parts(
|
|
|
|
def_id,
|
2020-12-14 19:30:36 -05:00
|
|
|
Some(prim.as_sym()),
|
2020-11-23 22:33:10 -05:00
|
|
|
ItemKind::PrimitiveItem(prim),
|
|
|
|
cx,
|
|
|
|
)
|
2019-12-09 17:46:20 +01:00
|
|
|
}));
|
2020-11-23 22:40:36 -05:00
|
|
|
m.items.extend(keywords.into_iter().map(|(def_id, kw)| {
|
2020-12-29 19:33:48 +01:00
|
|
|
Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::KeywordItem(kw), cx)
|
2019-12-09 17:46:20 +01:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2021-12-18 10:44:58 -06:00
|
|
|
Crate { module, primitives, external_traits: cx.external_traits.clone() }
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
|
|
|
|
2020-12-16 19:14:21 -05:00
|
|
|
fn external_generic_args(
|
|
|
|
cx: &mut DocContext<'_>,
|
2021-09-11 15:43:44 -07:00
|
|
|
did: DefId,
|
2019-12-09 17:46:20 +01:00
|
|
|
has_self: bool,
|
|
|
|
bindings: Vec<TypeBinding>,
|
2020-12-16 19:14:21 -05:00
|
|
|
substs: SubstsRef<'_>,
|
2019-12-09 17:46:20 +01:00
|
|
|
) -> GenericArgs {
|
|
|
|
let mut skip_self = has_self;
|
|
|
|
let mut ty_kind = None;
|
2019-12-22 17:42:04 -05:00
|
|
|
let args: Vec<_> = substs
|
|
|
|
.iter()
|
|
|
|
.filter_map(|kind| match kind.unpack() {
|
2022-01-28 11:25:15 +11:00
|
|
|
GenericArgKind::Lifetime(lt) => match *lt {
|
2020-10-26 14:18:31 -04:00
|
|
|
ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrAnon(_), .. }) => {
|
2020-12-18 13:24:55 -05:00
|
|
|
Some(GenericArg::Lifetime(Lifetime::elided()))
|
|
|
|
}
|
2020-08-07 23:34:44 +01:00
|
|
|
_ => lt.clean(cx).map(GenericArg::Lifetime),
|
|
|
|
},
|
2019-12-22 17:42:04 -05:00
|
|
|
GenericArgKind::Type(_) if skip_self => {
|
|
|
|
skip_self = false;
|
|
|
|
None
|
|
|
|
}
|
|
|
|
GenericArgKind::Type(ty) => {
|
2020-08-04 00:18:29 +02:00
|
|
|
ty_kind = Some(ty.kind());
|
2019-12-22 17:42:04 -05:00
|
|
|
Some(GenericArg::Type(ty.clean(cx)))
|
|
|
|
}
|
2021-09-01 15:26:07 -07:00
|
|
|
GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(ct.clean(cx)))),
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
|
|
|
.collect();
|
2019-12-09 17:46:20 +01:00
|
|
|
|
2021-09-11 15:55:21 -07:00
|
|
|
if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() {
|
2021-09-11 16:01:49 -07:00
|
|
|
let inputs = match ty_kind.unwrap() {
|
|
|
|
ty::Tuple(tys) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
|
2021-12-31 11:10:27 +01:00
|
|
|
_ => return GenericArgs::AngleBracketed { args, bindings: bindings.into() },
|
2021-09-11 15:43:44 -07:00
|
|
|
};
|
|
|
|
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 }
|
|
|
|
} else {
|
2021-12-31 11:10:27 +01:00
|
|
|
GenericArgs::AngleBracketed { args, bindings: bindings.into() }
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-16 19:14:21 -05:00
|
|
|
pub(super) fn external_path(
|
|
|
|
cx: &mut DocContext<'_>,
|
2021-08-24 10:33:41 -07:00
|
|
|
did: DefId,
|
2019-12-22 17:42:04 -05:00
|
|
|
has_self: bool,
|
|
|
|
bindings: Vec<TypeBinding>,
|
2020-12-16 19:14:21 -05:00
|
|
|
substs: SubstsRef<'_>,
|
2019-12-22 17:42:04 -05:00
|
|
|
) -> Path {
|
2021-08-24 10:33:41 -07:00
|
|
|
let def_kind = cx.tcx.def_kind(did);
|
|
|
|
let name = cx.tcx.item_name(did);
|
2019-12-09 17:46:20 +01:00
|
|
|
Path {
|
2021-08-24 10:33:41 -07:00
|
|
|
res: Res::Def(def_kind, did),
|
2019-12-09 17:46:20 +01:00
|
|
|
segments: vec![PathSegment {
|
2020-12-17 14:02:09 +01:00
|
|
|
name,
|
2021-09-11 15:55:21 -07:00
|
|
|
args: external_generic_args(cx, did, has_self, bindings, substs),
|
2019-12-09 17:46:20 +01:00
|
|
|
}],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-03 11:18:47 -07:00
|
|
|
/// Remove the generic arguments from a path.
|
2021-12-12 20:16:18 +03:00
|
|
|
crate fn strip_path_generics(mut path: Path) -> Path {
|
|
|
|
for ps in path.segments.iter_mut() {
|
2021-12-31 11:10:27 +01:00
|
|
|
ps.args = GenericArgs::AngleBracketed { args: vec![], bindings: ThinVec::new() }
|
2021-12-12 20:16:18 +03:00
|
|
|
}
|
2019-12-09 17:46:20 +01:00
|
|
|
|
2021-12-12 20:16:18 +03:00
|
|
|
path
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
|
|
|
|
2021-02-06 16:38:14 +01:00
|
|
|
crate fn qpath_to_string(p: &hir::QPath<'_>) -> String {
|
|
|
|
let segments = match *p {
|
2021-10-01 17:12:39 +02:00
|
|
|
hir::QPath::Resolved(_, path) => &path.segments,
|
|
|
|
hir::QPath::TypeRelative(_, segment) => return segment.ident.to_string(),
|
2021-02-06 16:38:14 +01:00
|
|
|
hir::QPath::LangItem(lang_item, ..) => return lang_item.name().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 {
|
2021-12-15 16:13:11 +11:00
|
|
|
s.push_str(seg.ident.as_str());
|
2021-02-06 16:38:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
s
|
|
|
|
}
|
|
|
|
|
2021-02-12 01:59:20 -05:00
|
|
|
crate fn build_deref_target_impls(cx: &mut DocContext<'_>, items: &[Item], ret: &mut Vec<Item>) {
|
2019-12-09 17:46:20 +01:00
|
|
|
let tcx = cx.tcx;
|
|
|
|
|
|
|
|
for item in items {
|
2020-12-13 11:32:57 -05:00
|
|
|
let target = match *item.kind {
|
2020-11-14 03:45:10 -05:00
|
|
|
ItemKind::TypedefItem(ref t, true) => &t.type_,
|
2019-12-09 17:46:20 +01:00
|
|
|
_ => continue,
|
|
|
|
};
|
2021-01-30 01:02:18 +00:00
|
|
|
|
|
|
|
if let Some(prim) = target.primitive_type() {
|
2021-08-29 21:41:46 +03:00
|
|
|
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_primitive_inherent_impls");
|
2021-01-30 01:02:18 +00:00
|
|
|
for &did in prim.impls(tcx).iter().filter(|did| !did.is_local()) {
|
|
|
|
inline::build_impl(cx, None, did, None, ret);
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
2021-11-24 12:29:58 -08:00
|
|
|
} else if let Type::Path { path } = target {
|
2021-11-11 15:45:45 -08:00
|
|
|
let did = path.def_id();
|
2019-12-09 17:46:20 +01:00
|
|
|
if !did.is_local() {
|
2021-01-30 01:02:18 +00:00
|
|
|
inline::build_impls(cx, None, did, None, ret);
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-06 16:38:14 +01:00
|
|
|
crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
|
|
|
|
use rustc_hir::*;
|
|
|
|
debug!("trying to get a name from pattern: {:?}", p);
|
|
|
|
|
|
|
|
Symbol::intern(&match p.kind {
|
2021-04-04 22:42:19 +01:00
|
|
|
PatKind::Wild | PatKind::Struct(..) => return kw::Underscore,
|
2021-02-06 16:38:14 +01:00
|
|
|
PatKind::Binding(_, _, ident, _) => return ident.name,
|
|
|
|
PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
|
2021-10-01 17:12:39 +02:00
|
|
|
PatKind::Or(pats) => {
|
2021-07-14 16:17:04 -05:00
|
|
|
pats.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(" | ")
|
|
|
|
}
|
2021-10-01 17:12:39 +02:00
|
|
|
PatKind::Tuple(elts, _) => format!(
|
2021-02-06 16:38:14 +01:00
|
|
|
"({})",
|
2021-07-14 16:17:04 -05:00
|
|
|
elts.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(", ")
|
2021-02-06 16:38:14 +01:00
|
|
|
),
|
2021-10-01 17:12:39 +02:00
|
|
|
PatKind::Box(p) => return name_from_pat(&*p),
|
|
|
|
PatKind::Ref(p, _) => return name_from_pat(&*p),
|
2021-02-06 16:38:14 +01:00
|
|
|
PatKind::Lit(..) => {
|
|
|
|
warn!(
|
|
|
|
"tried to get argument name from PatKind::Lit, which is silly in function arguments"
|
|
|
|
);
|
|
|
|
return Symbol::intern("()");
|
|
|
|
}
|
2021-02-09 00:20:44 +01:00
|
|
|
PatKind::Range(..) => return kw::Underscore,
|
2021-10-01 17:12:39 +02:00
|
|
|
PatKind::Slice(begin, ref mid, end) => {
|
2021-07-14 16:17:04 -05:00
|
|
|
let begin = begin.iter().map(|p| name_from_pat(p).to_string());
|
2021-02-06 16:38:14 +01:00
|
|
|
let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
|
2021-07-14 16:17:04 -05:00
|
|
|
let end = end.iter().map(|p| name_from_pat(p).to_string());
|
2021-02-06 16:38:14 +01:00
|
|
|
format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-02-02 14:24:45 +11:00
|
|
|
crate fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
|
|
|
|
match n.val() {
|
2022-01-12 03:19:52 +00:00
|
|
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => {
|
2020-07-02 23:13:32 +02:00
|
|
|
let mut s = if let Some(def) = def.as_local() {
|
2020-08-12 12:22:56 +02:00
|
|
|
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did);
|
2021-02-11 20:37:36 +01:00
|
|
|
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(hir_id))
|
2019-12-09 17:46:20 +01:00
|
|
|
} else {
|
2021-03-07 18:09:35 +01:00
|
|
|
inline::print_inlined_const(cx.tcx, def.did)
|
2019-11-22 17:26:09 -03:00
|
|
|
};
|
|
|
|
if let Some(promoted) = promoted {
|
2019-12-13 16:23:23 -03:00
|
|
|
s.push_str(&format!("::{:?}", promoted))
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
2019-11-22 17:26:09 -03:00
|
|
|
s
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2019-12-09 17:46:20 +01:00
|
|
|
_ => {
|
|
|
|
let mut s = n.to_string();
|
|
|
|
// array lengths are obviously usize
|
2020-06-19 18:57:15 +02:00
|
|
|
if s.ends_with("_usize") {
|
|
|
|
let n = s.len() - "_usize".len();
|
2019-12-09 17:46:20 +01:00
|
|
|
s.truncate(n);
|
|
|
|
if s.ends_with(": ") {
|
|
|
|
let n = s.len() - ": ".len();
|
|
|
|
s.truncate(n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-07 18:09:35 +01:00
|
|
|
crate fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<String> {
|
|
|
|
tcx.const_eval_poly(def_id).ok().and_then(|val| {
|
|
|
|
let ty = tcx.type_of(def_id);
|
2020-08-04 00:18:29 +02:00
|
|
|
match (val, ty.kind()) {
|
2020-02-15 11:56:23 +13:00
|
|
|
(_, &ty::Ref(..)) => None,
|
|
|
|
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
|
|
|
|
(ConstValue::Scalar(_), _) => {
|
2021-03-07 18:09:35 +01:00
|
|
|
let const_ = ty::Const::from_value(tcx, val, ty);
|
|
|
|
Some(print_const_with_custom_print_scalar(tcx, const_))
|
2019-12-11 14:50:19 +01:00
|
|
|
}
|
|
|
|
_ => None,
|
2020-02-15 11:56:23 +13:00
|
|
|
}
|
2020-03-22 00:20:58 +01:00
|
|
|
})
|
2019-12-11 14:50:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn format_integer_with_underscore_sep(num: &str) -> String {
|
|
|
|
let num_chars: Vec<_> = num.chars().collect();
|
2021-04-08 17:18:25 -04:00
|
|
|
let mut num_start_index = if num_chars.get(0) == Some(&'-') { 1 } else { 0 };
|
|
|
|
let chunk_size = match num[num_start_index..].as_bytes() {
|
|
|
|
[b'0', b'b' | b'x', ..] => {
|
|
|
|
num_start_index += 2;
|
|
|
|
4
|
|
|
|
}
|
|
|
|
[b'0', b'o', ..] => {
|
|
|
|
num_start_index += 2;
|
|
|
|
let remaining_chars = num_chars.len() - num_start_index;
|
|
|
|
if remaining_chars <= 6 {
|
|
|
|
// don't add underscores to Unix permissions like 0755 or 100755
|
|
|
|
return num.to_string();
|
|
|
|
}
|
|
|
|
3
|
|
|
|
}
|
|
|
|
_ => 3,
|
|
|
|
};
|
2019-12-11 14:50:19 +01:00
|
|
|
|
|
|
|
num_chars[..num_start_index]
|
|
|
|
.iter()
|
2021-04-08 17:18:25 -04:00
|
|
|
.chain(num_chars[num_start_index..].rchunks(chunk_size).rev().intersperse(&['_']).flatten())
|
2019-12-11 14:50:19 +01:00
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2022-02-02 14:24:45 +11:00
|
|
|
fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: ty::Const<'_>) -> String {
|
2019-12-11 14:50:19 +01:00
|
|
|
// Use a slightly different format for integer types which always shows the actual value.
|
|
|
|
// For all other types, fallback to the original `pretty_print_const`.
|
2022-02-02 14:24:45 +11:00
|
|
|
match (ct.val(), ct.ty().kind()) {
|
2020-09-26 15:15:35 +02:00
|
|
|
(ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Uint(ui)) => {
|
2022-02-17 17:58:38 +01:00
|
|
|
format!(
|
|
|
|
"{}{}",
|
|
|
|
format_integer_with_underscore_sep(&int.rustdoc_display()),
|
|
|
|
ui.name_str()
|
|
|
|
)
|
2019-12-11 14:50:19 +01:00
|
|
|
}
|
2020-09-26 15:15:35 +02:00
|
|
|
(ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Int(i)) => {
|
2022-02-02 14:24:45 +11:00
|
|
|
let ty = tcx.lift(ct.ty()).unwrap();
|
2021-03-07 18:09:35 +01:00
|
|
|
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
|
2020-09-26 15:15:35 +02:00
|
|
|
let data = int.assert_bits(size);
|
2020-11-04 13:41:58 +00:00
|
|
|
let sign_extended_data = size.sign_extend(data) as i128;
|
2019-12-11 14:50:19 +01:00
|
|
|
|
|
|
|
format!(
|
|
|
|
"{}{}",
|
|
|
|
format_integer_with_underscore_sep(&sign_extended_data.to_string()),
|
|
|
|
i.name_str()
|
|
|
|
)
|
|
|
|
}
|
|
|
|
_ => ct.to_string(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-07 18:09:35 +01:00
|
|
|
crate fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
|
|
|
|
if let hir::Node::Expr(expr) = tcx.hir().get(hir_id) {
|
2019-12-11 14:50:19 +01:00
|
|
|
if let hir::ExprKind::Lit(_) = &expr.kind {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-02-09 11:15:53 +03:00
|
|
|
if let hir::ExprKind::Unary(hir::UnOp::Neg, expr) = &expr.kind {
|
2019-12-11 14:50:19 +01:00
|
|
|
if let hir::ExprKind::Lit(_) = &expr.kind {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2021-02-11 20:37:36 +01:00
|
|
|
crate fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String {
|
|
|
|
let hir = tcx.hir();
|
|
|
|
let value = &hir.body(body).value;
|
2019-12-11 14:50:19 +01:00
|
|
|
|
|
|
|
let snippet = if !value.span.from_expansion() {
|
2021-02-11 20:37:36 +01:00
|
|
|
tcx.sess.source_map().span_to_snippet(value.span).ok()
|
2019-12-11 14:50:19 +01:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2021-02-11 20:37:36 +01:00
|
|
|
snippet.unwrap_or_else(|| rustc_hir_pretty::id_to_string(&hir, body.hir_id))
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Given a type Path, resolve it to a Type using the TyCtxt
|
2021-08-26 17:47:29 -07:00
|
|
|
crate fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
|
|
|
|
debug!("resolve_type({:?})", path);
|
2019-12-09 17:46:20 +01:00
|
|
|
|
2021-08-22 20:08:48 -07:00
|
|
|
match path.res {
|
|
|
|
Res::PrimTy(p) => Primitive(PrimitiveType::from(p)),
|
2022-02-09 11:03:27 +00:00
|
|
|
Res::SelfTy { .. } if path.segments.len() == 1 => Generic(kw::SelfUpper),
|
2021-08-22 20:08:48 -07:00
|
|
|
Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name),
|
|
|
|
_ => {
|
2021-11-11 15:45:45 -08:00
|
|
|
let _ = register_res(cx, path.res);
|
2021-11-24 12:29:58 -08:00
|
|
|
Type::Path { path }
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
2021-08-22 20:08:48 -07:00
|
|
|
}
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
|
|
|
|
2020-11-14 17:59:58 -05:00
|
|
|
crate fn get_auto_trait_and_blanket_impls(
|
2021-12-28 14:27:31 -08:00
|
|
|
cx: &mut DocContext<'_>,
|
2021-01-24 13:42:14 -05:00
|
|
|
item_def_id: DefId,
|
2019-12-09 17:46:20 +01:00
|
|
|
) -> impl Iterator<Item = Item> {
|
2021-01-22 14:33:21 -05:00
|
|
|
let auto_impls = cx
|
|
|
|
.sess()
|
|
|
|
.prof
|
|
|
|
.generic_activity("get_auto_trait_impls")
|
2021-01-24 13:42:14 -05:00
|
|
|
.run(|| AutoTraitFinder::new(cx).get_auto_trait_impls(item_def_id));
|
2021-01-22 14:33:21 -05:00
|
|
|
let blanket_impls = cx
|
|
|
|
.sess()
|
|
|
|
.prof
|
|
|
|
.generic_activity("get_blanket_impls")
|
2021-01-24 13:42:14 -05:00
|
|
|
.run(|| BlanketImplFinder { cx }.get_blanket_impls(item_def_id));
|
2020-12-15 23:51:38 -05:00
|
|
|
auto_impls.into_iter().chain(blanket_impls)
|
2019-12-09 17:46:20 +01:00
|
|
|
}
|
|
|
|
|
2021-05-03 14:57:51 -04:00
|
|
|
/// If `res` has a documentation page associated, store it in the cache.
|
|
|
|
///
|
|
|
|
/// This is later used by [`href()`] to determine the HTML link for the item.
|
|
|
|
///
|
|
|
|
/// [`href()`]: crate::html::format::href
|
2021-02-12 01:59:20 -05:00
|
|
|
crate fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
|
2021-05-03 14:57:51 -04:00
|
|
|
use DefKind::*;
|
2019-12-09 17:46:20 +01:00
|
|
|
debug!("register_res({:?})", res);
|
|
|
|
|
|
|
|
let (did, kind) = match res {
|
2021-11-24 18:32:03 -05:00
|
|
|
// These should be added to the cache using `record_extern_fqn`.
|
2021-05-03 14:57:51 -04:00
|
|
|
Res::Def(
|
2021-11-30 13:08:41 -05:00
|
|
|
kind @ (AssocTy | AssocFn | AssocConst | Variant | Fn | TyAlias | Enum | Trait | Struct
|
2021-11-11 15:05:25 -08:00
|
|
|
| Union | Mod | ForeignTy | Const | Static | Macro(..) | TraitAlias),
|
2021-05-03 14:57:51 -04:00
|
|
|
i,
|
|
|
|
) => (i, kind.into()),
|
2022-02-14 11:27:30 +00:00
|
|
|
// This is part of a trait definition or trait impl; document the trait.
|
2022-02-09 11:03:27 +00:00
|
|
|
Res::SelfTy { trait_: Some(trait_def_id), alias_to: _ } => (trait_def_id, ItemType::Trait),
|
2022-02-14 11:27:30 +00:00
|
|
|
// This is an inherent impl or a type definition; it doesn't have its own page.
|
|
|
|
Res::SelfTy { trait_: None, alias_to: Some((item_def_id, _)) } => return item_def_id,
|
2022-02-09 11:03:27 +00:00
|
|
|
Res::SelfTy { trait_: None, alias_to: None }
|
2021-05-03 14:57:51 -04:00
|
|
|
| Res::PrimTy(_)
|
|
|
|
| Res::ToolMod
|
|
|
|
| Res::SelfCtor(_)
|
|
|
|
| Res::Local(_)
|
|
|
|
| Res::NonMacroAttr(_)
|
|
|
|
| Res::Err => return res.def_id(),
|
|
|
|
Res::Def(
|
2021-10-02 12:59:26 +01:00
|
|
|
TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst
|
|
|
|
| InlineConst | OpaqueTy | Field | LifetimeParam | GlobalAsm | Impl | Closure
|
|
|
|
| Generator,
|
2021-05-03 14:57:51 -04:00
|
|
|
id,
|
|
|
|
) => return id,
|
2019-12-09 17:46:20 +01:00
|
|
|
};
|
2019-12-22 17:42:04 -05:00
|
|
|
if did.is_local() {
|
|
|
|
return did;
|
|
|
|
}
|
2019-12-09 17:46:20 +01:00
|
|
|
inline::record_extern_fqn(cx, did, kind);
|
2021-04-22 21:23:11 -04:00
|
|
|
if let ItemType::Trait = kind {
|
2019-12-09 17:46:20 +01:00
|
|
|
inline::record_extern_trait(cx, did);
|
|
|
|
}
|
|
|
|
did
|
|
|
|
}
|
|
|
|
|
2021-02-12 01:59:20 -05:00
|
|
|
crate fn resolve_use_source(cx: &mut DocContext<'_>, path: Path) -> ImportSource {
|
2019-12-09 17:46:20 +01:00
|
|
|
ImportSource {
|
2019-12-22 17:42:04 -05:00
|
|
|
did: if path.res.opt_def_id().is_none() { None } else { Some(register_res(cx, path.res)) },
|
2019-12-09 17:46:20 +01:00
|
|
|
path,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-12 01:59:20 -05:00
|
|
|
crate fn enter_impl_trait<F, R>(cx: &mut DocContext<'_>, f: F) -> R
|
2019-12-09 17:46:20 +01:00
|
|
|
where
|
2021-02-12 01:59:20 -05:00
|
|
|
F: FnOnce(&mut DocContext<'_>) -> R,
|
2019-12-09 17:46:20 +01:00
|
|
|
{
|
2021-02-19 14:27:30 -08:00
|
|
|
let old_bounds = mem::take(&mut cx.impl_trait_bounds);
|
2021-02-12 01:59:20 -05:00
|
|
|
let r = f(cx);
|
2021-02-19 14:27:30 -08:00
|
|
|
assert!(cx.impl_trait_bounds.is_empty());
|
|
|
|
cx.impl_trait_bounds = old_bounds;
|
2019-12-09 17:46:20 +01:00
|
|
|
r
|
|
|
|
}
|
2020-12-25 15:38:46 -08:00
|
|
|
|
2020-12-30 16:38:25 -08:00
|
|
|
/// Find the nearest parent module of a [`DefId`].
|
|
|
|
crate fn find_nearest_parent_module(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
|
|
|
|
if def_id.is_top_level_module() {
|
|
|
|
// The crate root has no parent. Use it as the root instead.
|
|
|
|
Some(def_id)
|
2020-12-25 16:33:15 -08:00
|
|
|
} else {
|
|
|
|
let mut current = def_id;
|
|
|
|
// The immediate parent might not always be a module.
|
|
|
|
// Find the first parent which is.
|
2020-12-25 16:35:28 -08:00
|
|
|
while let Some(parent) = tcx.parent(current) {
|
|
|
|
if tcx.def_kind(parent) == DefKind::Mod {
|
|
|
|
return Some(parent);
|
2020-12-25 15:38:46 -08:00
|
|
|
}
|
2020-12-25 16:35:28 -08:00
|
|
|
current = parent;
|
2020-12-25 15:38:46 -08:00
|
|
|
}
|
2020-12-25 16:35:28 -08:00
|
|
|
None
|
2020-12-25 15:38:46 -08:00
|
|
|
}
|
|
|
|
}
|
2021-01-28 17:05:22 +01:00
|
|
|
|
2021-02-14 14:47:55 +01:00
|
|
|
/// Checks for the existence of `hidden` in the attribute below if `flag` is `sym::hidden`:
|
2021-01-28 17:05:22 +01:00
|
|
|
///
|
2021-02-14 14:47:55 +01:00
|
|
|
/// ```
|
|
|
|
/// #[doc(hidden)]
|
|
|
|
/// pub fn foo() {}
|
2021-01-28 17:05:22 +01:00
|
|
|
/// ```
|
|
|
|
///
|
2021-02-14 14:47:55 +01:00
|
|
|
/// This function exists because it runs on `hir::Attributes` whereas the other is a
|
|
|
|
/// `clean::Attributes` method.
|
2021-02-23 22:13:48 +01:00
|
|
|
crate fn has_doc_flag(attrs: ty::Attributes<'_>, flag: Symbol) -> bool {
|
2021-01-28 17:05:22 +01:00
|
|
|
attrs.iter().any(|attr| {
|
|
|
|
attr.has_name(sym::doc)
|
2021-02-12 13:55:34 +01:00
|
|
|
&& attr.meta_item_list().map_or(false, |l| rustc_attr::list_contains_name(&l, flag))
|
2021-01-28 17:05:22 +01:00
|
|
|
})
|
|
|
|
}
|
2021-05-04 23:36:33 -04:00
|
|
|
|
2021-05-04 23:36:33 -04:00
|
|
|
/// A link to `doc.rust-lang.org` that includes the channel name. Use this instead of manual links
|
|
|
|
/// so that the channel is consistent.
|
2021-05-04 23:36:33 -04:00
|
|
|
///
|
|
|
|
/// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
|
2021-10-01 17:12:39 +02:00
|
|
|
crate const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL");
|
2021-06-13 15:30:05 -07:00
|
|
|
|
|
|
|
/// Render a sequence of macro arms in a format suitable for displaying to the user
|
|
|
|
/// as part of an item declaration.
|
|
|
|
pub(super) fn render_macro_arms<'a>(
|
2021-12-28 13:43:08 -08:00
|
|
|
tcx: TyCtxt<'_>,
|
2021-06-13 15:30:05 -07:00
|
|
|
matchers: impl Iterator<Item = &'a TokenTree>,
|
|
|
|
arm_delim: &str,
|
|
|
|
) -> String {
|
|
|
|
let mut out = String::new();
|
|
|
|
for matcher in matchers {
|
2021-12-28 13:43:08 -08:00
|
|
|
writeln!(out, " {} => {{ ... }}{}", render_macro_matcher(tcx, matcher), arm_delim)
|
2021-12-27 13:44:14 -08:00
|
|
|
.unwrap();
|
2021-06-13 15:30:05 -07:00
|
|
|
}
|
|
|
|
out
|
|
|
|
}
|
|
|
|
|
2021-07-05 11:00:27 +02:00
|
|
|
pub(super) fn display_macro_source(
|
|
|
|
cx: &mut DocContext<'_>,
|
|
|
|
name: Symbol,
|
|
|
|
def: &ast::MacroDef,
|
|
|
|
def_id: DefId,
|
2021-11-12 13:40:20 -08:00
|
|
|
vis: Visibility,
|
2021-07-05 11:00:27 +02:00
|
|
|
) -> String {
|
|
|
|
let tts: Vec<_> = def.body.inner_tokens().into_trees().collect();
|
|
|
|
// Extract the spans of all matchers. They represent the "interface" of the macro.
|
|
|
|
let matchers = tts.chunks(4).map(|arm| &arm[0]);
|
|
|
|
|
|
|
|
if def.macro_rules {
|
2021-12-28 13:43:08 -08:00
|
|
|
format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(cx.tcx, matchers, ";"))
|
2021-07-05 11:00:27 +02:00
|
|
|
} else {
|
|
|
|
if matchers.len() <= 1 {
|
|
|
|
format!(
|
|
|
|
"{}macro {}{} {{\n ...\n}}",
|
|
|
|
vis.to_src_with_space(cx.tcx, def_id),
|
|
|
|
name,
|
2021-12-28 13:43:08 -08:00
|
|
|
matchers.map(|matcher| render_macro_matcher(cx.tcx, matcher)).collect::<String>(),
|
2021-07-05 11:00:27 +02:00
|
|
|
)
|
|
|
|
} else {
|
|
|
|
format!(
|
|
|
|
"{}macro {} {{\n{}}}",
|
|
|
|
vis.to_src_with_space(cx.tcx, def_id),
|
|
|
|
name,
|
2021-12-28 13:43:08 -08:00
|
|
|
render_macro_arms(cx.tcx, matchers, ","),
|
2021-07-05 11:00:27 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|