summaryrefslogtreecommitdiffstats
path: root/src/librustdoc/clean
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /src/librustdoc/clean
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz
rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/librustdoc/clean')
-rw-r--r--src/librustdoc/clean/auto_trait.rs20
-rw-r--r--src/librustdoc/clean/blanket_impl.rs35
-rw-r--r--src/librustdoc/clean/cfg.rs31
-rw-r--r--src/librustdoc/clean/inline.rs61
-rw-r--r--src/librustdoc/clean/mod.rs464
-rw-r--r--src/librustdoc/clean/render_macro_matchers.rs14
-rw-r--r--src/librustdoc/clean/simplify.rs39
-rw-r--r--src/librustdoc/clean/types.rs117
-rw-r--r--src/librustdoc/clean/types/tests.rs2
-rw-r--r--src/librustdoc/clean/utils.rs123
10 files changed, 588 insertions, 318 deletions
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<Item> {
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<Item> = auto_traits
.into_iter()
@@ -163,9 +163,9 @@ where
fn get_lifetime(region: Region<'_>, names_map: &FxHashMap<Symbol, Lifetime>) -> 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<T: Debug>(&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::<Vec<_>>(),
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, "<code>{}</code>", feat)?;
+ write!(fmt, "<code>{feat}</code>")?;
} 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, "<code>{}</code>", feat)?;
+ write!(fmt, "<code>{feat}</code>")?;
} 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 <code>{}</code>", feat);
+ return write!(fmt, "target feature <code>{feat}</code>");
}
- Format::LongPlain => return write!(fmt, "target feature `{}`", feat),
- Format::ShortHtml => return write!(fmt, "<code>{}</code>", feat),
+ Format::LongPlain => return write!(fmt, "target feature `{feat}`"),
+ Format::ShortHtml => return write!(fmt, "<code>{feat}</code>"),
},
(sym::feature, Some(feat)) => match self.1 {
Format::LongHtml => {
- return write!(fmt, "crate feature <code>{}</code>", feat);
+ return write!(fmt, "crate feature <code>{feat}</code>");
}
- Format::LongPlain => return write!(fmt, "crate feature `{}`", feat),
- Format::ShortHtml => return write!(fmt, "<code>{}</code>", feat),
+ Format::LongPlain => return write!(fmt, "crate feature `{feat}`"),
+ Format::ShortHtml => return write!(fmt, "<code>{feat}</code>"),
},
_ => "",
};
@@ -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, "<code>{}</code>", 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::<Vec<_>>(), 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<Vec<clean::Item>> {
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<clean::Function> {
- 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<clean::Typedef> {
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<DefId>)>,
) -> Vec<clean::Item> {
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<DefId>,
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<LocalDefId>,
renamed: Option<Symbol>,
) -> 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<Life
| ty::ReError(_)
| ty::RePlaceholder(..)
| ty::ReErased => {
- 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<WherePredicate> {
// `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::<Vec<_>>();
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(&param_idx.into())
+ && let Some(bounds) = impl_trait.get_mut(&param_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::<Vec<_>>();
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| &param.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| &param.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<Path> {
+ 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<Type> {
- 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::<Vec<_>>();
let ty = clean_middle_opaque_bounds(cx, bounds);
@@ -2110,7 +2251,6 @@ fn clean_middle_opaque_bounds<'tcx>(
cx: &mut DocContext<'tcx>,
bounds: Vec<ty::Clause<'tcx>>,
) -> 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::<Vec<_>>();
- 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<DefId>)> {
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<TokenTree> {
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<Item> {
+ 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<String
};
// Reparse a single token tree.
- let mut reparsed_trees = match parser.parse_all_token_trees() {
- Ok(reparsed_trees) => 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<WP>) -> ThinVec<WP
// Look for equality predicates on associated types that can be merged into
// general bound predicates.
equalities.retain(|(lhs, rhs, bound_params)| {
- let Some((ty, trait_did, name)) = lhs.projection() else { return true; };
+ let Some((ty, trait_did, name)) = lhs.projection() else {
+ return true;
+ };
let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
merge_bounds(cx, bounds, bound_params.clone(), trait_did, name, rhs)
});
@@ -136,3 +138,38 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, 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| &param.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| &param.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<Attributes>,
cfg: Option<Arc<Cfg>>,
) -> 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<RenderedLink> {
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<RenderedLink> {
- 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<Generics>, Type),
/// An associated constant in a trait impl or a provided one in a trait declaration.
- AssocConstItem(Type, ConstantKind),
+ AssocConstItem(Box<Generics>, 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<GenericBound>, bound_params: Vec<GenericParamDef> },
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
@@ -1345,7 +1348,7 @@ impl GenericParamDef {
}
// maybe use a Generic enum and use Vec<Generic>?
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
pub(crate) struct Generics {
pub(crate) params: ThinVec<GenericParamDef>,
pub(crate) where_predicates: ThinVec<WherePredicate>,
@@ -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<SimplifiedTypes> = 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<Box<Type>> },
}
+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<Generics>,
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<TypeBinding>,
- 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<TypeBinding>,
- 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<String> {
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<Item = Item> {
- // FIXME: To be removed once `parallel_compiler` bugs are fixed!
- // More information in <https://github.com/rust-lang/rust/pull/106930>.
- if cfg!(parallel_compiler) {
- return vec![].into_iter().chain(vec![].into_iter());
- }
-
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::<String>(),
+ "{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::<String>(),
)
} 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<LocalDefId>,
+) -> 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(..))
+}