2019-12-09 17:53:42 +01: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::{
|
2022-08-08 18:00:42 +02:00
|
|
|
|
clean_doc_module, clean_middle_const, clean_middle_region, clean_middle_ty, inline, Crate,
|
|
|
|
|
ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path,
|
2022-11-02 15:23:25 +01:00
|
|
|
|
PathSegment, Primitive, PrimitiveType, Term, Type, TypeBinding, TypeBindingKind,
|
2019-12-09 17:53:42 +01:00
|
|
|
|
};
|
|
|
|
|
use crate::core::DocContext;
|
2022-11-03 18:15:24 +01:00
|
|
|
|
use crate::html::format::visibility_to_src_with_space;
|
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;
|
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};
|
2022-06-03 20:42:35 +02:00
|
|
|
|
use rustc_middle::mir;
|
|
|
|
|
use rustc_middle::mir::interpret::ConstValue;
|
2020-03-29 17:19:48 +02:00
|
|
|
|
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
2023-02-22 19:51:17 +04:00
|
|
|
|
use rustc_middle::ty::{self, 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;
|
2022-11-05 09:02:10 -07:00
|
|
|
|
use thin_vec::{thin_vec, ThinVec};
|
2019-12-09 17:53:42 +01:00
|
|
|
|
|
2021-04-08 17:18:25 -04:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests;
|
|
|
|
|
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(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
|
|
|
|
|
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.
|
2022-08-08 18:00:42 +02:00
|
|
|
|
let mut module = clean_doc_module(&module, cx);
|
2019-12-09 17:46:20 +01:00
|
|
|
|
|
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)
|
2022-04-16 14:28:09 +02:00
|
|
|
|
|| cx.tcx.is_compiler_builtins(it.item_id.krate()))
|
2019-12-09 17:46:20 +01:00
|
|
|
|
{
|
2022-04-16 14:28:09 +02:00
|
|
|
|
cx.cache.masked_crates.insert(it.item_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
|
|
|
|
{
|
2022-02-19 00:43:47 +01:00
|
|
|
|
let ItemKind::ModuleItem(ref mut m) = *module.kind
|
|
|
|
|
else { 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)| {
|
2022-07-21 16:05:17 +02:00
|
|
|
|
Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::KeywordItem, cx)
|
2019-12-09 17:46:20 +01:00
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-27 16:31:34 +01:00
|
|
|
|
Crate { module, external_traits: cx.external_traits.clone() }
|
2019-12-09 17:46:20 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-22 12:40:26 -07:00
|
|
|
|
pub(crate) fn substs_to_args<'tcx>(
|
|
|
|
|
cx: &mut DocContext<'tcx>,
|
2022-12-12 13:20:36 +00:00
|
|
|
|
substs: ty::Binder<'tcx, &[ty::subst::GenericArg<'tcx>]>,
|
2022-03-06 15:56:29 -08:00
|
|
|
|
mut skip_first: bool,
|
|
|
|
|
) -> Vec<GenericArg> {
|
2022-05-20 08:48:17 -07:00
|
|
|
|
let mut ret_val =
|
2022-12-12 13:20:36 +00:00
|
|
|
|
Vec::with_capacity(substs.skip_binder().len().saturating_sub(if skip_first {
|
|
|
|
|
1
|
|
|
|
|
} else {
|
|
|
|
|
0
|
|
|
|
|
}));
|
|
|
|
|
ret_val.extend(substs.iter().filter_map(|kind| match kind.skip_binder().unpack() {
|
2022-06-04 11:53:34 +02:00
|
|
|
|
GenericArgKind::Lifetime(lt) => {
|
2022-08-03 11:35:32 +02:00
|
|
|
|
Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
|
2022-06-04 11:53:34 +02:00
|
|
|
|
}
|
2022-05-20 08:48:17 -07:00
|
|
|
|
GenericArgKind::Type(_) if skip_first => {
|
|
|
|
|
skip_first = false;
|
|
|
|
|
None
|
|
|
|
|
}
|
2022-12-12 12:55:47 +00:00
|
|
|
|
GenericArgKind::Type(ty) => {
|
2022-12-12 13:20:36 +00:00
|
|
|
|
Some(GenericArg::Type(clean_middle_ty(kind.rebind(ty), cx, None)))
|
2022-12-12 12:55:47 +00:00
|
|
|
|
}
|
|
|
|
|
GenericArgKind::Const(ct) => {
|
2022-12-12 13:20:36 +00:00
|
|
|
|
Some(GenericArg::Const(Box::new(clean_middle_const(kind.rebind(ct), cx))))
|
2022-12-12 12:55:47 +00:00
|
|
|
|
}
|
2022-05-20 08:48:17 -07:00
|
|
|
|
}));
|
|
|
|
|
ret_val
|
2022-03-06 15:56:29 -08:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-22 12:40:26 -07:00
|
|
|
|
fn external_generic_args<'tcx>(
|
|
|
|
|
cx: &mut DocContext<'tcx>,
|
2022-03-06 15:56:29 -08:00
|
|
|
|
did: DefId,
|
|
|
|
|
has_self: bool,
|
2022-08-17 14:22:30 +10:00
|
|
|
|
bindings: ThinVec<TypeBinding>,
|
2022-12-12 13:20:36 +00:00
|
|
|
|
substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
|
2022-03-06 15:56:29 -08:00
|
|
|
|
) -> GenericArgs {
|
2022-12-12 13:20:36 +00:00
|
|
|
|
let args = substs_to_args(cx, substs.map_bound(|substs| &substs[..]), has_self);
|
2019-12-09 17:46:20 +01:00
|
|
|
|
|
2022-11-22 18:12:12 +00:00
|
|
|
|
if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
|
2022-12-12 13:20:36 +00:00
|
|
|
|
let ty = substs
|
|
|
|
|
.iter()
|
|
|
|
|
.nth(if has_self { 1 } else { 0 })
|
|
|
|
|
.unwrap()
|
|
|
|
|
.map_bound(|arg| arg.expect_ty());
|
2022-03-06 15:56:29 -08:00
|
|
|
|
let inputs =
|
|
|
|
|
// The trait's first substitution is the one after self, if there is one.
|
2022-12-12 13:20:36 +00:00
|
|
|
|
match ty.skip_binder().kind() {
|
|
|
|
|
ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None)).collect::<Vec<_>>().into(),
|
2022-08-17 14:22:30 +10:00
|
|
|
|
_ => return GenericArgs::AngleBracketed { args: args.into(), bindings },
|
2022-03-06 15:56:29 -08:00
|
|
|
|
};
|
2022-11-02 15:23:25 +01:00
|
|
|
|
let output = bindings.into_iter().next().and_then(|binding| match binding.kind {
|
|
|
|
|
TypeBindingKind::Equality { term: Term::Type(ty) } if ty != Type::Tuple(Vec::new()) => {
|
|
|
|
|
Some(Box::new(ty))
|
|
|
|
|
}
|
|
|
|
|
_ => None,
|
|
|
|
|
});
|
2021-09-11 15:43:44 -07:00
|
|
|
|
GenericArgs::Parenthesized { inputs, output }
|
|
|
|
|
} else {
|
2023-02-16 00:19:16 +01:00
|
|
|
|
GenericArgs::AngleBracketed { args: args.into(), bindings }
|
2019-12-09 17:46:20 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-22 12:40:26 -07:00
|
|
|
|
pub(super) fn external_path<'tcx>(
|
|
|
|
|
cx: &mut DocContext<'tcx>,
|
2021-08-24 10:33:41 -07:00
|
|
|
|
did: DefId,
|
2019-12-09 17:57:02 +01:00
|
|
|
|
has_self: bool,
|
2022-08-17 14:22:30 +10:00
|
|
|
|
bindings: ThinVec<TypeBinding>,
|
2022-12-12 13:20:36 +00:00
|
|
|
|
substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
|
2019-12-09 17:57:02 +01: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),
|
2022-11-05 09:02:10 -07:00
|
|
|
|
segments: thin_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.
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(crate) fn strip_path_generics(mut path: Path) -> Path {
|
2021-12-12 20:16:18 +03:00
|
|
|
|
for ps in path.segments.iter_mut() {
|
2022-05-19 16:26:28 -07:00
|
|
|
|
ps.args = GenericArgs::AngleBracketed { args: Default::default(), 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
|
|
|
|
}
|
|
|
|
|
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(crate) fn qpath_to_string(p: &hir::QPath<'_>) -> String {
|
2021-02-06 16:38:14 +01:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(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 {
|
2022-03-29 19:30:54 +02:00
|
|
|
|
ItemKind::AssocTypeItem(ref t, _) => &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");
|
2022-03-18 11:45:00 +01:00
|
|
|
|
for did in prim.impls(tcx).filter(|did| !did.is_local()) {
|
2023-03-18 19:18:51 +04:00
|
|
|
|
inline::build_impl(cx, 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() {
|
2023-03-18 19:18:51 +04:00
|
|
|
|
inline::build_impls(cx, did, None, ret);
|
2019-12-09 17:46:20 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
|
2021-02-06 16:38:14 +01:00
|
|
|
|
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-05-20 21:06:44 -04:00
|
|
|
|
pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
|
2022-06-10 11:18:06 +10:00
|
|
|
|
match n.kind() {
|
2022-09-22 12:34:23 +02:00
|
|
|
|
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs: _ }) => {
|
2022-07-28 11:06:16 +02:00
|
|
|
|
let s = if let Some(def) = def.as_local() {
|
2022-05-08 15:53:19 +02:00
|
|
|
|
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def))
|
2019-12-09 17:46:20 +01:00
|
|
|
|
} else {
|
2022-05-08 15:53:19 +02:00
|
|
|
|
inline::print_inlined_const(cx.tcx, def)
|
2019-11-22 17:26:09 -03:00
|
|
|
|
};
|
2022-06-27 16:32:47 +02:00
|
|
|
|
|
2019-11-22 17:26:09 -03:00
|
|
|
|
s
|
2019-12-09 17:46:20 +01:00
|
|
|
|
}
|
2022-11-05 16:55:40 -07:00
|
|
|
|
// array lengths are obviously usize
|
|
|
|
|
ty::ConstKind::Value(ty::ValTree::Leaf(scalar))
|
|
|
|
|
if *n.ty().kind() == ty::Uint(ty::UintTy::Usize) =>
|
|
|
|
|
{
|
|
|
|
|
scalar.to_string()
|
2019-12-09 17:46:20 +01:00
|
|
|
|
}
|
2022-11-05 16:55:40 -07:00
|
|
|
|
_ => n.to_string(),
|
2019-12-09 17:46:20 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-03 19:36:28 +01:00
|
|
|
|
pub(crate) fn print_evaluated_const(
|
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
|
def_id: DefId,
|
|
|
|
|
underscores_and_type: bool,
|
|
|
|
|
) -> Option<String> {
|
2022-06-03 20:42:35 +02:00
|
|
|
|
tcx.const_eval_poly(def_id).ok().and_then(|val| {
|
2023-02-07 01:29:48 -07:00
|
|
|
|
let ty = tcx.type_of(def_id).subst_identity();
|
2020-08-04 00:18:29 +02:00
|
|
|
|
match (val, ty.kind()) {
|
2020-02-15 11:56:23 +13:00
|
|
|
|
(_, &ty::Ref(..)) => None,
|
2022-06-03 20:42:35 +02:00
|
|
|
|
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
|
|
|
|
|
(ConstValue::Scalar(_), _) => {
|
|
|
|
|
let const_ = mir::ConstantKind::from_value(val, ty);
|
2022-09-03 19:36:28 +01:00
|
|
|
|
Some(print_const_with_custom_print_scalar(tcx, const_, underscores_and_type))
|
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-10-09 09:07:03 +00:00
|
|
|
|
fn print_const_with_custom_print_scalar<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
ct: mir::ConstantKind<'tcx>,
|
2022-09-03 19:36:28 +01:00
|
|
|
|
underscores_and_type: bool,
|
|
|
|
|
) -> 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-06-03 20:42:35 +02:00
|
|
|
|
match (ct, ct.ty().kind()) {
|
|
|
|
|
(mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Uint(ui)) => {
|
2022-09-03 19:36:28 +01:00
|
|
|
|
if underscores_and_type {
|
|
|
|
|
format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
|
|
|
|
|
} else {
|
|
|
|
|
int.to_string()
|
|
|
|
|
}
|
2019-12-11 14:50:19 +01:00
|
|
|
|
}
|
2022-06-03 20:42:35 +02:00
|
|
|
|
(mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Int(i)) => {
|
2022-10-09 09:07:03 +00:00
|
|
|
|
let ty = ct.ty();
|
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;
|
2022-09-03 19:36:28 +01:00
|
|
|
|
if underscores_and_type {
|
|
|
|
|
format!(
|
|
|
|
|
"{}{}",
|
|
|
|
|
format_integer_with_underscore_sep(&sign_extended_data.to_string()),
|
|
|
|
|
i.name_str()
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
sign_extended_data.to_string()
|
|
|
|
|
}
|
2019-12-11 14:50:19 +01:00
|
|
|
|
}
|
|
|
|
|
_ => ct.to_string(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(crate) fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
|
2021-03-07 18:09:35 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-15 11:30:14 +01:00
|
|
|
|
if let hir::ExprKind::Unary(hir::UnOp::Neg, expr) = &expr.kind &&
|
|
|
|
|
let hir::ExprKind::Lit(_) = &expr.kind
|
|
|
|
|
{
|
|
|
|
|
return true;
|
2019-12-11 14:50:19 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-23 17:19:56 +02:00
|
|
|
|
/// Build a textual representation of an unevaluated constant expression.
|
|
|
|
|
///
|
|
|
|
|
/// If the const expression is too complex, an underscore `_` is returned.
|
|
|
|
|
/// For const arguments, it's `{ _ }` to be precise.
|
|
|
|
|
/// This means that the output is not necessarily valid Rust code.
|
|
|
|
|
///
|
|
|
|
|
/// Currently, only
|
|
|
|
|
///
|
|
|
|
|
/// * literals (optionally with a leading `-`)
|
|
|
|
|
/// * unit `()`
|
|
|
|
|
/// * blocks (`{ … }`) around simple expressions and
|
|
|
|
|
/// * paths without arguments
|
|
|
|
|
///
|
|
|
|
|
/// are considered simple enough. Simple blocks are included since they are
|
|
|
|
|
/// necessary to disambiguate unit from the unit type.
|
|
|
|
|
/// This list might get extended in the future.
|
|
|
|
|
///
|
|
|
|
|
/// Without this censoring, in a lot of cases the output would get too large
|
|
|
|
|
/// and verbose. Consider `match` expressions, blocks and deeply nested ADTs.
|
|
|
|
|
/// Further, private and `doc(hidden)` fields of structs would get leaked
|
|
|
|
|
/// since HIR datatypes like the `body` parameter do not contain enough
|
|
|
|
|
/// semantic information for this function to be able to hide them –
|
|
|
|
|
/// at least not without significant performance overhead.
|
|
|
|
|
///
|
|
|
|
|
/// Whenever possible, prefer to evaluate the constant first and try to
|
|
|
|
|
/// use a different method for pretty-printing. Ideally this function
|
|
|
|
|
/// should only ever be used as a fallback.
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(crate) fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String {
|
2021-02-11 20:37:36 +01:00
|
|
|
|
let hir = tcx.hir();
|
|
|
|
|
let value = &hir.body(body).value;
|
2019-12-11 14:50:19 +01:00
|
|
|
|
|
2022-06-23 17:19:56 +02:00
|
|
|
|
#[derive(PartialEq, Eq)]
|
|
|
|
|
enum Classification {
|
|
|
|
|
Literal,
|
|
|
|
|
Simple,
|
|
|
|
|
Complex,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
use Classification::*;
|
|
|
|
|
|
|
|
|
|
fn classify(expr: &hir::Expr<'_>) -> Classification {
|
|
|
|
|
match &expr.kind {
|
|
|
|
|
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
|
|
|
|
|
if matches!(expr.kind, hir::ExprKind::Lit(_)) { Literal } else { Complex }
|
|
|
|
|
}
|
|
|
|
|
hir::ExprKind::Lit(_) => Literal,
|
|
|
|
|
hir::ExprKind::Tup([]) => Simple,
|
|
|
|
|
hir::ExprKind::Block(hir::Block { stmts: [], expr: Some(expr), .. }, _) => {
|
|
|
|
|
if classify(expr) == Complex { Complex } else { Simple }
|
|
|
|
|
}
|
|
|
|
|
// Paths with a self-type or arguments are too “complex” following our measure since
|
|
|
|
|
// they may leak private fields of structs (with feature `adt_const_params`).
|
|
|
|
|
// Consider: `<Self as Trait<{ Struct { private: () } }>>::CONSTANT`.
|
|
|
|
|
// Paths without arguments are definitely harmless though.
|
|
|
|
|
hir::ExprKind::Path(hir::QPath::Resolved(_, hir::Path { segments, .. })) => {
|
|
|
|
|
if segments.iter().all(|segment| segment.args.is_none()) { Simple } else { Complex }
|
|
|
|
|
}
|
|
|
|
|
// FIXME: Claiming that those kinds of QPaths are simple is probably not true if the Ty
|
|
|
|
|
// contains const arguments. Is there a *concise* way to check for this?
|
|
|
|
|
hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => Simple,
|
|
|
|
|
// FIXME: Can they contain const arguments and thus leak private struct fields?
|
|
|
|
|
hir::ExprKind::Path(hir::QPath::LangItem(..)) => Simple,
|
|
|
|
|
_ => Complex,
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-12-11 14:50:19 +01:00
|
|
|
|
|
2022-06-23 17:19:56 +02:00
|
|
|
|
let classification = classify(value);
|
|
|
|
|
|
|
|
|
|
if classification == Literal
|
|
|
|
|
&& !value.span.from_expansion()
|
|
|
|
|
&& let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) {
|
|
|
|
|
// For literals, we avoid invoking the pretty-printer and use the source snippet instead to
|
|
|
|
|
// preserve certain stylistic choices the user likely made for the sake legibility like
|
|
|
|
|
//
|
|
|
|
|
// * hexadecimal notation
|
|
|
|
|
// * underscores
|
|
|
|
|
// * character escapes
|
|
|
|
|
//
|
|
|
|
|
// FIXME: This passes through `-/*spacer*/0` verbatim.
|
|
|
|
|
snippet
|
|
|
|
|
} else if classification == Simple {
|
|
|
|
|
// Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and
|
|
|
|
|
// other formatting artifacts.
|
|
|
|
|
rustc_hir_pretty::id_to_string(&hir, body.hir_id)
|
|
|
|
|
} else if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst {
|
|
|
|
|
// FIXME: Omit the curly braces if the enclosing expression is an array literal
|
|
|
|
|
// with a repeated element (an `ExprKind::Repeat`) as in such case it
|
|
|
|
|
// would not actually need any disambiguation.
|
|
|
|
|
"{ _ }".to_owned()
|
|
|
|
|
} else {
|
|
|
|
|
"_".to_owned()
|
|
|
|
|
}
|
2019-12-09 17:46:20 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Given a type Path, resolve it to a Type using the TyCtxt
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
|
2021-08-26 17:47:29 -07:00
|
|
|
|
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-09-16 11:45:33 +10:00
|
|
|
|
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } 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
|
|
|
|
}
|
|
|
|
|
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(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> {
|
2023-02-21 10:03:31 +11:00
|
|
|
|
// FIXME: To be removed once `parallel_compiler` bugs are fixed!
|
|
|
|
|
// More information in <https://github.com/rust-lang/rust/pull/106930>.
|
|
|
|
|
if cfg!(parallel_compiler) {
|
|
|
|
|
return vec![].into_iter().chain(vec![].into_iter());
|
|
|
|
|
}
|
|
|
|
|
|
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
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(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);
|
|
|
|
|
|
2022-09-14 15:57:22 +10:00
|
|
|
|
let (kind, did) = match res {
|
2021-05-03 14:57:51 -04:00
|
|
|
|
Res::Def(
|
2021-11-11 15:05:25 -08:00
|
|
|
|
kind @ (AssocTy | AssocFn | AssocConst | Variant | Fn | TyAlias | Enum | Trait | Struct
|
2022-03-29 17:11:12 +02:00
|
|
|
|
| Union | Mod | ForeignTy | Const | Static(_) | Macro(..) | TraitAlias),
|
2022-09-14 15:57:22 +10:00
|
|
|
|
did,
|
|
|
|
|
) => (kind.into(), did),
|
|
|
|
|
|
|
|
|
|
_ => panic!("register_res: unexpected {:?}", res),
|
2019-12-09 17:46:20 +01:00
|
|
|
|
};
|
|
|
|
|
if did.is_local() {
|
|
|
|
|
return did;
|
|
|
|
|
}
|
|
|
|
|
inline::record_extern_fqn(cx, did, kind);
|
|
|
|
|
did
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(crate) fn resolve_use_source(cx: &mut DocContext<'_>, path: Path) -> ImportSource {
|
2019-12-09 17:46:20 +01:00
|
|
|
|
ImportSource {
|
|
|
|
|
did: if path.res.opt_def_id().is_none() { None } else { Some(register_res(cx, path.res)) },
|
|
|
|
|
path,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-22 12:40:26 -07:00
|
|
|
|
pub(crate) fn enter_impl_trait<'tcx, F, R>(cx: &mut DocContext<'tcx>, f: F) -> R
|
2019-12-09 17:46:20 +01:00
|
|
|
|
where
|
2022-05-22 12:40:26 -07:00
|
|
|
|
F: FnOnce(&mut DocContext<'tcx>) -> 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`].
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(crate) fn find_nearest_parent_module(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
|
2020-12-30 16:38:25 -08:00
|
|
|
|
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.
|
2022-04-25 22:08:45 +03:00
|
|
|
|
while let Some(parent) = tcx.opt_parent(current) {
|
2020-12-25 16:35:28 -08:00
|
|
|
|
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.
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool {
|
2022-04-26 13:21:09 +02:00
|
|
|
|
tcx.get_attrs(did, sym::doc).any(|attr| {
|
|
|
|
|
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.
|
2022-05-20 21:06:44 -04:00
|
|
|
|
pub(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,
|
2022-11-03 18:15:24 +01:00
|
|
|
|
vis: ty::Visibility<DefId>,
|
2021-07-05 11:00:27 +02:00
|
|
|
|
) -> String {
|
|
|
|
|
// Extract the spans of all matchers. They represent the "interface" of the macro.
|
2023-05-12 16:57:29 -05:00
|
|
|
|
let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
|
2021-07-05 11:00:27 +02:00
|
|
|
|
|
|
|
|
|
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}}",
|
2022-11-03 18:15:24 +01:00
|
|
|
|
visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
|
2021-07-05 11:00:27 +02:00
|
|
|
|
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{}}}",
|
2022-11-03 18:15:24 +01:00
|
|
|
|
visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
|
2021-07-05 11:00:27 +02:00
|
|
|
|
name,
|
2021-12-28 13:43:08 -08:00
|
|
|
|
render_macro_arms(cx.tcx, matchers, ","),
|
2021-07-05 11:00:27 +02:00
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|