From d1b2d29528b7794b41e66fc2136e395a02f8529b Mon Sep 17 00:00:00 2001
From: Daniel Baumann
Date: Thu, 30 May 2024 05:59:35 +0200
Subject: Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann
---
src/librustdoc/clean/auto_trait.rs | 20 +-
src/librustdoc/clean/blanket_impl.rs | 35 +-
src/librustdoc/clean/cfg.rs | 31 +-
src/librustdoc/clean/inline.rs | 61 ++-
src/librustdoc/clean/mod.rs | 464 ++++++++++++++-------
src/librustdoc/clean/render_macro_matchers.rs | 14 +-
src/librustdoc/clean/simplify.rs | 39 +-
src/librustdoc/clean/types.rs | 117 +++---
src/librustdoc/clean/types/tests.rs | 2 +-
src/librustdoc/clean/utils.rs | 123 ++++--
src/librustdoc/config.rs | 26 +-
src/librustdoc/core.rs | 56 ++-
src/librustdoc/docfs.rs | 6 +-
src/librustdoc/doctest.rs | 80 ++--
src/librustdoc/externalfiles.rs | 12 +-
src/librustdoc/formats/cache.rs | 9 +-
src/librustdoc/formats/item_type.rs | 3 +-
src/librustdoc/formats/renderer.rs | 7 +-
src/librustdoc/html/format.rs | 138 +++---
src/librustdoc/html/highlight.rs | 38 +-
src/librustdoc/html/highlight/tests.rs | 2 +-
src/librustdoc/html/length_limit.rs | 7 +-
src/librustdoc/html/markdown.rs | 145 +++++--
src/librustdoc/html/markdown/tests.rs | 2 +-
src/librustdoc/html/render/context.rs | 39 +-
src/librustdoc/html/render/mod.rs | 266 ++++++------
src/librustdoc/html/render/print_item.rs | 114 ++---
src/librustdoc/html/render/sidebar.rs | 14 +-
src/librustdoc/html/render/span_map.rs | 97 +++--
src/librustdoc/html/render/type_layout.rs | 2 +-
src/librustdoc/html/render/write_shared.rs | 29 +-
src/librustdoc/html/sources.rs | 7 +-
src/librustdoc/html/static/css/noscript.css | 2 +-
src/librustdoc/html/static/css/rustdoc.css | 74 ++--
src/librustdoc/html/static/css/themes/ayu.css | 14 +-
src/librustdoc/html/static/css/themes/dark.css | 6 +-
src/librustdoc/html/static/css/themes/light.css | 6 +-
src/librustdoc/html/static/js/search.js | 29 +-
src/librustdoc/html/static/js/source-script.js | 235 -----------
src/librustdoc/html/static/js/src-script.js | 235 +++++++++++
src/librustdoc/html/static/js/storage.js | 2 +-
src/librustdoc/html/static_files.rs | 4 +-
src/librustdoc/html/templates/STYLE.md | 2 +-
src/librustdoc/html/templates/page.html | 16 +-
src/librustdoc/html/templates/print_item.html | 2 +-
src/librustdoc/html/templates/type_layout.html | 5 +
src/librustdoc/json/conversions.rs | 9 +-
src/librustdoc/json/mod.rs | 6 +-
src/librustdoc/lib.rs | 15 +-
src/librustdoc/lint.rs | 12 +
src/librustdoc/markdown.rs | 12 +-
src/librustdoc/passes/calculate_doc_coverage.rs | 8 +-
src/librustdoc/passes/check_doc_test_visibility.rs | 11 +-
src/librustdoc/passes/collect_intra_doc_links.rs | 222 ++++++----
src/librustdoc/passes/collect_trait_impls.rs | 4 +-
src/librustdoc/passes/lint.rs | 2 +
src/librustdoc/passes/lint/bare_urls.rs | 13 +-
.../passes/lint/check_code_block_syntax.rs | 19 +-
src/librustdoc/passes/lint/html_tags.rs | 14 +-
.../passes/lint/redundant_explicit_links.rs | 347 +++++++++++++++
src/librustdoc/passes/propagate_doc_cfg.rs | 5 +-
src/librustdoc/passes/strip_hidden.rs | 3 +-
src/librustdoc/passes/strip_priv_imports.rs | 7 +-
src/librustdoc/passes/strip_private.rs | 9 +-
src/librustdoc/passes/stripper.rs | 19 +-
src/librustdoc/scrape_examples.rs | 8 +-
src/librustdoc/visit_ast.rs | 85 ++--
src/librustdoc/visit_lib.rs | 4 +-
68 files changed, 2165 insertions(+), 1306 deletions(-)
delete mode 100644 src/librustdoc/html/static/js/source-script.js
create mode 100644 src/librustdoc/html/static/js/src-script.js
create mode 100644 src/librustdoc/passes/lint/redundant_explicit_links.rs
(limited to 'src/librustdoc')
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 92bae5516..a06f31a93 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -46,7 +46,7 @@ where
let tcx = self.cx.tcx;
let trait_ref = ty::Binder::dummy(ty::TraitRef::new(tcx, trait_def_id, [ty]));
if !self.cx.generated_synthetics.insert((ty, trait_def_id)) {
- debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref);
+ debug!("get_auto_trait_impl_for({trait_ref:?}): already generated, aborting");
return None;
}
@@ -137,10 +137,10 @@ where
pub(crate) fn get_auto_trait_impls(&mut self, item_def_id: DefId) -> Vec {
let tcx = self.cx.tcx;
let param_env = tcx.param_env(item_def_id);
- let ty = tcx.type_of(item_def_id).subst_identity();
+ let ty = tcx.type_of(item_def_id).instantiate_identity();
let f = auto_trait::AutoTraitFinder::new(tcx);
- debug!("get_auto_trait_impls({:?})", ty);
+ debug!("get_auto_trait_impls({ty:?})");
let auto_traits: Vec<_> = self.cx.auto_traits.to_vec();
let mut auto_traits: Vec = auto_traits
.into_iter()
@@ -163,9 +163,9 @@ where
fn get_lifetime(region: Region<'_>, names_map: &FxHashMap) -> Lifetime {
region_name(region)
.map(|name| {
- names_map.get(&name).unwrap_or_else(|| {
- panic!("Missing lifetime with name {:?} for {:?}", name.as_str(), region)
- })
+ names_map
+ .get(&name)
+ .unwrap_or_else(|| panic!("Missing lifetime with name {name:?} for {region:?}"))
})
.unwrap_or(&Lifetime::statik())
.clone()
@@ -372,7 +372,7 @@ where
let output = output.as_ref().cloned().map(Box::new);
if old_output.is_some() && old_output != output {
- panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, output);
+ panic!("Output mismatch for {ty:?} {old_output:?} {output:?}");
}
let new_params = GenericArgs::Parenthesized { inputs: old_input, output };
@@ -462,7 +462,7 @@ where
);
let mut generic_params = raw_generics.params;
- debug!("param_env_to_generics({:?}): generic_params={:?}", item_def_id, generic_params);
+ debug!("param_env_to_generics({item_def_id:?}): generic_params={generic_params:?}");
let mut has_sized = FxHashSet::default();
let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default();
@@ -623,7 +623,7 @@ where
// loop
ty_to_traits.entry(ty.clone()).or_default().insert(trait_.clone());
}
- _ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id),
+ _ => panic!("Unexpected LHS {lhs:?} for {item_def_id:?}"),
}
}
};
@@ -710,7 +710,7 @@ where
/// involved (impls rarely have more than a few bounds) means that it
/// shouldn't matter in practice.
fn unstable_debug_sort(&self, vec: &mut [T]) {
- vec.sort_by_cached_key(|x| format!("{:?}", x))
+ vec.sort_by_cached_key(|x| format!("{x:?}"))
}
fn is_fn_trait(&self, path: &Path) -> bool {
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index a36041588..dad2aa406 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -17,7 +17,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
let param_env = cx.tcx.param_env(item_def_id);
let ty = cx.tcx.type_of(item_def_id);
- trace!("get_blanket_impls({:?})", ty);
+ trace!("get_blanket_impls({ty:?})");
let mut impls = Vec::new();
for trait_def_id in cx.tcx.all_traits() {
if !cx.cache.effective_visibilities.is_reachable(cx.tcx, trait_def_id)
@@ -38,18 +38,22 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
continue;
}
let infcx = cx.tcx.infer_ctxt().build();
- let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
- let impl_ty = ty.subst(infcx.tcx, substs);
- let param_env = EarlyBinder::bind(param_env).subst(infcx.tcx, substs);
+ let args = infcx.fresh_args_for_item(DUMMY_SP, item_def_id);
+ let impl_ty = ty.instantiate(infcx.tcx, args);
+ let param_env = EarlyBinder::bind(param_env).instantiate(infcx.tcx, args);
- let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
- let impl_trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
+ let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
+ let impl_trait_ref = trait_ref.instantiate(infcx.tcx, impl_args);
// Require the type the impl is implemented on to match
// our type, and ignore the impl if there was a mismatch.
- let Ok(eq_result) = infcx.at(&traits::ObligationCause::dummy(), param_env).eq(DefineOpaqueTypes::No, impl_trait_ref.self_ty(), impl_ty) else {
- continue
- };
+ let Ok(eq_result) = infcx.at(&traits::ObligationCause::dummy(), param_env).eq(
+ DefineOpaqueTypes::No,
+ impl_trait_ref.self_ty(),
+ impl_ty,
+ ) else {
+ continue;
+ };
let InferOk { value: (), obligations } = eq_result;
// FIXME(eddyb) ignoring `obligations` might cause false positives.
drop(obligations);
@@ -63,12 +67,12 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
let predicates = cx
.tcx
.predicates_of(impl_def_id)
- .instantiate(cx.tcx, impl_substs)
+ .instantiate(cx.tcx, impl_args)
.predicates
.into_iter()
.chain(Some(ty::Binder::dummy(impl_trait_ref).to_predicate(infcx.tcx)));
for predicate in predicates {
- debug!("testing predicate {:?}", predicate);
+ debug!("testing predicate {predicate:?}");
let obligation = traits::Obligation::new(
infcx.tcx,
traits::ObligationCause::dummy(),
@@ -104,11 +108,11 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
// the post-inference `trait_ref`, as it's more accurate.
trait_: Some(clean_trait_ref_with_bindings(
cx,
- ty::Binder::dummy(trait_ref.subst_identity()),
+ ty::Binder::dummy(trait_ref.instantiate_identity()),
ThinVec::new(),
)),
for_: clean_middle_ty(
- ty::Binder::dummy(ty.subst_identity()),
+ ty::Binder::dummy(ty.instantiate_identity()),
cx,
None,
None,
@@ -117,11 +121,12 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
.tcx
.associated_items(impl_def_id)
.in_definition_order()
- .map(|x| clean_middle_assoc_item(x, cx))
+ .filter(|item| !item.is_impl_trait_in_trait())
+ .map(|item| clean_middle_assoc_item(item, cx))
.collect::>(),
polarity: ty::ImplPolarity::Positive,
kind: ImplKind::Blanket(Box::new(clean_middle_ty(
- ty::Binder::dummy(trait_ref.subst_identity().self_ty()),
+ ty::Binder::dummy(trait_ref.instantiate_identity().self_ty()),
cx,
None,
None,
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 5177cffe6..ab5aec12f 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -434,9 +434,9 @@ impl<'a> fmt::Display for Display<'a> {
}
if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) {
if self.1.is_html() {
- write!(fmt, "{}", feat)?;
+ write!(fmt, "{feat}")?;
} else {
- write!(fmt, "`{}`", feat)?;
+ write!(fmt, "`{feat}`")?;
}
} else {
write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?;
@@ -471,9 +471,9 @@ impl<'a> fmt::Display for Display<'a> {
}
if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) {
if self.1.is_html() {
- write!(fmt, "{}", feat)?;
+ write!(fmt, "{feat}")?;
} else {
- write!(fmt, "`{}`", feat)?;
+ write!(fmt, "`{feat}`")?;
}
} else {
write_with_opt_paren(fmt, !sub_cfg.is_simple(), Display(sub_cfg, self.1))?;
@@ -519,8 +519,11 @@ impl<'a> fmt::Display for Display<'a> {
"asmjs" => "JavaScript",
"loongarch64" => "LoongArch LA64",
"m68k" => "M68k",
+ "csky" => "CSKY",
"mips" => "MIPS",
+ "mips32r6" => "MIPS Release 6",
"mips64" => "MIPS-64",
+ "mips64r6" => "MIPS-64 Release 6",
"msp430" => "MSP430",
"powerpc" => "PowerPC",
"powerpc64" => "PowerPC-64",
@@ -549,21 +552,21 @@ impl<'a> fmt::Display for Display<'a> {
"sgx" => "SGX",
_ => "",
},
- (sym::target_endian, Some(endian)) => return write!(fmt, "{}-endian", endian),
- (sym::target_pointer_width, Some(bits)) => return write!(fmt, "{}-bit", bits),
+ (sym::target_endian, Some(endian)) => return write!(fmt, "{endian}-endian"),
+ (sym::target_pointer_width, Some(bits)) => return write!(fmt, "{bits}-bit"),
(sym::target_feature, Some(feat)) => match self.1 {
Format::LongHtml => {
- return write!(fmt, "target feature {}", feat);
+ return write!(fmt, "target feature {feat}");
}
- Format::LongPlain => return write!(fmt, "target feature `{}`", feat),
- Format::ShortHtml => return write!(fmt, "{}", feat),
+ Format::LongPlain => return write!(fmt, "target feature `{feat}`"),
+ Format::ShortHtml => return write!(fmt, "{feat}"),
},
(sym::feature, Some(feat)) => match self.1 {
Format::LongHtml => {
- return write!(fmt, "crate feature {}", feat);
+ return write!(fmt, "crate feature {feat}");
}
- Format::LongPlain => return write!(fmt, "crate feature `{}`", feat),
- Format::ShortHtml => return write!(fmt, "{}", feat),
+ Format::LongPlain => return write!(fmt, "crate feature `{feat}`"),
+ Format::ShortHtml => return write!(fmt, "{feat}"),
},
_ => "",
};
@@ -578,12 +581,12 @@ impl<'a> fmt::Display for Display<'a> {
Escape(v.as_str())
)
} else {
- write!(fmt, r#"`{}="{}"`"#, name, v)
+ write!(fmt, r#"`{name}="{v}"`"#)
}
} else if self.1.is_html() {
write!(fmt, "{}", Escape(name.as_str()))
} else {
- write!(fmt, "`{}`", name)
+ write!(fmt, "`{name}`")
}
}
}
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 870cfa930..cac211307 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -9,9 +9,10 @@ use rustc_ast as ast;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId};
+use rustc_hir::def_id::{DefId, DefIdSet, LocalModDefId};
use rustc_hir::Mutability;
use rustc_metadata::creader::{CStore, LoadedMacro};
+use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
@@ -49,7 +50,7 @@ pub(crate) fn try_inline(
}
let mut ret = Vec::new();
- debug!("attrs={:?}", attrs);
+ debug!("attrs={attrs:?}");
let attrs_without_docs = attrs.map(|(attrs, def_id)| {
(attrs.into_iter().filter(|a| a.doc_str().is_none()).cloned().collect::>(), def_id)
@@ -78,7 +79,7 @@ pub(crate) fn try_inline(
build_impls(cx, did, attrs_without_docs, &mut ret);
clean::UnionItem(build_union(cx, did))
}
- Res::Def(DefKind::TyAlias, did) => {
+ Res::Def(DefKind::TyAlias { .. }, did) => {
record_extern_fqn(cx, did, ItemType::Typedef);
build_impls(cx, did, attrs_without_docs, &mut ret);
clean::TypedefItem(build_type_alias(cx, did))
@@ -137,9 +138,10 @@ pub(crate) fn try_inline(
pub(crate) fn try_inline_glob(
cx: &mut DocContext<'_>,
res: Res,
- current_mod: LocalDefId,
+ current_mod: LocalModDefId,
visited: &mut DefIdSet,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
+ import: &hir::Item<'_>,
) -> Option> {
let did = res.opt_def_id()?;
if did.is_local() {
@@ -152,12 +154,20 @@ pub(crate) fn try_inline_glob(
// reexported by the glob, e.g. because they are shadowed by something else.
let reexports = cx
.tcx
- .module_children_local(current_mod)
+ .module_children_local(current_mod.to_local_def_id())
.iter()
.filter(|child| !child.reexport_chain.is_empty())
.filter_map(|child| child.res.opt_def_id())
.collect();
- let mut items = build_module_items(cx, did, visited, inlined_names, Some(&reexports));
+ let attrs = cx.tcx.hir().attrs(import.hir_id());
+ let mut items = build_module_items(
+ cx,
+ did,
+ visited,
+ inlined_names,
+ Some(&reexports),
+ Some((attrs, Some(import.owner_id.def_id.to_def_id()))),
+ );
items.retain(|item| {
if let Some(name) = item.name {
// If an item with the same type and name already exists,
@@ -190,7 +200,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT
let fqn = if let ItemType::Macro = kind {
// Check to see if it is a macro 2.0 or built-in macro
if matches!(
- CStore::from_tcx(cx.tcx).load_macro_untracked(did, cx.sess()),
+ CStore::from_tcx(cx.tcx).load_macro_untracked(did, cx.tcx),
LoadedMacro::MacroDef(def, _)
if matches!(&def.kind, ast::ItemKind::MacroDef(ast_def)
if !ast_def.macro_rules)
@@ -215,6 +225,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
.tcx
.associated_items(did)
.in_definition_order()
+ .filter(|item| !item.is_impl_trait_in_trait())
.map(|item| clean_middle_assoc_item(item, cx))
.collect();
@@ -226,7 +237,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
}
fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box {
- let sig = cx.tcx.fn_sig(did).subst_identity();
+ let sig = cx.tcx.fn_sig(did).instantiate_identity();
let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => {
@@ -279,7 +290,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box {
let predicates = cx.tcx.explicit_predicates_of(did);
let type_ = clean_middle_ty(
- ty::Binder::dummy(cx.tcx.type_of(did).subst_identity()),
+ ty::Binder::dummy(cx.tcx.type_of(did).instantiate_identity()),
cx,
Some(did),
None,
@@ -314,9 +325,8 @@ pub(crate) fn build_impls(
// * https://github.com/rust-lang/rust/pull/99917 — where the feature got used
// * https://github.com/rust-lang/rust/issues/53487 — overall tracking issue for Error
if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
- use rustc_middle::ty::fast_reject::SimplifiedType::*;
let type_ =
- if tcx.is_trait(did) { TraitSimplifiedType(did) } else { AdtSimplifiedType(did) };
+ if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) };
for &did in tcx.incoherent_impls(type_) {
build_impl(cx, did, attrs, ret);
}
@@ -391,7 +401,7 @@ pub(crate) fn build_impl(
let for_ = match &impl_item {
Some(impl_) => clean_ty(impl_.self_ty, cx),
None => clean_middle_ty(
- ty::Binder::dummy(tcx.type_of(did).subst_identity()),
+ ty::Binder::dummy(tcx.type_of(did).instantiate_identity()),
cx,
Some(did),
None,
@@ -459,6 +469,7 @@ pub(crate) fn build_impl(
None => (
tcx.associated_items(did)
.in_definition_order()
+ .filter(|item| !item.is_impl_trait_in_trait())
.filter(|item| {
// If this is a trait impl, filter out associated items whose corresponding item
// in the associated trait is marked `doc(hidden)`.
@@ -473,7 +484,7 @@ pub(crate) fn build_impl(
associated_trait.def_id,
)
.unwrap(); // corresponding associated item has to exist
- !tcx.is_doc_hidden(trait_item.def_id)
+ document_hidden || !tcx.is_doc_hidden(trait_item.def_id)
} else {
item.visibility(tcx).is_public()
}
@@ -496,7 +507,7 @@ pub(crate) fn build_impl(
let mut stack: Vec<&Type> = vec![&for_];
if let Some(did) = trait_.as_ref().map(|t| t.def_id()) {
- if tcx.is_doc_hidden(did) {
+ if !document_hidden && tcx.is_doc_hidden(did) {
return;
}
}
@@ -505,7 +516,7 @@ pub(crate) fn build_impl(
}
while let Some(ty) = stack.pop() {
- if let Some(did) = ty.def_id(&cx.cache) && tcx.is_doc_hidden(did) {
+ if let Some(did) = ty.def_id(&cx.cache) && !document_hidden && tcx.is_doc_hidden(did) {
return;
}
if let Some(generics) = ty.generics() {
@@ -518,7 +529,7 @@ pub(crate) fn build_impl(
}
let (merged_attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs);
- trace!("merged_attrs={:?}", merged_attrs);
+ trace!("merged_attrs={merged_attrs:?}");
trace!(
"build_impl: impl {:?} for {:?}",
@@ -547,7 +558,7 @@ pub(crate) fn build_impl(
}
fn build_module(cx: &mut DocContext<'_>, did: DefId, visited: &mut DefIdSet) -> clean::Module {
- let items = build_module_items(cx, did, visited, &mut FxHashSet::default(), None);
+ let items = build_module_items(cx, did, visited, &mut FxHashSet::default(), None, None);
let span = clean::Span::new(cx.tcx.def_span(did));
clean::Module { items, span }
@@ -559,6 +570,7 @@ fn build_module_items(
visited: &mut DefIdSet,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
allowed_def_ids: Option<&DefIdSet>,
+ attrs: Option<(&[ast::Attribute], Option)>,
) -> Vec {
let mut items = Vec::new();
@@ -613,7 +625,7 @@ fn build_module_items(
cfg: None,
inline_stmt_id: None,
});
- } else if let Some(i) = try_inline(cx, res, item.ident.name, None, visited) {
+ } else if let Some(i) = try_inline(cx, res, item.ident.name, attrs, visited) {
items.extend(i)
}
}
@@ -632,13 +644,18 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
}
fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
+ let mut generics =
+ clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id));
+ clean::simplify::move_bounds_to_generic_parameters(&mut generics);
+
clean::Constant {
type_: clean_middle_ty(
- ty::Binder::dummy(cx.tcx.type_of(def_id).subst_identity()),
+ ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()),
cx,
Some(def_id),
None,
),
+ generics: Box::new(generics),
kind: clean::ConstantKind::Extern { def_id },
}
}
@@ -646,7 +663,7 @@ fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
clean::Static {
type_: clean_middle_ty(
- ty::Binder::dummy(cx.tcx.type_of(did).subst_identity()),
+ ty::Binder::dummy(cx.tcx.type_of(did).instantiate_identity()),
cx,
Some(did),
None,
@@ -663,7 +680,7 @@ fn build_macro(
import_def_id: Option,
macro_kind: MacroKind,
) -> clean::ItemKind {
- match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.sess()) {
+ match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
LoadedMacro::MacroDef(item_def, _) => match macro_kind {
MacroKind::Bang => {
if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
@@ -764,7 +781,7 @@ pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) {
cx.active_extern_traits.insert(did);
}
- debug!("record_extern_trait: {:?}", did);
+ debug!("record_extern_trait: {did:?}");
let trait_ = build_external_trait(cx, did);
cx.external_traits.borrow_mut().insert(did, trait_);
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 8ad1ed095..c9a05460b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -24,7 +24,6 @@ use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc_middle::metadata::Reexport;
use rustc_middle::middle::resolve_bound_vars as rbv;
use rustc_middle::ty::fold::TypeFolder;
-use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{self, AdtKind, EarlyBinder, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
@@ -54,7 +53,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
let mut inserted = FxHashSet::default();
items.extend(doc.foreigns.iter().map(|(item, renamed)| {
let item = clean_maybe_renamed_foreign_item(cx, item, *renamed);
- if let Some(name) = item.name && !item.is_doc_hidden() {
+ if let Some(name) = item.name && (cx.render_options.document_hidden || !item.is_doc_hidden()) {
inserted.insert((item.type_(), name));
}
item
@@ -64,7 +63,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
return None;
}
let item = clean_doc_module(x, cx);
- if item.is_doc_hidden() {
+ if !cx.render_options.document_hidden && item.is_doc_hidden() {
// Hidden modules are stripped at a later stage.
// If a hidden module has the same name as a visible one, we want
// to keep both of them around.
@@ -85,12 +84,25 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
}
let v = clean_maybe_renamed_item(cx, item, *renamed, *import_id);
for item in &v {
- if let Some(name) = item.name && !item.is_doc_hidden() {
+ if let Some(name) = item.name && (cx.render_options.document_hidden || !item.is_doc_hidden()) {
inserted.insert((item.type_(), name));
}
}
v
}));
+ items.extend(doc.inlined_foreigns.iter().flat_map(|((_, renamed), (res, local_import_id))| {
+ let Some(def_id) = res.opt_def_id() else { return Vec::new() };
+ let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id));
+ let import = cx.tcx.hir().expect_item(*local_import_id);
+ match import.kind {
+ hir::ItemKind::Use(path, kind) => {
+ let hir::UsePath { segments, span, .. } = *path;
+ let path = hir::Path { segments, res: *res, span };
+ clean_use_statement_inner(import, name, &path, kind, cx, &mut Default::default())
+ }
+ _ => unreachable!(),
+ }
+ }));
items.extend(doc.items.values().flat_map(|(item, renamed, _)| {
// Now we actually lower the imports, skipping everything else.
if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
@@ -120,25 +132,31 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
});
let kind = ModuleItem(Module { items, span });
- generate_item_with_correct_attrs(cx, kind, doc.def_id, doc.name, doc.import_id, doc.renamed)
+ generate_item_with_correct_attrs(
+ cx,
+ kind,
+ doc.def_id.to_def_id(),
+ doc.name,
+ doc.import_id,
+ doc.renamed,
+ )
}
fn generate_item_with_correct_attrs(
cx: &mut DocContext<'_>,
kind: ItemKind,
- local_def_id: LocalDefId,
+ def_id: DefId,
name: Symbol,
import_id: Option,
renamed: Option,
) -> Item {
- let def_id = local_def_id.to_def_id();
let target_attrs = inline::load_attrs(cx, def_id);
let attrs = if let Some(import_id) = import_id {
let is_inline = inline::load_attrs(cx, import_id.to_def_id())
.lists(sym::doc)
.get_word_attr(sym::inline)
.is_some();
- let mut attrs = get_all_import_attributes(cx, import_id, local_def_id, is_inline);
+ let mut attrs = get_all_import_attributes(cx, import_id, def_id, is_inline);
add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None);
attrs
} else {
@@ -197,11 +215,11 @@ pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
) -> Path {
let kind = cx.tcx.def_kind(trait_ref.def_id()).into();
if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
- span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {:?}", kind);
+ span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {kind:?}");
}
inline::record_extern_fqn(cx, trait_ref.def_id(), kind);
let path =
- external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.map_bound(|tr| tr.substs));
+ external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.map_bound(|tr| tr.args));
debug!(?trait_ref);
@@ -239,7 +257,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
| rbv::ResolvedArg::Free(_, node_id),
) = def
{
- if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
+ if let Some(lt) = cx.args.get(&node_id).and_then(|p| p.as_lt()).cloned() {
return lt;
}
}
@@ -250,11 +268,12 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'t
let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
Constant {
type_: clean_middle_ty(
- ty::Binder::dummy(cx.tcx.type_of(def_id).subst_identity()),
+ ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()),
cx,
Some(def_id),
None,
),
+ generics: Box::new(Generics::default()),
kind: ConstantKind::Anonymous { body: constant.value.body },
}
}
@@ -266,6 +285,7 @@ pub(crate) fn clean_middle_const<'tcx>(
// FIXME: instead of storing the stringified expression, store `self` directly instead.
Constant {
type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None, None),
+ generics: Box::new(Generics::default()),
kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() },
}
}
@@ -284,7 +304,7 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option {
- debug!("cannot clean region {:?}", region);
+ debug!("cannot clean region {region:?}");
None
}
}
@@ -350,9 +370,8 @@ fn clean_poly_trait_predicate<'tcx>(
cx: &mut DocContext<'tcx>,
) -> Option {
// `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
- if pred.skip_binder().constness == ty::BoundConstness::ConstIfConst
- && Some(pred.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait()
- {
+ // FIXME(effects) check constness
+ if Some(pred.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait() {
return None;
}
@@ -442,7 +461,7 @@ fn clean_projection<'tcx>(
let bounds = cx
.tcx
.explicit_item_bounds(ty.skip_binder().def_id)
- .subst_iter_copied(cx.tcx, ty.skip_binder().substs)
+ .iter_instantiated_copied(cx.tcx, ty.skip_binder().args)
.map(|(pred, _)| pred)
.collect::>();
return clean_middle_opaque_bounds(cx, bounds);
@@ -481,9 +500,9 @@ fn projection_to_path_segment<'tcx>(
PathSegment {
name: item.name,
args: GenericArgs::AngleBracketed {
- args: substs_to_args(
+ args: ty_args_to_args(
cx,
- ty.map_bound(|ty| &ty.substs[generics.parent_count..]),
+ ty.map_bound(|ty| &ty.args[generics.parent_count..]),
false,
None,
)
@@ -504,7 +523,7 @@ fn clean_generic_param_def<'tcx>(
ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
let default = if has_default {
Some(clean_middle_ty(
- ty::Binder::dummy(cx.tcx.type_of(def.def_id).subst_identity()),
+ ty::Binder::dummy(cx.tcx.type_of(def.def_id).instantiate_identity()),
cx,
Some(def.def_id),
None,
@@ -538,7 +557,7 @@ fn clean_generic_param_def<'tcx>(
)),
default: match has_default {
true => Some(Box::new(
- cx.tcx.const_param_default(def.def_id).subst_identity().to_string(),
+ cx.tcx.const_param_default(def.def_id).instantiate_identity().to_string(),
)),
false => None,
},
@@ -786,10 +805,10 @@ fn clean_ty_generics<'tcx>(
let where_predicates = preds
.predicates
.iter()
- .flat_map(|(p, _)| {
+ .flat_map(|(pred, _)| {
let mut projection = None;
let param_idx = (|| {
- let bound_p = p.kind();
+ let bound_p = pred.kind();
match bound_p.skip_binder() {
ty::ClauseKind::Trait(pred) => {
if let ty::Param(param) = pred.self_ty().kind() {
@@ -814,33 +833,26 @@ fn clean_ty_generics<'tcx>(
})();
if let Some(param_idx) = param_idx
- && let Some(b) = impl_trait.get_mut(¶m_idx.into())
+ && let Some(bounds) = impl_trait.get_mut(¶m_idx.into())
{
- let p: WherePredicate = clean_predicate(*p, cx)?;
+ let pred = clean_predicate(*pred, cx)?;
- b.extend(
- p.get_bounds()
+ bounds.extend(
+ pred.get_bounds()
.into_iter()
.flatten()
.cloned()
- .filter(|b| !b.is_sized_bound(cx)),
);
- let proj = projection.map(|p| {
- (
- clean_projection(p.map_bound(|p| p.projection_ty), cx, None),
- p.map_bound(|p| p.term),
- )
- });
- if let Some(((_, trait_did, name), rhs)) = proj
- .as_ref()
- .and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs)))
+ if let Some(proj) = projection
+ && let lhs = clean_projection(proj.map_bound(|p| p.projection_ty), cx, None)
+ && let Some((_, trait_did, name)) = lhs.projection()
{
impl_trait_proj.entry(param_idx).or_default().push((
trait_did,
name,
- *rhs,
- p.get_bound_params()
+ proj.map_bound(|p| p.term),
+ pred.get_bound_params()
.into_iter()
.flatten()
.cloned()
@@ -851,13 +863,32 @@ fn clean_ty_generics<'tcx>(
return None;
}
- Some(p)
+ Some(pred)
})
.collect::>();
for (param, mut bounds) in impl_trait {
+ let mut has_sized = false;
+ bounds.retain(|b| {
+ if b.is_sized_bound(cx) {
+ has_sized = true;
+ false
+ } else {
+ true
+ }
+ });
+ if !has_sized {
+ bounds.push(GenericBound::maybe_sized(cx));
+ }
+
// Move trait bounds to the front.
- bounds.sort_by_key(|b| !matches!(b, GenericBound::TraitBound(..)));
+ bounds.sort_by_key(|b| !b.is_trait_bound());
+
+ // Add back a `Sized` bound if there are no *trait* bounds remaining (incl. `?Sized`).
+ // Since all potential trait bounds are at the front we can just check the first bound.
+ if bounds.first().map_or(true, |b| !b.is_trait_bound()) {
+ bounds.insert(0, GenericBound::sized(cx));
+ }
let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() };
if let Some(proj) = impl_trait_proj.remove(&idx) {
@@ -879,7 +910,7 @@ fn clean_ty_generics<'tcx>(
// implicit `Sized` bound unless removed with `?Sized`.
// However, in the list of where-predicates below, `Sized` appears like a
// normal bound: It's either present (the type is sized) or
- // absent (the type is unsized) but never *maybe* (i.e. `?Sized`).
+ // absent (the type might be unsized) but never *maybe* (i.e. `?Sized`).
//
// This is unsuitable for rendering.
// Thus, as a first step remove all `Sized` bounds that should be implicit.
@@ -890,8 +921,8 @@ fn clean_ty_generics<'tcx>(
let mut sized_params = FxHashSet::default();
where_predicates.retain(|pred| {
if let WherePredicate::BoundPredicate { ty: Generic(g), bounds, .. } = pred
- && *g != kw::SelfUpper
- && bounds.iter().any(|b| b.is_sized_bound(cx))
+ && *g != kw::SelfUpper
+ && bounds.iter().any(|b| b.is_sized_bound(cx))
{
sized_params.insert(*g);
false
@@ -1158,11 +1189,18 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
let local_did = trait_item.owner_id.to_def_id();
cx.with_param_env(local_did, |cx| {
let inner = match trait_item.kind {
- hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem(
- clean_ty(ty, cx),
- ConstantKind::Local { def_id: local_did, body: default },
- ),
- hir::TraitItemKind::Const(ty, None) => TyAssocConstItem(clean_ty(ty, cx)),
+ hir::TraitItemKind::Const(ty, Some(default)) => {
+ let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
+ AssocConstItem(
+ Box::new(generics),
+ clean_ty(ty, cx),
+ ConstantKind::Local { def_id: local_did, body: default },
+ )
+ }
+ hir::TraitItemKind::Const(ty, None) => {
+ let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
+ TyAssocConstItem(Box::new(generics), clean_ty(ty, cx))
+ }
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body));
MethodItem(m, None)
@@ -1207,8 +1245,9 @@ pub(crate) fn clean_impl_item<'tcx>(
cx.with_param_env(local_did, |cx| {
let inner = match impl_.kind {
hir::ImplItemKind::Const(ty, expr) => {
+ let generics = clean_generics(impl_.generics, cx);
let default = ConstantKind::Local { def_id: local_did, body: expr };
- AssocConstItem(clean_ty(ty, cx), default)
+ AssocConstItem(Box::new(generics), clean_ty(ty, cx), default)
}
hir::ImplItemKind::Fn(ref sig, body) => {
let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body));
@@ -1243,24 +1282,31 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
let kind = match assoc_item.kind {
ty::AssocKind::Const => {
let ty = clean_middle_ty(
- ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()),
+ ty::Binder::dummy(tcx.type_of(assoc_item.def_id).instantiate_identity()),
cx,
Some(assoc_item.def_id),
None,
);
+ let mut generics = Box::new(clean_ty_generics(
+ cx,
+ tcx.generics_of(assoc_item.def_id),
+ tcx.explicit_predicates_of(assoc_item.def_id),
+ ));
+ simplify::move_bounds_to_generic_parameters(&mut generics);
+
let provided = match assoc_item.container {
ty::ImplContainer => true,
ty::TraitContainer => tcx.defaultness(assoc_item.def_id).has_value(),
};
if provided {
- AssocConstItem(ty, ConstantKind::Extern { def_id: assoc_item.def_id })
+ AssocConstItem(generics, ty, ConstantKind::Extern { def_id: assoc_item.def_id })
} else {
- TyAssocConstItem(ty)
+ TyAssocConstItem(generics, ty)
}
}
ty::AssocKind::Fn => {
- let sig = tcx.fn_sig(assoc_item.def_id).subst_identity();
+ let sig = tcx.fn_sig(assoc_item.def_id).instantiate_identity();
let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
ty::BoundVariableKind::Region(ty::BrNamed(_, name))
@@ -1283,7 +1329,9 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
if assoc_item.fn_has_self_parameter {
let self_ty = match assoc_item.container {
- ty::ImplContainer => tcx.type_of(assoc_item.container_id(tcx)).subst_identity(),
+ ty::ImplContainer => {
+ tcx.type_of(assoc_item.container_id(tcx)).instantiate_identity()
+ }
ty::TraitContainer => tcx.types.self_param,
};
let self_arg_ty = sig.input(0).skip_binder();
@@ -1339,7 +1387,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
let mut predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
if let ty::TraitContainer = assoc_item.container {
let bounds =
- tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied();
+ tcx.explicit_item_bounds(assoc_item.def_id).instantiate_identity_iter_copied();
predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));
}
let mut generics = clean_ty_generics(
@@ -1347,34 +1395,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
tcx.generics_of(assoc_item.def_id),
ty::GenericPredicates { parent: None, predicates },
);
- // Move bounds that are (likely) directly attached to the parameters of the
- // (generic) associated type from the where clause to the respective parameter.
- // There is no guarantee that this is what the user actually wrote but we have
- // no way of knowing.
- let mut where_predicates = ThinVec::new();
- for mut pred in generics.where_predicates {
- if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred
- && let Some(GenericParamDef {
- kind: GenericParamDefKind::Type { bounds: param_bounds, .. },
- ..
- }) = generics.params.iter_mut().find(|param| ¶m.name == arg)
- {
- param_bounds.append(bounds);
- } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred
- && let Some(GenericParamDef {
- kind: GenericParamDefKind::Lifetime { outlives: param_bounds },
- ..
- }) = generics.params.iter_mut().find(|param| ¶m.name == arg)
- {
- param_bounds.extend(bounds.drain(..).map(|bound| match bound {
- GenericBound::Outlives(lifetime) => lifetime,
- _ => unreachable!(),
- }));
- } else {
- where_predicates.push(pred);
- }
- }
- generics.where_predicates = where_predicates;
+ simplify::move_bounds_to_generic_parameters(&mut generics);
if let ty::TraitContainer = assoc_item.container {
// Move bounds that are (likely) directly attached to the associated type
@@ -1442,7 +1463,9 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
AssocTypeItem(
Box::new(Typedef {
type_: clean_middle_ty(
- ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()),
+ ty::Binder::dummy(
+ tcx.type_of(assoc_item.def_id).instantiate_identity(),
+ ),
cx,
Some(assoc_item.def_id),
None,
@@ -1459,7 +1482,9 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
AssocTypeItem(
Box::new(Typedef {
type_: clean_middle_ty(
- ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()),
+ ty::Binder::dummy(
+ tcx.type_of(assoc_item.def_id).instantiate_identity(),
+ ),
cx,
Some(assoc_item.def_id),
None,
@@ -1478,14 +1503,127 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx)
}
+fn first_non_private_clean_path<'tcx>(
+ cx: &mut DocContext<'tcx>,
+ path: &hir::Path<'tcx>,
+ new_path_segments: &'tcx [hir::PathSegment<'tcx>],
+ new_path_span: rustc_span::Span,
+) -> Path {
+ let new_hir_path =
+ hir::Path { segments: new_path_segments, res: path.res, span: new_path_span };
+ let mut new_clean_path = clean_path(&new_hir_path, cx);
+ // In here we need to play with the path data one last time to provide it the
+ // missing `args` and `res` of the final `Path` we get, which, since it comes
+ // from a re-export, doesn't have the generics that were originally there, so
+ // we add them by hand.
+ if let Some(path_last) = path.segments.last().as_ref()
+ && let Some(new_path_last) = new_clean_path.segments[..].last_mut()
+ && let Some(path_last_args) = path_last.args.as_ref()
+ && path_last.args.is_some()
+ {
+ assert!(new_path_last.args.is_empty());
+ new_path_last.args = clean_generic_args(path_last_args, cx);
+ }
+ new_clean_path
+}
+
+/// The goal of this function is to return the first `Path` which is not private (ie not private
+/// or `doc(hidden)`). If it's not possible, it'll return the "end type".
+///
+/// If the path is not a re-export or is public, it'll return `None`.
+fn first_non_private<'tcx>(
+ cx: &mut DocContext<'tcx>,
+ hir_id: hir::HirId,
+ path: &hir::Path<'tcx>,
+) -> Option {
+ let target_def_id = path.res.opt_def_id()?;
+ let (parent_def_id, ident) = match &path.segments[..] {
+ [] => return None,
+ // Relative paths are available in the same scope as the owner.
+ [leaf] => (cx.tcx.local_parent(hir_id.owner.def_id), leaf.ident),
+ // So are self paths.
+ [parent, leaf] if parent.ident.name == kw::SelfLower => {
+ (cx.tcx.local_parent(hir_id.owner.def_id), leaf.ident)
+ }
+ // Crate paths are not. We start from the crate root.
+ [parent, leaf] if matches!(parent.ident.name, kw::Crate | kw::PathRoot) => {
+ (LOCAL_CRATE.as_def_id().as_local()?, leaf.ident)
+ }
+ [parent, leaf] if parent.ident.name == kw::Super => {
+ let parent_mod = cx.tcx.parent_module(hir_id);
+ if let Some(super_parent) = cx.tcx.opt_local_parent(parent_mod.to_local_def_id()) {
+ (super_parent, leaf.ident)
+ } else {
+ // If we can't find the parent of the parent, then the parent is already the crate.
+ (LOCAL_CRATE.as_def_id().as_local()?, leaf.ident)
+ }
+ }
+ // Absolute paths are not. We start from the parent of the item.
+ [.., parent, leaf] => (parent.res.opt_def_id()?.as_local()?, leaf.ident),
+ };
+ let hir = cx.tcx.hir();
+ // First we try to get the `DefId` of the item.
+ for child in
+ cx.tcx.module_children_local(parent_def_id).iter().filter(move |c| c.ident == ident)
+ {
+ if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = child.res {
+ continue;
+ }
+
+ if let Some(def_id) = child.res.opt_def_id() && target_def_id == def_id {
+ let mut last_path_res = None;
+ 'reexps: for reexp in child.reexport_chain.iter() {
+ if let Some(use_def_id) = reexp.id() &&
+ let Some(local_use_def_id) = use_def_id.as_local() &&
+ let Some(hir::Node::Item(item)) = hir.find_by_def_id(local_use_def_id) &&
+ !item.ident.name.is_empty() &&
+ let hir::ItemKind::Use(path, _) = item.kind
+ {
+ for res in &path.res {
+ if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res {
+ continue;
+ }
+ if (cx.render_options.document_hidden ||
+ !cx.tcx.is_doc_hidden(use_def_id)) &&
+ // We never check for "cx.render_options.document_private"
+ // because if a re-export is not fully public, it's never
+ // documented.
+ cx.tcx.local_visibility(local_use_def_id).is_public() {
+ break 'reexps;
+ }
+ last_path_res = Some((path, res));
+ continue 'reexps;
+ }
+ }
+ }
+ if !child.reexport_chain.is_empty() {
+ // So in here, we use the data we gathered from iterating the reexports. If
+ // `last_path_res` is set, it can mean two things:
+ //
+ // 1. We found a public reexport.
+ // 2. We didn't find a public reexport so it's the "end type" path.
+ if let Some((new_path, _)) = last_path_res {
+ return Some(first_non_private_clean_path(cx, path, new_path.segments, new_path.span));
+ }
+ // If `last_path_res` is `None`, it can mean two things:
+ //
+ // 1. The re-export is public, no need to change anything, just use the path as is.
+ // 2. Nothing was found, so let's just return the original path.
+ return None;
+ }
+ }
+ }
+ None
+}
+
fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
- let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
+ let hir::Ty { hir_id, span, ref kind } = *hir_ty;
let hir::TyKind::Path(qpath) = kind else { unreachable!() };
match qpath {
hir::QPath::Resolved(None, path) => {
if let Res::Def(DefKind::TyParam, did) = path.res {
- if let Some(new_ty) = cx.substs.get(&did).and_then(|p| p.as_ty()).cloned() {
+ if let Some(new_ty) = cx.args.get(&did).and_then(|p| p.as_ty()).cloned() {
return new_ty;
}
if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) {
@@ -1496,7 +1634,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
if let Some(expanded) = maybe_expand_private_type_alias(cx, path) {
expanded
} else {
- let path = clean_path(path, cx);
+ // First we check if it's a private re-export.
+ let path = if let Some(path) = first_non_private(cx, hir_id, &path) {
+ path
+ } else {
+ clean_path(path, cx)
+ };
resolve_type(cx, path)
}
}
@@ -1563,7 +1706,7 @@ fn maybe_expand_private_type_alias<'tcx>(
cx: &mut DocContext<'tcx>,
path: &hir::Path<'tcx>,
) -> Option {
- let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
+ let Res::Def(DefKind::TyAlias { .. }, def_id) = path.res else { return None };
// Substitute private type aliases
let def_id = def_id.as_local()?;
let alias = if !cx.cache.effective_visibilities.is_exported(cx.tcx, def_id.to_def_id())
@@ -1576,7 +1719,7 @@ fn maybe_expand_private_type_alias<'tcx>(
let hir::ItemKind::TyAlias(ty, generics) = alias else { return None };
let provided_params = &path.segments.last().expect("segments were empty");
- let mut substs = DefIdMap::default();
+ let mut args = DefIdMap::default();
let generic_args = provided_params.args();
let mut indices: hir::GenericParamCount = Default::default();
@@ -1600,7 +1743,7 @@ fn maybe_expand_private_type_alias<'tcx>(
} else {
Lifetime::elided()
};
- substs.insert(param.def_id.to_def_id(), SubstParam::Lifetime(cleaned));
+ args.insert(param.def_id.to_def_id(), SubstParam::Lifetime(cleaned));
}
indices.lifetimes += 1;
}
@@ -1617,10 +1760,9 @@ fn maybe_expand_private_type_alias<'tcx>(
_ => None,
});
if let Some(ty) = type_ {
- substs.insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(ty, cx)));
+ args.insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(ty, cx)));
} else if let Some(default) = *default {
- substs
- .insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(default, cx)));
+ args.insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(default, cx)));
}
indices.types += 1;
}
@@ -1637,7 +1779,7 @@ fn maybe_expand_private_type_alias<'tcx>(
_ => None,
});
if let Some(ct) = const_ {
- substs.insert(
+ args.insert(
param.def_id.to_def_id(),
SubstParam::Constant(clean_const(ct, cx)),
);
@@ -1648,7 +1790,7 @@ fn maybe_expand_private_type_alias<'tcx>(
}
}
- Some(cx.enter_alias(substs, def_id.to_def_id(), |cx| clean_ty(ty, cx)))
+ Some(cx.enter_alias(args, def_id.to_def_id(), |cx| clean_ty(&ty, cx)))
}
pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
@@ -1725,11 +1867,11 @@ fn normalize<'tcx>(
.map(|resolved| infcx.resolve_vars_if_possible(resolved.value));
match normalized {
Ok(normalized_value) => {
- debug!("normalized {:?} to {:?}", ty, normalized_value);
+ debug!("normalized {ty:?} to {normalized_value:?}");
Some(normalized_value)
}
Err(err) => {
- debug!("failed to normalize {:?}: {:?}", ty, err);
+ debug!("failed to normalize {ty:?}: {err:?}");
None
}
}
@@ -1922,7 +2064,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
abi: sig.abi(),
}))
}
- ty::Adt(def, substs) => {
+ ty::Adt(def, args) => {
let did = def.did();
let kind = match def.adt_kind() {
AdtKind::Struct => ItemType::Struct,
@@ -1930,7 +2072,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
AdtKind::Enum => ItemType::Enum,
};
inline::record_extern_fqn(cx, did, kind);
- let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(substs));
+ let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(args));
Type::Path { path }
}
ty::Foreign(did) => {
@@ -1940,7 +2082,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
did,
false,
ThinVec::new(),
- ty::Binder::dummy(InternalSubsts::empty()),
+ ty::Binder::dummy(ty::GenericArgs::empty()),
);
Type::Path { path }
}
@@ -1953,10 +2095,10 @@ pub(crate) fn clean_middle_ty<'tcx>(
.principal_def_id()
.or_else(|| dids.next())
.unwrap_or_else(|| panic!("found trait object `{bound_ty:?}` with no traits?"));
- let substs = match obj.principal() {
- Some(principal) => principal.map_bound(|p| p.substs),
- // marker traits have no substs.
- _ => ty::Binder::dummy(InternalSubsts::empty()),
+ let args = match obj.principal() {
+ Some(principal) => principal.map_bound(|p| p.args),
+ // marker traits have no args.
+ _ => ty::Binder::dummy(ty::GenericArgs::empty()),
};
inline::record_extern_fqn(cx, did, ItemType::Trait);
@@ -1965,7 +2107,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
let mut bounds = dids
.map(|did| {
- let empty = ty::Binder::dummy(InternalSubsts::empty());
+ let empty = ty::Binder::dummy(ty::GenericArgs::empty());
let path = external_path(cx, did, false, ThinVec::new(), empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
PolyTrait { trait_: path, generic_params: Vec::new() }
@@ -1979,7 +2121,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
pb.map_bound(|pb| {
pb
// HACK(compiler-errors): Doesn't actually matter what self
- // type we put here, because we're only using the GAT's substs.
+ // type we put here, because we're only using the GAT's args.
.with_self_ty(cx.tcx, cx.tcx.types.self_param)
.projection_ty
}),
@@ -2005,7 +2147,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
.collect();
let late_bound_regions = late_bound_regions.into_iter().collect();
- let path = external_path(cx, did, false, bindings, substs);
+ let path = external_path(cx, did, false, bindings, args);
bounds.insert(0, PolyTrait { trait_: path, generic_params: late_bound_regions });
DynTrait(bounds, lifetime)
@@ -2026,9 +2168,9 @@ pub(crate) fn clean_middle_ty<'tcx>(
assoc: PathSegment {
name: cx.tcx.associated_item(alias_ty.skip_binder().def_id).name,
args: GenericArgs::AngleBracketed {
- args: substs_to_args(
+ args: ty_args_to_args(
cx,
- alias_ty.map_bound(|ty| ty.substs.as_slice()),
+ alias_ty.map_bound(|ty| ty.args.as_slice()),
true,
None,
)
@@ -2051,11 +2193,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
data.def_id,
false,
ThinVec::new(),
- bound_ty.rebind(data.substs),
+ bound_ty.rebind(data.args),
);
Type::Path { path }
} else {
- let ty = cx.tcx.type_of(data.def_id).subst(cx.tcx, data.substs);
+ let ty = cx.tcx.type_of(data.def_id).instantiate(cx.tcx, data.args);
clean_middle_ty(bound_ty.rebind(ty), cx, None, None)
}
}
@@ -2068,11 +2210,10 @@ pub(crate) fn clean_middle_ty<'tcx>(
}
}
- ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
// If it's already in the same alias, don't get an infinite loop.
if cx.current_type_aliases.contains_key(&def_id) {
- let path =
- external_path(cx, def_id, false, ThinVec::new(), bound_ty.rebind(substs));
+ let path = external_path(cx, def_id, false, ThinVec::new(), bound_ty.rebind(args));
Type::Path { path }
} else {
*cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
@@ -2081,7 +2222,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
let bounds = cx
.tcx
.explicit_item_bounds(def_id)
- .subst_iter_copied(cx.tcx, substs)
+ .iter_instantiated_copied(cx.tcx, args)
.map(|(bound, _)| bound)
.collect::>();
let ty = clean_middle_opaque_bounds(cx, bounds);
@@ -2110,7 +2251,6 @@ fn clean_middle_opaque_bounds<'tcx>(
cx: &mut DocContext<'tcx>,
bounds: Vec>,
) -> Type {
- let mut regions = vec![];
let mut has_sized = false;
let mut bounds = bounds
.iter()
@@ -2119,10 +2259,7 @@ fn clean_middle_opaque_bounds<'tcx>(
let trait_ref = match bound_predicate.skip_binder() {
ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
- if let Some(r) = clean_middle_region(reg) {
- regions.push(GenericBound::Outlives(r));
- }
- return None;
+ return clean_middle_region(reg).map(GenericBound::Outlives);
}
_ => return None,
};
@@ -2158,10 +2295,20 @@ fn clean_middle_opaque_bounds<'tcx>(
Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings))
})
.collect::>();
- bounds.extend(regions);
- if !has_sized && !bounds.is_empty() {
- bounds.insert(0, GenericBound::maybe_sized(cx));
+
+ if !has_sized {
+ bounds.push(GenericBound::maybe_sized(cx));
+ }
+
+ // Move trait bounds to the front.
+ bounds.sort_by_key(|b| !b.is_trait_bound());
+
+ // Add back a `Sized` bound if there are no *trait* bounds remaining (incl. `?Sized`).
+ // Since all potential trait bounds are at the front we can just check the first bound.
+ if bounds.first().map_or(true, |b| !b.is_trait_bound()) {
+ bounds.insert(0, GenericBound::sized(cx));
}
+
ImplTrait(bounds)
}
@@ -2174,7 +2321,7 @@ pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext
field.did,
field.name,
clean_middle_ty(
- ty::Binder::dummy(cx.tcx.type_of(field.did).subst_identity()),
+ ty::Binder::dummy(cx.tcx.type_of(field.did).instantiate_identity()),
cx,
Some(field.did),
None,
@@ -2305,10 +2452,10 @@ fn clean_bare_fn_ty<'tcx>(
pub(crate) fn reexport_chain<'tcx>(
tcx: TyCtxt<'tcx>,
import_def_id: LocalDefId,
- target_def_id: LocalDefId,
+ target_def_id: DefId,
) -> &'tcx [Reexport] {
for child in tcx.module_children_local(tcx.local_parent(import_def_id)) {
- if child.res.opt_def_id() == Some(target_def_id.to_def_id())
+ if child.res.opt_def_id() == Some(target_def_id)
&& child.reexport_chain.first().and_then(|r| r.id()) == Some(import_def_id.to_def_id())
{
return &child.reexport_chain;
@@ -2321,7 +2468,7 @@ pub(crate) fn reexport_chain<'tcx>(
fn get_all_import_attributes<'hir>(
cx: &mut DocContext<'hir>,
import_def_id: LocalDefId,
- target_def_id: LocalDefId,
+ target_def_id: DefId,
is_inline: bool,
) -> Vec<(Cow<'hir, ast::Attribute>, Option)> {
let mut attrs = Vec::new();
@@ -2336,7 +2483,7 @@ fn get_all_import_attributes<'hir>(
attrs = import_attrs.iter().map(|attr| (Cow::Borrowed(attr), Some(def_id))).collect();
first = false;
// We don't add attributes of an intermediate re-export if it has `#[doc(hidden)]`.
- } else if !cx.tcx.is_doc_hidden(def_id) {
+ } else if cx.render_options.document_hidden || !cx.tcx.is_doc_hidden(def_id) {
add_without_unwanted_attributes(&mut attrs, import_attrs, is_inline, Some(def_id));
}
}
@@ -2344,19 +2491,19 @@ fn get_all_import_attributes<'hir>(
}
fn filter_tokens_from_list(
- args_tokens: TokenStream,
+ args_tokens: &TokenStream,
should_retain: impl Fn(&TokenTree) -> bool,
) -> Vec {
let mut tokens = Vec::with_capacity(args_tokens.len());
let mut skip_next_comma = false;
- for token in args_tokens.into_trees() {
+ for token in args_tokens.trees() {
match token {
TokenTree::Token(Token { kind: TokenKind::Comma, .. }, _) if skip_next_comma => {
skip_next_comma = false;
}
- token if should_retain(&token) => {
+ token if should_retain(token) => {
skip_next_comma = false;
- tokens.push(token);
+ tokens.push(token.clone());
}
_ => {
skip_next_comma = true;
@@ -2414,7 +2561,7 @@ fn add_without_unwanted_attributes<'hir>(
match normal.item.args {
ast::AttrArgs::Delimited(ref mut args) => {
let tokens =
- filter_tokens_from_list(args.tokens.clone(), |token| {
+ filter_tokens_from_list(&args.tokens, |token| {
!matches!(
token,
TokenTree::Token(
@@ -2458,8 +2605,9 @@ fn clean_maybe_renamed_item<'tcx>(
ItemKind::Static(ty, mutability, body_id) => {
StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) })
}
- ItemKind::Const(ty, body_id) => ConstantItem(Constant {
+ ItemKind::Const(ty, generics, body_id) => ConstantItem(Constant {
type_: clean_ty(ty, cx),
+ generics: Box::new(clean_generics(generics, cx)),
kind: ConstantKind::Local { body: body_id, def_id },
}),
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
@@ -2538,7 +2686,7 @@ fn clean_maybe_renamed_item<'tcx>(
vec![generate_item_with_correct_attrs(
cx,
kind,
- item.owner_id.def_id,
+ item.owner_id.def_id.to_def_id(),
name,
import_id,
renamed,
@@ -2574,8 +2722,8 @@ fn clean_impl<'tcx>(
let for_ = clean_ty(impl_.self_ty, cx);
let type_alias =
for_.def_id(&cx.cache).and_then(|alias_def_id: DefId| match tcx.def_kind(alias_def_id) {
- DefKind::TyAlias => Some(clean_middle_ty(
- ty::Binder::dummy(tcx.type_of(def_id).subst_identity()),
+ DefKind::TyAlias { .. } => Some(clean_middle_ty(
+ ty::Binder::dummy(tcx.type_of(def_id).instantiate_identity()),
cx,
Some(def_id.to_def_id()),
None,
@@ -2640,15 +2788,12 @@ fn clean_extern_crate<'tcx>(
}
}
- // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
- vec![Item {
- name: Some(name),
- attrs: Box::new(Attributes::from_ast(attrs)),
- item_id: crate_def_id.into(),
- kind: Box::new(ExternCrateItem { src: orig_name }),
- cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
- inline_stmt_id: Some(krate_owner_def_id),
- }]
+ vec![Item::from_def_id_and_parts(
+ krate_owner_def_id,
+ Some(name),
+ ExternCrateItem { src: orig_name },
+ cx,
+ )]
}
fn clean_use_statement<'tcx>(
@@ -2662,9 +2807,6 @@ fn clean_use_statement<'tcx>(
let mut items = Vec::new();
let hir::UsePath { segments, ref res, span } = *path;
for &res in res {
- if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res {
- continue;
- }
let path = hir::Path { segments, res, span };
items.append(&mut clean_use_statement_inner(import, name, &path, kind, cx, inlined_names));
}
@@ -2679,6 +2821,9 @@ fn clean_use_statement_inner<'tcx>(
cx: &mut DocContext<'tcx>,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
) -> Vec {
+ if should_ignore_res(path.res) {
+ return Vec::new();
+ }
// We need this comparison because some imports (for std types for example)
// are "inserted" as well but directly by the compiler and they should not be
// taken into account.
@@ -2691,11 +2836,12 @@ fn clean_use_statement_inner<'tcx>(
let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
let pub_underscore = visibility.is_public() && name == kw::Underscore;
let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id);
+ let import_def_id = import.owner_id.def_id.to_def_id();
// The parent of the module in which this import resides. This
// is the same as `current_mod` if that's already the top
// level module.
- let parent_mod = cx.tcx.parent_module_from_def_id(current_mod);
+ let parent_mod = cx.tcx.parent_module_from_def_id(current_mod.to_local_def_id());
// This checks if the import can be seen from a higher level module.
// In other words, it checks if the visibility is the equivalent of
@@ -2741,9 +2887,14 @@ fn clean_use_statement_inner<'tcx>(
let inner = if kind == hir::UseKind::Glob {
if !denied {
let mut visited = DefIdSet::default();
- if let Some(items) =
- inline::try_inline_glob(cx, path.res, current_mod, &mut visited, inlined_names)
- {
+ if let Some(items) = inline::try_inline_glob(
+ cx,
+ path.res,
+ current_mod,
+ &mut visited,
+ inlined_names,
+ import,
+ ) {
return items;
}
}
@@ -2759,7 +2910,6 @@ fn clean_use_statement_inner<'tcx>(
denied = true;
}
if !denied {
- let import_def_id = import.owner_id.to_def_id();
if let Some(mut items) = inline::try_inline(
cx,
path.res,
@@ -2779,7 +2929,7 @@ fn clean_use_statement_inner<'tcx>(
Import::new_simple(name, resolve_use_source(cx, path), true)
};
- vec![Item::from_def_id_and_parts(import.owner_id.to_def_id(), None, ImportItem(inner), cx)]
+ vec![Item::from_def_id_and_parts(import_def_id, None, ImportItem(inner), cx)]
}
fn clean_maybe_renamed_foreign_item<'tcx>(
diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs
index ef38ca3c1..66d10f236 100644
--- a/src/librustdoc/clean/render_macro_matchers.rs
+++ b/src/librustdoc/clean/render_macro_matchers.rs
@@ -76,17 +76,13 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option reparsed_trees,
- Err(diagnostic) => {
- diagnostic.cancel();
- return None;
- }
- };
- if reparsed_trees.len() != 1 {
+ if parser.token == token::Eof {
+ return None;
+ }
+ let reparsed_tree = parser.parse_token_tree();
+ if parser.token != token::Eof {
return None;
}
- let reparsed_tree = reparsed_trees.pop().unwrap();
// Compare against the original tree.
if reparsed_tree.eq_unspanned(matcher) { Some(snippet) } else { None }
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 65b1b72ad..7b8f20326 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -47,7 +47,9 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> ThinVec, child: DefId, trait_: DefId)
})
.any(|did| trait_is_same_or_supertrait(cx, did, trait_))
}
+
+/// Move bounds that are (likely) directly attached to generic parameters from the where-clause to
+/// the respective parameter.
+///
+/// There is no guarantee that this is what the user actually wrote but we have no way of knowing.
+// FIXME(fmease): It'd make a lot of sense to just incorporate this logic into `clean_ty_generics`
+// making every of its users benefit from it.
+pub(crate) fn move_bounds_to_generic_parameters(generics: &mut clean::Generics) {
+ use clean::types::*;
+
+ let mut where_predicates = ThinVec::new();
+ for mut pred in generics.where_predicates.drain(..) {
+ if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred
+ && let Some(GenericParamDef {
+ kind: GenericParamDefKind::Type { bounds: param_bounds, .. },
+ ..
+ }) = generics.params.iter_mut().find(|param| ¶m.name == arg)
+ {
+ param_bounds.append(bounds);
+ } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred
+ && let Some(GenericParamDef {
+ kind: GenericParamDefKind::Lifetime { outlives: param_bounds },
+ ..
+ }) = generics.params.iter_mut().find(|param| ¶m.name == arg)
+ {
+ param_bounds.extend(bounds.drain(..).map(|bound| match bound {
+ GenericBound::Outlives(lifetime) => lifetime,
+ _ => unreachable!(),
+ }));
+ } else {
+ where_predicates.push(pred);
+ }
+ }
+ generics.where_predicates = where_predicates;
+}
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 26139d527..49bde1d31 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -78,7 +78,7 @@ impl ItemId {
#[track_caller]
pub(crate) fn expect_def_id(self) -> DefId {
self.as_def_id()
- .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{:?}` isn't a DefId", self))
+ .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{self:?}` isn't a DefId"))
}
#[inline]
@@ -352,7 +352,7 @@ fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
match tcx.def_kind(parent) {
DefKind::Struct | DefKind::Union => false,
DefKind::Variant => true,
- parent_kind => panic!("unexpected parent kind: {:?}", parent_kind),
+ parent_kind => panic!("unexpected parent kind: {parent_kind:?}"),
}
}
@@ -436,7 +436,7 @@ impl Item {
attrs: Box,
cfg: Option>,
) -> Item {
- trace!("name={:?}, def_id={:?} cfg={:?}", name, def_id, cfg);
+ trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
Item {
item_id: def_id.into(),
@@ -451,11 +451,7 @@ impl Item {
pub(crate) fn links(&self, cx: &Context<'_>) -> Vec {
use crate::html::format::{href, link_tooltip};
- let Some(links) = cx.cache()
- .intra_doc_links
- .get(&self.item_id) else {
- return vec![]
- };
+ let Some(links) = cx.cache().intra_doc_links.get(&self.item_id) else { return vec![] };
links
.iter()
.filter_map(|ItemLink { link: s, link_text, page_id: id, ref fragment }| {
@@ -484,11 +480,9 @@ impl Item {
/// the link text, but does need to know which `[]`-bracketed names
/// are actually links.
pub(crate) fn link_names(&self, cache: &Cache) -> Vec {
- let Some(links) = cache
- .intra_doc_links
- .get(&self.item_id) else {
- return vec![];
- };
+ let Some(links) = cache.intra_doc_links.get(&self.item_id) else {
+ return vec![];
+ };
links
.iter()
.map(|ItemLink { link: s, link_text, .. }| RenderedLink {
@@ -830,9 +824,9 @@ pub(crate) enum ItemKind {
ProcMacroItem(ProcMacro),
PrimitiveItem(PrimitiveType),
/// A required associated constant in a trait declaration.
- TyAssocConstItem(Type),
+ TyAssocConstItem(Box, Type),
/// An associated constant in a trait impl or a provided one in a trait declaration.
- AssocConstItem(Type, ConstantKind),
+ AssocConstItem(Box, Type, ConstantKind),
/// A required associated type in a trait declaration.
///
/// The bounds may be non-empty if there is a `where` clause.
@@ -877,8 +871,8 @@ impl ItemKind {
| MacroItem(_)
| ProcMacroItem(_)
| PrimitiveItem(_)
- | TyAssocConstItem(_)
- | AssocConstItem(_, _)
+ | TyAssocConstItem(..)
+ | AssocConstItem(..)
| TyAssocTypeItem(..)
| AssocTypeItem(..)
| StrippedItem(_)
@@ -1225,15 +1219,24 @@ pub(crate) enum GenericBound {
}
impl GenericBound {
+ pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
+ Self::sized_with(cx, hir::TraitBoundModifier::None)
+ }
+
pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
+ Self::sized_with(cx, hir::TraitBoundModifier::Maybe)
+ }
+
+ fn sized_with(cx: &mut DocContext<'_>, modifier: hir::TraitBoundModifier) -> GenericBound {
let did = cx.tcx.require_lang_item(LangItem::Sized, None);
- let empty = ty::Binder::dummy(ty::InternalSubsts::empty());
+ let empty = ty::Binder::dummy(ty::GenericArgs::empty());
let path = external_path(cx, did, false, ThinVec::new(), empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
- GenericBound::TraitBound(
- PolyTrait { trait_: path, generic_params: Vec::new() },
- hir::TraitBoundModifier::Maybe,
- )
+ GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifier)
+ }
+
+ pub(crate) fn is_trait_bound(&self) -> bool {
+ matches!(self, Self::TraitBound(..))
}
pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
@@ -1275,7 +1278,7 @@ impl Lifetime {
}
}
-#[derive(Clone, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub(crate) enum WherePredicate {
BoundPredicate { ty: Type, bounds: Vec, bound_params: Vec },
RegionPredicate { lifetime: Lifetime, bounds: Vec },
@@ -1345,7 +1348,7 @@ impl GenericParamDef {
}
// maybe use a Generic enum and use Vec?
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
pub(crate) struct Generics {
pub(crate) params: ThinVec,
pub(crate) where_predicates: ThinVec,
@@ -1782,7 +1785,6 @@ impl PrimitiveType {
}
pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
- use ty::fast_reject::SimplifiedType::*;
use ty::{FloatTy, IntTy, UintTy};
use PrimitiveType::*;
static CELL: OnceCell = OnceCell::new();
@@ -1790,38 +1792,38 @@ impl PrimitiveType {
let single = |x| iter::once(x).collect();
CELL.get_or_init(move || {
map! {
- Isize => single(IntSimplifiedType(IntTy::Isize)),
- I8 => single(IntSimplifiedType(IntTy::I8)),
- I16 => single(IntSimplifiedType(IntTy::I16)),
- I32 => single(IntSimplifiedType(IntTy::I32)),
- I64 => single(IntSimplifiedType(IntTy::I64)),
- I128 => single(IntSimplifiedType(IntTy::I128)),
- Usize => single(UintSimplifiedType(UintTy::Usize)),
- U8 => single(UintSimplifiedType(UintTy::U8)),
- U16 => single(UintSimplifiedType(UintTy::U16)),
- U32 => single(UintSimplifiedType(UintTy::U32)),
- U64 => single(UintSimplifiedType(UintTy::U64)),
- U128 => single(UintSimplifiedType(UintTy::U128)),
- F32 => single(FloatSimplifiedType(FloatTy::F32)),
- F64 => single(FloatSimplifiedType(FloatTy::F64)),
- Str => single(StrSimplifiedType),
- Bool => single(BoolSimplifiedType),
- Char => single(CharSimplifiedType),
- Array => single(ArraySimplifiedType),
- Slice => single(SliceSimplifiedType),
+ Isize => single(SimplifiedType::Int(IntTy::Isize)),
+ I8 => single(SimplifiedType::Int(IntTy::I8)),
+ I16 => single(SimplifiedType::Int(IntTy::I16)),
+ I32 => single(SimplifiedType::Int(IntTy::I32)),
+ I64 => single(SimplifiedType::Int(IntTy::I64)),
+ I128 => single(SimplifiedType::Int(IntTy::I128)),
+ Usize => single(SimplifiedType::Uint(UintTy::Usize)),
+ U8 => single(SimplifiedType::Uint(UintTy::U8)),
+ U16 => single(SimplifiedType::Uint(UintTy::U16)),
+ U32 => single(SimplifiedType::Uint(UintTy::U32)),
+ U64 => single(SimplifiedType::Uint(UintTy::U64)),
+ U128 => single(SimplifiedType::Uint(UintTy::U128)),
+ F32 => single(SimplifiedType::Float(FloatTy::F32)),
+ F64 => single(SimplifiedType::Float(FloatTy::F64)),
+ Str => single(SimplifiedType::Str),
+ Bool => single(SimplifiedType::Bool),
+ Char => single(SimplifiedType::Char),
+ Array => single(SimplifiedType::Array),
+ Slice => single(SimplifiedType::Slice),
// FIXME: If we ever add an inherent impl for tuples
// with different lengths, they won't show in rustdoc.
//
// Either manually update this arrayvec at this point
// or start with a more complex refactoring.
- Tuple => [TupleSimplifiedType(1), TupleSimplifiedType(2), TupleSimplifiedType(3)].into(),
- Unit => single(TupleSimplifiedType(0)),
- RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into_iter().collect(),
- Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(),
+ Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
+ Unit => single(SimplifiedType::Tuple(0)),
+ RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
+ Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
// FIXME: This will be wrong if we ever add inherent impls
// for function pointers.
- Fn => single(FunctionSimplifiedType(1)),
- Never => single(NeverSimplifiedType),
+ Fn => single(SimplifiedType::Function(1)),
+ Never => single(SimplifiedType::Never),
}
})
}
@@ -2210,6 +2212,17 @@ pub(crate) enum GenericArgs {
Parenthesized { inputs: Box<[Type]>, output: Option> },
}
+impl GenericArgs {
+ pub(crate) fn is_empty(&self) -> bool {
+ match self {
+ GenericArgs::AngleBracketed { args, bindings } => {
+ args.is_empty() && bindings.is_empty()
+ }
+ GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
+ }
+ }
+}
+
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) struct PathSegment {
pub(crate) name: Symbol,
@@ -2253,6 +2266,7 @@ pub(crate) struct Static {
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub(crate) struct Constant {
pub(crate) type_: Type,
+ pub(crate) generics: Box,
pub(crate) kind: ConstantKind,
}
@@ -2502,7 +2516,8 @@ mod size_asserts {
static_assert_size!(GenericParamDef, 56);
static_assert_size!(Generics, 16);
static_assert_size!(Item, 56);
- static_assert_size!(ItemKind, 64);
+ // FIXME(generic_const_items): Further reduce the size.
+ static_assert_size!(ItemKind, 72);
static_assert_size!(PathSegment, 40);
static_assert_size!(Type, 32);
// tidy-alphabetical-end
diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs
index 394954208..4907a5527 100644
--- a/src/librustdoc/clean/types/tests.rs
+++ b/src/librustdoc/clean/types/tests.rs
@@ -73,7 +73,7 @@ fn should_not_trim() {
fn is_same_generic() {
use crate::clean::types::{PrimitiveType, Type};
use crate::formats::cache::Cache;
- let cache = Cache::new(false);
+ let cache = Cache::new(false, false);
let generic = Type::Generic(rustc_span::symbol::sym::Any);
let unit = Type::Primitive(PrimitiveType::Unit);
assert!(!generic.is_doc_subtype_of(&unit, &cache));
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index b786ecbe3..a86bbcc76 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -13,11 +13,10 @@ use rustc_ast as ast;
use rustc_ast::tokenstream::TokenTree;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
use rustc_middle::mir;
use rustc_middle::mir::interpret::ConstValue;
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt};
use rustc_span::symbol::{kw, sym, Symbol};
use std::fmt::Write as _;
use std::mem;
@@ -39,11 +38,15 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
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.item_id.krate()))
- {
+ if cx.tcx.is_compiler_builtins(it.item_id.krate()) {
cx.cache.masked_crates.insert(it.item_id.krate());
+ } else if it.is_extern_crate()
+ && it.attrs.has_doc_flag(sym::masked)
+ && let Some(def_id) = it.item_id.as_def_id()
+ && let Some(local_def_id) = def_id.as_local()
+ && let Some(cnum) = cx.tcx.extern_mod_stmt_cnum(local_def_id)
+ {
+ cx.cache.masked_crates.insert(cnum);
}
}
}
@@ -71,7 +74,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
Crate { module, external_traits: cx.external_traits.clone() }
}
-pub(crate) fn substs_to_args<'tcx>(
+pub(crate) fn ty_args_to_args<'tcx>(
cx: &mut DocContext<'tcx>,
args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>,
has_self: bool,
@@ -114,12 +117,12 @@ fn external_generic_args<'tcx>(
did: DefId,
has_self: bool,
bindings: ThinVec,
- substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
+ ty_args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
) -> GenericArgs {
- let args = substs_to_args(cx, substs.map_bound(|substs| &substs[..]), has_self, Some(did));
+ let args = ty_args_to_args(cx, ty_args.map_bound(|args| &args[..]), has_self, Some(did));
if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
- let ty = substs
+ let ty = ty_args
.iter()
.nth(if has_self { 1 } else { 0 })
.unwrap()
@@ -147,7 +150,7 @@ pub(super) fn external_path<'tcx>(
did: DefId,
has_self: bool,
bindings: ThinVec,
- substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
+ args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
) -> Path {
let def_kind = cx.tcx.def_kind(did);
let name = cx.tcx.item_name(did);
@@ -155,7 +158,7 @@ pub(super) fn external_path<'tcx>(
res: Res::Def(def_kind, did),
segments: thin_vec![PathSegment {
name,
- args: external_generic_args(cx, did, has_self, bindings, substs),
+ args: external_generic_args(cx, did, has_self, bindings, args),
}],
}
}
@@ -217,7 +220,7 @@ pub(crate) fn build_deref_target_impls(
pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
use rustc_hir::*;
- debug!("trying to get a name from pattern: {:?}", p);
+ debug!("trying to get a name from pattern: {p:?}");
Symbol::intern(&match p.kind {
PatKind::Wild | PatKind::Struct(..) => return kw::Underscore,
@@ -250,7 +253,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
match n.kind() {
- ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs: _ }) => {
+ ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => {
let s = if let Some(def) = def.as_local() {
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def))
} else {
@@ -275,7 +278,7 @@ pub(crate) fn print_evaluated_const(
underscores_and_type: bool,
) -> Option {
tcx.const_eval_poly(def_id).ok().and_then(|val| {
- let ty = tcx.type_of(def_id).subst_identity();
+ let ty = tcx.type_of(def_id).instantiate_identity();
match (val, ty.kind()) {
(_, &ty::Ref(..)) => None,
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
@@ -460,7 +463,7 @@ pub(crate) fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String {
/// Given a type Path, resolve it to a Type using the TyCtxt
pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
- debug!("resolve_type({:?})", path);
+ debug!("resolve_type({path:?})");
match path.res {
Res::PrimTy(p) => Primitive(PrimitiveType::from(p)),
@@ -479,12 +482,6 @@ pub(crate) fn get_auto_trait_and_blanket_impls(
cx: &mut DocContext<'_>,
item_def_id: DefId,
) -> impl Iterator {
- // FIXME: To be removed once `parallel_compiler` bugs are fixed!
- // More information in .
- if cfg!(parallel_compiler) {
- return vec![].into_iter().chain(vec![].into_iter());
- }
-
let auto_impls = cx
.sess()
.prof
@@ -505,16 +502,30 @@ pub(crate) fn get_auto_trait_and_blanket_impls(
/// [`href()`]: crate::html::format::href
pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
use DefKind::*;
- debug!("register_res({:?})", res);
+ debug!("register_res({res:?})");
let (kind, did) = match res {
Res::Def(
- kind @ (AssocTy | AssocFn | AssocConst | Variant | Fn | TyAlias | Enum | Trait | Struct
- | Union | Mod | ForeignTy | Const | Static(_) | Macro(..) | TraitAlias),
+ kind @ (AssocTy
+ | AssocFn
+ | AssocConst
+ | Variant
+ | Fn
+ | TyAlias { .. }
+ | Enum
+ | Trait
+ | Struct
+ | Union
+ | Mod
+ | ForeignTy
+ | Const
+ | Static(_)
+ | Macro(..)
+ | TraitAlias),
did,
) => (kind.into(), did),
- _ => panic!("register_res: unexpected {:?}", res),
+ _ => panic!("register_res: unexpected {res:?}"),
};
if did.is_local() {
return did;
@@ -592,8 +603,12 @@ pub(super) fn render_macro_arms<'a>(
) -> String {
let mut out = String::new();
for matcher in matchers {
- writeln!(out, " {} => {{ ... }}{}", render_macro_matcher(tcx, matcher), arm_delim)
- .unwrap();
+ writeln!(
+ out,
+ " {matcher} => {{ ... }}{arm_delim}",
+ matcher = render_macro_matcher(tcx, matcher),
+ )
+ .unwrap();
}
out
}
@@ -609,22 +624,54 @@ pub(super) fn display_macro_source(
let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
if def.macro_rules {
- format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(cx.tcx, matchers, ";"))
+ format!("macro_rules! {name} {{\n{arms}}}", arms = render_macro_arms(cx.tcx, matchers, ";"))
} else {
if matchers.len() <= 1 {
format!(
- "{}macro {}{} {{\n ...\n}}",
- visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
- name,
- matchers.map(|matcher| render_macro_matcher(cx.tcx, matcher)).collect::(),
+ "{vis}macro {name}{matchers} {{\n ...\n}}",
+ vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
+ matchers = matchers
+ .map(|matcher| render_macro_matcher(cx.tcx, matcher))
+ .collect::(),
)
} else {
format!(
- "{}macro {} {{\n{}}}",
- visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
- name,
- render_macro_arms(cx.tcx, matchers, ","),
+ "{vis}macro {name} {{\n{arms}}}",
+ vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
+ arms = render_macro_arms(cx.tcx, matchers, ","),
)
}
}
}
+
+pub(crate) fn inherits_doc_hidden(
+ tcx: TyCtxt<'_>,
+ mut def_id: LocalDefId,
+ stop_at: Option,
+) -> bool {
+ let hir = tcx.hir();
+ while let Some(id) = tcx.opt_local_parent(def_id) {
+ if let Some(stop_at) = stop_at && id == stop_at {
+ return false;
+ }
+ def_id = id;
+ if tcx.is_doc_hidden(def_id.to_def_id()) {
+ return true;
+ } else if let Some(node) = hir.find_by_def_id(def_id) &&
+ matches!(
+ node,
+ hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }),
+ )
+ {
+ // `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly
+ // on them, they don't inherit it from the parent context.
+ return false;
+ }
+ }
+ false
+}
+
+#[inline]
+pub(crate) fn should_ignore_res(res: Res) -> bool {
+ matches!(res, Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..))
+}
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 217f1a6ee..81fb13f41 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -50,7 +50,7 @@ impl TryFrom<&str> for OutputFormat {
match value {
"json" => Ok(OutputFormat::Json),
"html" => Ok(OutputFormat::Html),
- _ => Err(format!("unknown output format `{}`", value)),
+ _ => Err(format!("unknown output format `{value}`")),
}
}
}
@@ -383,7 +383,7 @@ impl Options {
match kind.parse() {
Ok(kind) => emit.push(kind),
Err(()) => {
- diag.err(format!("unrecognized emission type: {}", kind));
+ diag.err(format!("unrecognized emission type: {kind}"));
return Err(1);
}
}
@@ -415,7 +415,7 @@ impl Options {
println!("rustdoc: [check-theme] Starting tests! (Ignoring all other arguments)");
for theme_file in to_check.iter() {
- print!(" - Checking \"{}\"...", theme_file);
+ print!(" - Checking \"{theme_file}\"...");
let (success, differences) = theme::test_theme_against(theme_file, &paths, &diag);
if !differences.is_empty() || !success {
println!(" FAILED");
@@ -556,30 +556,28 @@ impl Options {
matches.opt_strs("theme").iter().map(|s| (PathBuf::from(&s), s.to_owned()))
{
if !theme_file.is_file() {
- diag.struct_err(format!("invalid argument: \"{}\"", theme_s))
+ diag.struct_err(format!("invalid argument: \"{theme_s}\""))
.help("arguments to --theme must be files")
.emit();
return Err(1);
}
if theme_file.extension() != Some(OsStr::new("css")) {
- diag.struct_err(format!("invalid argument: \"{}\"", theme_s))
+ diag.struct_err(format!("invalid argument: \"{theme_s}\""))
.help("arguments to --theme must have a .css extension")
.emit();
return Err(1);
}
let (success, ret) = theme::test_theme_against(&theme_file, &paths, &diag);
if !success {
- diag.struct_err(format!("error loading theme file: \"{}\"", theme_s)).emit();
+ diag.struct_err(format!("error loading theme file: \"{theme_s}\"")).emit();
return Err(1);
} else if !ret.is_empty() {
diag.struct_warn(format!(
- "theme file \"{}\" is missing CSS rules from the default theme",
- theme_s
+ "theme file \"{theme_s}\" is missing CSS rules from the default theme",
))
.warn("the theme may appear incorrect when loaded")
.help(format!(
- "to see what rules are missing, call `rustdoc --check-theme \"{}\"`",
- theme_s
+ "to see what rules are missing, call `rustdoc --check-theme \"{theme_s}\"`",
))
.emit();
}
@@ -608,7 +606,7 @@ impl Options {
match matches.opt_str("r").as_deref() {
Some("rust") | None => {}
Some(s) => {
- diag.struct_err(format!("unknown input format: {}", s)).emit();
+ diag.struct_err(format!("unknown input format: {s}")).emit();
return Err(1);
}
}
@@ -628,7 +626,7 @@ impl Options {
let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) {
Ok(types) => types,
Err(e) => {
- diag.struct_err(format!("unknown crate type: {}", e)).emit();
+ diag.struct_err(format!("unknown crate type: {e}")).emit();
return Err(1);
}
};
@@ -787,7 +785,7 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Han
for &flag in deprecated_flags.iter() {
if matches.opt_present(flag) {
- diag.struct_warn(format!("the `{}` flag is deprecated", flag))
+ diag.struct_warn(format!("the `{flag}` flag is deprecated"))
.note(
"see issue #44136 \
for more information",
@@ -800,7 +798,7 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Han
for &flag in removed_flags.iter() {
if matches.opt_present(flag) {
- let mut err = diag.struct_warn(format!("the `{}` flag no longer functions", flag));
+ let mut err = diag.struct_warn(format!("the `{flag}` flag no longer functions"));
err.note(
"see issue #44136 \
for more information",
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 9687b8b18..4c8dab61f 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -10,6 +10,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{HirId, Path};
use rustc_interface::interface;
+use rustc_lint::{late_lint_mod, MissingDoc};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks};
@@ -45,7 +46,7 @@ pub(crate) struct DocContext<'tcx> {
// The current set of parameter substitutions,
// for expanding type aliases at the HIR level:
/// Table `DefId` of type, lifetime, or const parameter -> substituted type, lifetime, or const
- pub(crate) substs: DefIdMap,
+ pub(crate) args: DefIdMap,
pub(crate) current_type_aliases: DefIdMap,
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
pub(crate) impl_trait_bounds: FxHashMap>,
@@ -85,17 +86,17 @@ impl<'tcx> DocContext<'tcx> {
/// the substitutions for a type alias' RHS.
pub(crate) fn enter_alias(
&mut self,
- substs: DefIdMap,
+ args: DefIdMap,
def_id: DefId,
f: F,
) -> R
where
F: FnOnce(&mut Self) -> R,
{
- let old_substs = mem::replace(&mut self.substs, substs);
+ let old_args = mem::replace(&mut self.args, args);
*self.current_type_aliases.entry(def_id).or_insert(0) += 1;
let r = f(self);
- self.substs = old_substs;
+ self.args = old_args;
if let Some(count) = self.current_type_aliases.get_mut(&def_id) {
*count -= 1;
if *count == 0 {
@@ -136,19 +137,13 @@ pub(crate) fn new_handler(
ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip();
Box::new(
- EmitterWriter::stderr(
- color_config,
- source_map.map(|sm| sm as _),
- None,
- fallback_bundle,
- short,
- unstable_opts.teach,
- diagnostic_width,
- false,
- unstable_opts.track_diagnostics,
- TerminalUrl::No,
- )
- .ui_testing(unstable_opts.ui_testing),
+ EmitterWriter::stderr(color_config, fallback_bundle)
+ .sm(source_map.map(|sm| sm as _))
+ .short_message(short)
+ .teach(unstable_opts.teach)
+ .diagnostic_width(diagnostic_width)
+ .track_diagnostics(unstable_opts.track_diagnostics)
+ .ui_testing(unstable_opts.ui_testing),
)
}
ErrorOutputType::Json { pretty, json_rendered } => {
@@ -173,10 +168,8 @@ pub(crate) fn new_handler(
}
};
- rustc_errors::Handler::with_emitter_and_flags(
- emitter,
- unstable_opts.diagnostic_handler_flags(true),
- )
+ rustc_errors::Handler::with_emitter(emitter)
+ .with_flags(unstable_opts.diagnostic_handler_flags(true))
}
/// Parse, resolve, and typecheck the given crate.
@@ -270,8 +263,9 @@ pub(crate) fn create_config(
parse_sess_created: None,
register_lints: Some(Box::new(crate::lint::register_lints)),
override_queries: Some(|_sess, providers, _external_providers| {
+ // We do not register late module lints, so this only runs `MissingDoc`.
// Most lints will require typechecking, so just don't run them.
- providers.lint_mod = |_, _| {};
+ providers.lint_mod = |tcx, module_def_id| late_lint_mod(tcx, module_def_id, MissingDoc);
// hack so that `used_trait_imports` won't try to call typeck
providers.used_trait_imports = |_, _| {
static EMPTY_SET: LazyLock> = LazyLock::new(UnordSet::default);
@@ -289,13 +283,14 @@ pub(crate) fn create_config(
let hir = tcx.hir();
let body = hir.body(hir.body_owned_by(def_id));
- debug!("visiting body for {:?}", def_id);
+ debug!("visiting body for {def_id:?}");
EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
(rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id)
};
}),
make_codegen_backend: None,
registry: rustc_driver::diagnostics_registry(),
+ ice_file: None,
}
}
@@ -324,9 +319,7 @@ pub(crate) fn run_global_ctxt(
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
});
tcx.sess.abort_if_errors();
- tcx.sess.time("missing_docs", || {
- rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
- });
+ tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx));
tcx.sess.time("check_mod_attrs", || {
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module))
});
@@ -340,12 +333,12 @@ pub(crate) fn run_global_ctxt(
param_env: ParamEnv::empty(),
external_traits: Default::default(),
active_extern_traits: Default::default(),
- substs: Default::default(),
+ args: Default::default(),
current_type_aliases: Default::default(),
impl_trait_bounds: Default::default(),
generated_synthetics: Default::default(),
auto_traits,
- cache: Cache::new(render_options.document_private),
+ cache: Cache::new(render_options.document_private, render_options.document_hidden),
inlined: FxHashSet::default(),
output_format,
render_options,
@@ -384,7 +377,7 @@ pub(crate) fn run_global_ctxt(
fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) {
let mut msg =
- diag.struct_span_warn(sp, format!("the `#![doc({})]` attribute is deprecated", name));
+ diag.struct_span_warn(sp, format!("the `#![doc({name})]` attribute is deprecated"));
msg.note(
"see issue #44136 \
for more information",
@@ -477,7 +470,7 @@ impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> {
}
fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) {
- debug!("visiting path {:?}", path);
+ debug!("visiting path {path:?}");
if path.res == Res::Err {
// We have less context here than in rustc_resolve,
// so we can only emit the name and span.
@@ -494,8 +487,7 @@ impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> {
self.tcx.sess,
path.span,
E0433,
- "failed to resolve: {}",
- label
+ "failed to resolve: {label}",
);
err.span_label(path.span, label);
err.note("this error was originally ignored because you are running `rustdoc`");
diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs
index d58b8dc6a..82c1a5039 100644
--- a/src/librustdoc/docfs.rs
+++ b/src/librustdoc/docfs.rs
@@ -72,9 +72,9 @@ impl DocFS {
let sender = self.errors.clone().expect("can't write after closing");
self.pool.execute(move || {
fs::write(&path, contents).unwrap_or_else(|e| {
- sender.send(format!("\"{}\": {}", path.display(), e)).unwrap_or_else(|_| {
- panic!("failed to send error on \"{}\"", path.display())
- })
+ sender.send(format!("\"{path}\": {e}", path = path.display())).unwrap_or_else(
+ |_| panic!("failed to send error on \"{}\"", path.display()),
+ )
});
});
} else {
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 217257316..36d5adb63 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -1,7 +1,7 @@
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc;
-use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError, TerminalUrl};
+use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{self as hir, intravisit, CRATE_HIR_ID};
use rustc_interface::interface;
@@ -108,6 +108,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
override_queries: None,
make_codegen_backend: None,
registry: rustc_driver::diagnostics_registry(),
+ ice_file: None,
};
let test_args = options.test_args.clone();
@@ -191,7 +192,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
// The allow lint level is not expected,
// as if allow is specified, no message
// is to be emitted.
- v => unreachable!("Invalid lint level '{}'", v),
+ v => unreachable!("Invalid lint level '{v}'"),
})
.unwrap_or("warn")
.to_string();
@@ -403,7 +404,7 @@ fn run_test(
compiler.stdin(Stdio::piped());
compiler.stderr(Stdio::piped());
- debug!("compiler invocation for doctest: {:?}", compiler);
+ debug!("compiler invocation for doctest: {compiler:?}");
let mut child = compiler.spawn().expect("Failed to spawn rustc process");
{
@@ -468,7 +469,9 @@ fn run_test(
// Run the code!
let mut cmd;
+ let output_file = make_maybe_absolute_path(output_file);
if let Some(tool) = runtool {
+ let tool = make_maybe_absolute_path(tool.into());
cmd = Command::new(tool);
cmd.args(runtool_args);
cmd.arg(output_file);
@@ -502,6 +505,20 @@ fn run_test(
Ok(())
}
+/// Converts a path intended to use as a command to absolute if it is
+/// relative, and not a single component.
+///
+/// This is needed to deal with relative paths interacting with
+/// `Command::current_dir` in a platform-specific way.
+fn make_maybe_absolute_path(path: PathBuf) -> PathBuf {
+ if path.components().count() == 1 {
+ // Look up process via PATH.
+ path
+ } else {
+ std::env::current_dir().map(|c| c.join(&path)).unwrap_or_else(|_| path)
+ }
+}
+
/// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
/// lines before the test code begins as well as if the output stream supports colors or not.
pub(crate) fn make_test(
@@ -557,36 +574,14 @@ pub(crate) fn make_test(
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
false,
);
- supports_color = EmitterWriter::stderr(
- ColorConfig::Auto,
- None,
- None,
- fallback_bundle.clone(),
- false,
- false,
- Some(80),
- false,
- false,
- TerminalUrl::No,
- )
- .supports_color();
+ supports_color = EmitterWriter::stderr(ColorConfig::Auto, fallback_bundle.clone())
+ .diagnostic_width(Some(80))
+ .supports_color();
- let emitter = EmitterWriter::new(
- Box::new(io::sink()),
- None,
- None,
- fallback_bundle,
- false,
- false,
- false,
- None,
- false,
- false,
- TerminalUrl::No,
- );
+ let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle);
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
- let handler = Handler::with_emitter(false, None, Box::new(emitter));
+ let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings();
let sess = ParseSess::with_span_handler(handler, sm);
let mut found_main = false;
@@ -653,8 +648,7 @@ pub(crate) fn make_test(
(found_main, found_extern_crate, found_macro)
})
});
- let Ok((already_has_main, already_has_extern_crate, found_macro)) = result
- else {
+ let Ok((already_has_main, already_has_extern_crate, found_macro)) = result else {
// If the parser panicked due to a fatal error, pass the test code through unchanged.
// The error will be reported during compilation.
return (s.to_owned(), 0, false);
@@ -760,21 +754,9 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
false,
);
- let emitter = EmitterWriter::new(
- Box::new(io::sink()),
- None,
- None,
- fallback_bundle,
- false,
- false,
- false,
- None,
- false,
- false,
- TerminalUrl::No,
- );
+ let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle);
- let handler = Handler::with_emitter(false, None, Box::new(emitter));
+ let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings();
let sess = ParseSess::with_span_handler(handler, sm);
let mut parser =
match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) {
@@ -967,7 +949,7 @@ impl Collector {
if !item_path.is_empty() {
item_path.push(' ');
}
- format!("{} - {}(line {})", filename.prefer_local(), item_path, line)
+ format!("{} - {item_path}(line {line})", filename.prefer_local())
}
pub(crate) fn set_position(&mut self, position: Span) {
@@ -1044,7 +1026,7 @@ impl Tester for Collector {
path.push(&test_id);
if let Err(err) = std::fs::create_dir_all(&path) {
- eprintln!("Couldn't create directory for doctest executables: {}", err);
+ eprintln!("Couldn't create directory for doctest executables: {err}");
panic::resume_unwind(Box::new(()));
}
@@ -1113,7 +1095,7 @@ impl Tester for Collector {
eprint!("Test executable succeeded, but it's marked `should_panic`.");
}
TestFailure::MissingErrorCodes(codes) => {
- eprint!("Some expected error codes were not found: {:?}", codes);
+ eprint!("Some expected error codes were not found: {codes:?}");
}
TestFailure::ExecutionError(err) => {
eprint!("Couldn't run the test: {err}");
diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs
index 88049c4ca..f0ebb8e5a 100644
--- a/src/librustdoc/externalfiles.rs
+++ b/src/librustdoc/externalfiles.rs
@@ -37,8 +37,7 @@ impl ExternalHtml {
let bc = load_external_files(before_content, diag)?;
let m_bc = load_external_files(md_before_content, diag)?;
let bc = format!(
- "{}{}",
- bc,
+ "{bc}{}",
Markdown {
content: &m_bc,
links: &[],
@@ -53,8 +52,7 @@ impl ExternalHtml {
let ac = load_external_files(after_content, diag)?;
let m_ac = load_external_files(md_after_content, diag)?;
let ac = format!(
- "{}{}",
- ac,
+ "{ac}{}",
Markdown {
content: &m_ac,
links: &[],
@@ -83,7 +81,11 @@ pub(crate) fn load_string>(
let contents = match fs::read(file_path) {
Ok(bytes) => bytes,
Err(e) => {
- diag.struct_err(format!("error reading `{}`: {}", file_path.display(), e)).emit();
+ diag.struct_err(format!(
+ "error reading `{file_path}`: {e}",
+ file_path = file_path.display()
+ ))
+ .emit();
return Err(LoadStringError::ReadFail);
}
};
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index dac762e9f..d1deda0c7 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -86,6 +86,9 @@ pub(crate) struct Cache {
/// Whether to document private items.
/// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions.
pub(crate) document_private: bool,
+ /// Whether to document hidden items.
+ /// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions.
+ pub(crate) document_hidden: bool,
/// Crates marked with [`#[doc(masked)]`][doc_masked].
///
@@ -137,8 +140,8 @@ struct CacheBuilder<'a, 'tcx> {
}
impl Cache {
- pub(crate) fn new(document_private: bool) -> Self {
- Cache { document_private, ..Cache::default() }
+ pub(crate) fn new(document_private: bool, document_hidden: bool) -> Self {
+ Cache { document_private, document_hidden, ..Cache::default() }
}
/// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was
@@ -473,7 +476,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
| clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } => {
dids.insert(path.def_id());
if let Some(generics) = path.generics() &&
- let ty::Adt(adt, _) = self.tcx.type_of(path.def_id()).subst_identity().kind() &&
+ let ty::Adt(adt, _) = self.tcx.type_of(path.def_id()).instantiate_identity().kind() &&
adt.is_fundamental() {
for ty in generics {
if let Some(did) = ty.def_id(self.cache) {
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index 452e14918..a78893558 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -115,7 +115,7 @@ impl From for ItemType {
DefKind::Struct => Self::Struct,
DefKind::Union => Self::Union,
DefKind::Trait => Self::Trait,
- DefKind::TyAlias => Self::Typedef,
+ DefKind::TyAlias { .. } => Self::Typedef,
DefKind::TraitAlias => Self::TraitAlias,
DefKind::Macro(kind) => match kind {
MacroKind::Bang => ItemType::Macro,
@@ -136,7 +136,6 @@ impl From for ItemType {
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::OpaqueTy
- | DefKind::ImplTraitPlaceholder
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index 6f9cc0266..c49f1a4d3 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -77,8 +77,11 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
cx.mod_item_in(&item)?;
- let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) = *item.kind
- else { unreachable!() };
+ let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
+ *item.kind
+ else {
+ unreachable!()
+ };
for it in module.items {
debug!("Adding {:?} to worklist", it.name);
work.push((cx.make_child_renderer(), it));
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 54c0cd2ef..2f611c31a 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -18,7 +18,7 @@ use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_metadata::creader::{CStore, LoadedMacro};
use rustc_middle::ty;
use rustc_middle::ty::TyCtxt;
@@ -109,6 +109,10 @@ impl Buffer {
self.buffer
}
+ pub(crate) fn push(&mut self, c: char) {
+ self.buffer.push(c);
+ }
+
pub(crate) fn push_str(&mut self, s: &str) {
self.buffer.push_str(s);
}
@@ -228,9 +232,9 @@ impl clean::GenericParamDef {
if let Some(default) = default {
if f.alternate() {
- write!(f, " = {:#}", default)?;
+ write!(f, " = {default:#}")?;
} else {
- write!(f, " = {}", default)?;
+ write!(f, " = {default}")?;
}
}
@@ -451,9 +455,9 @@ impl clean::GenericBound {
hir::TraitBoundModifier::MaybeConst => "",
};
if f.alternate() {
- write!(f, "{}{:#}", modifier_str, ty.print(cx))
+ write!(f, "{modifier_str}{ty:#}", ty = ty.print(cx))
} else {
- write!(f, "{}{}", modifier_str, ty.print(cx))
+ write!(f, "{modifier_str}{ty}", ty = ty.print(cx))
}
}
})
@@ -599,12 +603,12 @@ fn generate_macro_def_id_path(
let cstore = CStore::from_tcx(tcx);
// We need this to prevent a `panic` when this function is used from intra doc links...
if !cstore.has_crate_data(def_id.krate) {
- debug!("No data for crate {}", crate_name);
+ debug!("No data for crate {crate_name}");
return Err(HrefError::NotInExternalCache);
}
// Check to see if it is a macro 2.0 or built-in macro.
// More information in .
- let is_macro_2 = match cstore.load_macro_untracked(def_id, tcx.sess) {
+ let is_macro_2 = match cstore.load_macro_untracked(def_id, tcx) {
LoadedMacro::MacroDef(def, _) => {
// If `ast_def.macro_rules` is `true`, then it's not a macro 2.0.
matches!(&def.kind, ast::ItemKind::MacroDef(ast_def) if !ast_def.macro_rules)
@@ -631,19 +635,18 @@ fn generate_macro_def_id_path(
let url = match cache.extern_locations[&def_id.krate] {
ExternalLocation::Remote(ref s) => {
// `ExternalLocation::Remote` always end with a `/`.
- format!("{}{}", s, path.iter().map(|p| p.as_str()).join("/"))
+ format!("{s}{path}", path = path.iter().map(|p| p.as_str()).join("/"))
}
ExternalLocation::Local => {
// `root_path` always end with a `/`.
format!(
- "{}{}/{}",
- root_path.unwrap_or(""),
- crate_name,
- path.iter().map(|p| p.as_str()).join("/")
+ "{root_path}{crate_name}/{path}",
+ root_path = root_path.unwrap_or(""),
+ path = path.iter().map(|p| p.as_str()).join("/")
)
}
ExternalLocation::Unknown => {
- debug!("crate {} not in cache when linkifying macros", crate_name);
+ debug!("crate {crate_name} not in cache when linkifying macros");
return Err(HrefError::NotInExternalCache);
}
};
@@ -662,6 +665,14 @@ pub(crate) fn href_with_root_path(
// documented on their parent's page
tcx.parent(did)
}
+ DefKind::ExternCrate => {
+ // Link to the crate itself, not the `extern crate` item.
+ if let Some(local_did) = did.as_local() {
+ tcx.extern_mod_stmt_cnum(local_did).unwrap_or(LOCAL_CRATE).as_def_id()
+ } else {
+ did
+ }
+ }
_ => did,
};
let cache = cx.cache();
@@ -724,7 +735,7 @@ pub(crate) fn href_with_root_path(
_ => {
let prefix = shortty.as_str();
let last = fqp.last().unwrap();
- url_parts.push_fmt(format_args!("{}.{}.html", prefix, last));
+ url_parts.push_fmt(format_args!("{prefix}.{last}.html"));
}
}
Ok((url_parts.finish(), shortty, fqp.to_vec()))
@@ -771,9 +782,10 @@ pub(crate) fn href_relative_parts<'fqp>(
pub(crate) fn link_tooltip(did: DefId, fragment: &Option, cx: &Context<'_>) -> String {
let cache = cx.cache();
- let Some((fqp, shortty)) = cache.paths.get(&did)
- .or_else(|| cache.external_paths.get(&did))
- else { return String::new() };
+ let Some((fqp, shortty)) = cache.paths.get(&did).or_else(|| cache.external_paths.get(&did))
+ else {
+ return String::new();
+ };
let mut buf = Buffer::new();
let fqp = if *shortty == ItemType::Primitive {
// primitives are documented in a crate, but not actually part of it
@@ -819,9 +831,9 @@ fn resolved_path<'cx>(
let path = if use_absolute {
if let Ok((_, _, fqp)) = href(did, cx) {
format!(
- "{}::{}",
- join_with_double_colon(&fqp[..fqp.len() - 1]),
- anchor(did, *fqp.last().unwrap(), cx)
+ "{path}::{anchor}",
+ path = join_with_double_colon(&fqp[..fqp.len() - 1]),
+ anchor = anchor(did, *fqp.last().unwrap(), cx)
)
} else {
last.name.to_string()
@@ -829,7 +841,7 @@ fn resolved_path<'cx>(
} else {
anchor(did, last.name, cx).to_string()
};
- write!(w, "{}{}", path, last.args.print(cx))?;
+ write!(w, "{path}{args}", args = last.args.print(cx))?;
}
Ok(())
}
@@ -897,7 +909,7 @@ fn primitive_link_fragment(
None => {}
}
}
- write!(f, "{}", name)?;
+ f.write_str(name)?;
if needs_termination {
write!(f, "")?;
}
@@ -937,15 +949,11 @@ pub(crate) fn anchor<'a, 'cx: 'a>(
if let Ok((url, short_ty, fqp)) = parts {
write!(
f,
- r#"{}"#,
- short_ty,
- url,
- short_ty,
- join_with_double_colon(&fqp),
- text.as_str()
+ r#"{text}"#,
+ path = join_with_double_colon(&fqp),
)
} else {
- write!(f, "{}", text)
+ f.write_str(text.as_str())
}
})
}
@@ -956,10 +964,10 @@ fn fmt_type<'cx>(
use_absolute: bool,
cx: &'cx Context<'_>,
) -> fmt::Result {
- trace!("fmt_type(t = {:?})", t);
+ trace!("fmt_type(t = {t:?})");
match *t {
- clean::Generic(name) => write!(f, "{}", name),
+ clean::Generic(name) => f.write_str(name.as_str()),
clean::Type::Path { ref path } => {
// Paths like `T::Output` and `Self::Output` should be rendered with all segments.
let did = path.def_id();
@@ -1076,13 +1084,13 @@ fn fmt_type<'cx>(
if matches!(**t, clean::Generic(_)) || t.is_assoc_ty() {
let text = if f.alternate() {
- format!("*{} {:#}", m, t.print(cx))
+ format!("*{m} {ty:#}", ty = t.print(cx))
} else {
- format!("*{} {}", m, t.print(cx))
+ format!("*{m} {ty}", ty = t.print(cx))
};
primitive_link(f, clean::PrimitiveType::RawPointer, &text, cx)
} else {
- primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m), cx)?;
+ primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{m} "), cx)?;
fmt::Display::fmt(&t.print(cx), f)
}
}
@@ -1093,22 +1101,35 @@ fn fmt_type<'cx>(
};
let m = mutability.print_with_space();
let amp = if f.alternate() { "&" } else { "&" };
- match **ty {
+
+ if let clean::Generic(name) = **ty {
+ return primitive_link(
+ f,
+ PrimitiveType::Reference,
+ &format!("{amp}{lt}{m}{name}"),
+ cx,
+ );
+ }
+
+ write!(f, "{amp}{lt}{m}")?;
+
+ let needs_parens = match **ty {
clean::DynTrait(ref bounds, ref trait_lt)
if bounds.len() > 1 || trait_lt.is_some() =>
{
- write!(f, "{}{}{}(", amp, lt, m)?;
- fmt_type(ty, f, use_absolute, cx)?;
- write!(f, ")")
- }
- clean::Generic(name) => {
- primitive_link(f, PrimitiveType::Reference, &format!("{amp}{lt}{m}{name}"), cx)
- }
- _ => {
- write!(f, "{}{}{}", amp, lt, m)?;
- fmt_type(ty, f, use_absolute, cx)
+ true
}
+ clean::ImplTrait(ref bounds) if bounds.len() > 1 => true,
+ _ => false,
+ };
+ if needs_parens {
+ f.write_str("(")?;
+ }
+ fmt_type(ty, f, use_absolute, cx)?;
+ if needs_parens {
+ f.write_str(")")?;
}
+ Ok(())
}
clean::ImplTrait(ref bounds) => {
if f.alternate() {
@@ -1423,11 +1444,20 @@ impl clean::FnDecl {
clean::SelfValue => {
write!(f, "self")?;
}
- clean::SelfBorrowed(Some(ref lt), mtbl) => {
- write!(f, "{}{} {}self", amp, lt.print(), mtbl.print_with_space())?;
+ clean::SelfBorrowed(Some(ref lt), mutability) => {
+ write!(
+ f,
+ "{amp}{lifetime} {mutability}self",
+ lifetime = lt.print(),
+ mutability = mutability.print_with_space(),
+ )?;
}
- clean::SelfBorrowed(None, mtbl) => {
- write!(f, "{}{}self", amp, mtbl.print_with_space())?;
+ clean::SelfBorrowed(None, mutability) => {
+ write!(
+ f,
+ "{amp}{mutability}self",
+ mutability = mutability.print_with_space(),
+ )?;
}
clean::SelfExplicit(ref typ) => {
write!(f, "self: ")?;
@@ -1501,7 +1531,7 @@ pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
"pub(super) ".into()
} else {
let path = cx.tcx().def_path(vis_did);
- debug!("path={:?}", path);
+ debug!("path={path:?}");
// modified from `resolved_path()` to work with `DefPathData`
let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
let anchor = anchor(vis_did, last_name, cx);
@@ -1510,12 +1540,12 @@ pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
for seg in &path.data[..path.data.len() - 1] {
let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap());
}
- let _ = write!(s, "{}) ", anchor);
+ let _ = write!(s, "{anchor}) ");
s.into()
}
}
};
- display_fn(move |f| write!(f, "{}", to_print))
+ display_fn(move |f| f.write_str(&to_print))
}
/// This function is the same as print_with_space, except that it renders no links.
@@ -1610,7 +1640,7 @@ impl clean::Import {
if name == self.source.path.last() {
write!(f, "use {};", self.source.print(cx))
} else {
- write!(f, "use {} as {};", self.source.print(cx), name)
+ write!(f, "use {source} as {name};", source = self.source.print(cx))
}
}
clean::ImportKind::Glob => {
@@ -1639,7 +1669,7 @@ impl clean::ImportSource {
if let hir::def::Res::PrimTy(p) = self.path.res {
primitive_link(f, PrimitiveType::from(p), name.as_str(), cx)?;
} else {
- write!(f, "{}", name)?;
+ f.write_str(name.as_str())?;
}
Ok(())
}
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index c94968b48..039e8cdb9 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -928,18 +928,16 @@ fn string_without_closing_tag(
href_context: &Option>,
open_tag: bool,
) -> Option<&'static str> {
- let Some(klass) = klass
- else {
- write!(out, "{}", text).unwrap();
+ let Some(klass) = klass else {
+ write!(out, "{text}").unwrap();
return None;
};
- let Some(def_span) = klass.get_span()
- else {
+ let Some(def_span) = klass.get_span() else {
if !open_tag {
- write!(out, "{}", text).unwrap();
+ write!(out, "{text}").unwrap();
return None;
}
- write!(out, "{}", klass.as_html(), text).unwrap();
+ write!(out, "{text}", klass = klass.as_html()).unwrap();
return Some("");
};
@@ -949,14 +947,17 @@ fn string_without_closing_tag(
match t {
"self" | "Self" => write!(
&mut path,
- "{}",
- Class::Self_(DUMMY_SP).as_html(),
- t
+ "{t}",
+ klass = Class::Self_(DUMMY_SP).as_html(),
),
"crate" | "super" => {
- write!(&mut path, "{}", Class::KeyWord.as_html(), t)
+ write!(
+ &mut path,
+ "{t}",
+ klass = Class::KeyWord.as_html(),
+ )
}
- t => write!(&mut path, "{}", t),
+ t => write!(&mut path, "{t}"),
}
.expect("Failed to build source HTML path");
path
@@ -988,19 +989,24 @@ fn string_without_closing_tag(
)
.ok()
.map(|(url, _, _)| url),
+ LinkFromSrc::Doc(def_id) => {
+ format::href_with_root_path(*def_id, context, Some(&href_context.root_path))
+ .ok()
+ .map(|(doc_link, _, _)| doc_link)
+ }
}
})
{
if !open_tag {
// We're already inside an element which has the same klass, no need to give it
// again.
- write!(out, "{}", href, text_s).unwrap();
+ write!(out, "{text_s}").unwrap();
} else {
let klass_s = klass.as_html();
if klass_s.is_empty() {
- write!(out, "{}", href, text_s).unwrap();
+ write!(out, "{text_s}").unwrap();
} else {
- write!(out, "{}", klass_s, href, text_s).unwrap();
+ write!(out, "{text_s}").unwrap();
}
}
return Some("");
@@ -1015,7 +1021,7 @@ fn string_without_closing_tag(
out.write_str(&text_s).unwrap();
Some("")
} else {
- write!(out, "{}", klass_s, text_s).unwrap();
+ write!(out, "{text_s}").unwrap();
Some("")
}
}
diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs
index 2c93b9a09..4c0874a68 100644
--- a/src/librustdoc/html/highlight/tests.rs
+++ b/src/librustdoc/html/highlight/tests.rs
@@ -23,7 +23,7 @@ fn test_html_highlighting() {
let html = {
let mut out = Buffer::new();
write_code(&mut out, src, None, None);
- format!("{}
{}
\n", STYLE, out.into_inner())
+ format!("{STYLE}
{}
\n", out.into_inner())
};
expect_file!["fixtures/sample.html"].assert_eq(&html);
});
diff --git a/src/librustdoc/html/length_limit.rs b/src/librustdoc/html/length_limit.rs
index 4c8db2c67..8562e103d 100644
--- a/src/librustdoc/html/length_limit.rs
+++ b/src/librustdoc/html/length_limit.rs
@@ -78,8 +78,7 @@ impl HtmlWithLimit {
pub(super) fn open_tag(&mut self, tag_name: &'static str) {
assert!(
tag_name.chars().all(|c| ('a'..='z').contains(&c)),
- "tag_name contained non-alphabetic chars: {:?}",
- tag_name
+ "tag_name contained non-alphabetic chars: {tag_name:?}",
);
self.queued_tags.push(tag_name);
}
@@ -88,7 +87,7 @@ impl HtmlWithLimit {
pub(super) fn close_tag(&mut self) {
match self.unclosed_tags.pop() {
// Close the most recently opened tag.
- Some(tag_name) => write!(self.buf, "{}>", tag_name).unwrap(),
+ Some(tag_name) => write!(self.buf, "{tag_name}>").unwrap(),
// There are valid cases where `close_tag()` is called without
// there being any tags to close. For example, this occurs when
// a tag is opened after the length limit is exceeded;
@@ -101,7 +100,7 @@ impl HtmlWithLimit {
/// Write all queued tags and add them to the `unclosed_tags` list.
fn flush_queue(&mut self) {
for tag_name in self.queued_tags.drain(..) {
- write!(self.buf, "<{}>", tag_name).unwrap();
+ write!(self.buf, "<{tag_name}>").unwrap();
self.unclosed_tags.push(tag_name);
}
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index fd00277e2..98cc38a10 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -50,7 +50,7 @@ use crate::html::render::small_url_encode;
use crate::html::toc::TocBuilder;
use pulldown_cmark::{
- html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
+ html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, Parser, Tag,
};
#[cfg(test)]
@@ -246,10 +246,9 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> {
return Some(Event::Html(
format!(
"
\
-
{}
\
+
{text}
\
",
- lang,
- Escape(&original_text),
+ text = Escape(&original_text),
)
.into(),
));
@@ -288,8 +287,9 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> {
let test_escaped = small_url_encode(test);
Some(format!(
- r#"Run"#,
- url, test_escaped, channel, edition,
+ "Run",
))
});
@@ -308,7 +308,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> {
// insert newline to clearly separate it from the
// previous block so we can shorten the html output
let mut s = Buffer::new();
- s.push_str("\n");
+ s.push('\n');
highlight::render_example_with_highlighting(
&text,
@@ -349,7 +349,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> {
dest,
title,
))) => {
- debug!("saw start of shortcut link to {} with title {}", dest, title);
+ debug!("saw start of shortcut link to {dest} with title {title}");
// If this is a shortcut link, it was resolved by the broken_link_callback.
// So the URL will already be updated properly.
let link = self.links.iter().find(|&link| *link.href == **dest);
@@ -370,7 +370,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> {
dest,
_,
))) => {
- debug!("saw end of shortcut link to {}", dest);
+ debug!("saw end of shortcut link to {dest}");
if self.links.iter().any(|link| *link.href == **dest) {
assert!(self.shortcut_link.is_some(), "saw closing link without opening tag");
self.shortcut_link = None;
@@ -379,7 +379,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> {
// Handle backticks in inline code blocks, but only if we're in the middle of a shortcut link.
// [`fn@f`]
Some(Event::Code(text)) => {
- trace!("saw code {}", text);
+ trace!("saw code {text}");
if let Some(link) = self.shortcut_link {
// NOTE: this only replaces if the code block is the *entire* text.
// If only part of the link has code highlighting, the disambiguator will not be removed.
@@ -394,7 +394,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> {
l.href == link.href
&& Some(&**text) == l.original_text.get(1..l.original_text.len() - 1)
}) {
- debug!("replacing {} with {}", text, link.new_text);
+ debug!("replacing {text} with {new_text}", new_text = link.new_text);
*text = CowStr::Borrowed(&link.new_text);
}
}
@@ -402,7 +402,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> {
// Replace plain text in links, but only in the middle of a shortcut link.
// [fn@f]
Some(Event::Text(text)) => {
- trace!("saw text {}", text);
+ trace!("saw text {text}");
if let Some(link) = self.shortcut_link {
// NOTE: same limitations as `Event::Code`
if let Some(link) = self
@@ -410,7 +410,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> {
.iter()
.find(|l| l.href == link.href && **text == *l.original_text)
{
- debug!("replacing {} with {}", text, link.new_text);
+ debug!("replacing {text} with {new_text}", new_text = link.new_text);
*text = CowStr::Borrowed(&link.new_text);
}
}
@@ -522,18 +522,16 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator
let mut html_header = String::new();
html::push_html(&mut html_header, self.buf.iter().map(|(ev, _)| ev.clone()));
let sec = builder.push(level as u32, html_header, id.clone());
- self.buf.push_front((Event::Html(format!("{} ", sec).into()), 0..0));
+ self.buf.push_front((Event::Html(format!("{sec} ").into()), 0..0));
}
let level =
std::cmp::min(level as u32 + (self.heading_offset as u32), MAX_HEADER_LEVEL);
- self.buf.push_back((Event::Html(format!("", level).into()), 0..0));
+ self.buf.push_back((Event::Html(format!("").into()), 0..0));
let start_tags = format!(
"\
",
- id = id,
- level = level
);
return Some((Event::Html(start_tags.into()), 0..0));
}
@@ -683,14 +681,14 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> {
v.sort_by(|a, b| a.1.cmp(&b.1));
let mut ret = String::from("