summaryrefslogtreecommitdiffstats
path: root/src/librustdoc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
commit64d98f8ee037282c35007b64c2649055c56af1db (patch)
tree5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /src/librustdoc
parentAdding debian version 1.67.1+dfsg1-1. (diff)
downloadrustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz
rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/librustdoc')
-rw-r--r--src/librustdoc/clean/auto_trait.rs20
-rw-r--r--src/librustdoc/clean/blanket_impl.rs8
-rw-r--r--src/librustdoc/clean/cfg.rs2
-rw-r--r--src/librustdoc/clean/cfg/tests.rs20
-rw-r--r--src/librustdoc/clean/inline.rs41
-rw-r--r--src/librustdoc/clean/mod.rs272
-rw-r--r--src/librustdoc/clean/simplify.rs2
-rw-r--r--src/librustdoc/clean/types.rs80
-rw-r--r--src/librustdoc/clean/utils.rs33
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/doctest.rs11
-rw-r--r--src/librustdoc/fold.rs26
-rw-r--r--src/librustdoc/formats/cache.rs11
-rw-r--r--src/librustdoc/formats/item_type.rs3
-rw-r--r--src/librustdoc/formats/mod.rs6
-rw-r--r--src/librustdoc/html/format.rs31
-rw-r--r--src/librustdoc/html/highlight.rs46
-rw-r--r--src/librustdoc/html/markdown.rs43
-rw-r--r--src/librustdoc/html/markdown/tests.rs8
-rw-r--r--src/librustdoc/html/render/context.rs33
-rw-r--r--src/librustdoc/html/render/mod.rs35
-rw-r--r--src/librustdoc/html/render/print_item.rs91
-rw-r--r--src/librustdoc/html/render/search_index.rs92
-rw-r--r--src/librustdoc/html/render/write_shared.rs64
-rw-r--r--src/librustdoc/html/sources.rs62
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css376
-rw-r--r--src/librustdoc/html/static/css/settings.css37
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css63
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css49
-rw-r--r--src/librustdoc/html/static/css/themes/light.css49
-rw-r--r--src/librustdoc/html/static/js/main.js49
-rw-r--r--src/librustdoc/html/static/js/search.js130
-rw-r--r--src/librustdoc/html/static/js/settings.js6
-rw-r--r--src/librustdoc/html/static/js/source-script.js2
-rw-r--r--src/librustdoc/html/templates/page.html32
-rw-r--r--src/librustdoc/html/templates/print_item.html2
-rw-r--r--src/librustdoc/json/conversions.rs47
-rw-r--r--src/librustdoc/lib.rs8
-rw-r--r--src/librustdoc/markdown.rs2
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs5
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links/early.rs22
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs6
-rw-r--r--src/librustdoc/passes/lint/check_code_block_syntax.rs4
-rw-r--r--src/librustdoc/passes/strip_priv_imports.rs3
-rw-r--r--src/librustdoc/passes/strip_private.rs3
-rw-r--r--src/librustdoc/passes/stripper.rs31
-rw-r--r--src/librustdoc/visit.rs8
48 files changed, 1035 insertions, 943 deletions
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 953f4aa8a..a302750aa 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -44,7 +44,7 @@ where
discard_positive_impl: bool,
) -> Option<Item> {
let tcx = self.cx.tcx;
- let trait_ref = tcx.mk_trait_ref(trait_def_id, [ty]);
+ let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(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);
return None;
@@ -124,7 +124,7 @@ where
unsafety: hir::Unsafety::Normal,
generics: new_generics,
trait_: Some(clean_trait_ref_with_bindings(self.cx, trait_ref, ThinVec::new())),
- for_: clean_middle_ty(ty, self.cx, None),
+ for_: clean_middle_ty(ty::Binder::dummy(ty), self.cx, None),
items: Vec::new(),
polarity,
kind: ImplKind::Auto,
@@ -402,15 +402,13 @@ where
bound_params: Vec::new(),
})
})
- .chain(
- lifetime_to_bounds.into_iter().filter(|&(_, ref bounds)| !bounds.is_empty()).map(
- |(lifetime, bounds)| {
- let mut bounds_vec = bounds.into_iter().collect();
- self.sort_where_bounds(&mut bounds_vec);
- WherePredicate::RegionPredicate { lifetime, bounds: bounds_vec }
- },
- ),
- )
+ .chain(lifetime_to_bounds.into_iter().filter(|(_, bounds)| !bounds.is_empty()).map(
+ |(lifetime, bounds)| {
+ let mut bounds_vec = bounds.into_iter().collect();
+ self.sort_where_bounds(&mut bounds_vec);
+ WherePredicate::RegionPredicate { lifetime, bounds: bounds_vec }
+ },
+ ))
.collect()
}
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index a1145b90d..e6b2b2349 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -33,7 +33,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
trait_def_id,
impl_def_id
);
- let trait_ref = cx.tcx.bound_impl_trait_ref(impl_def_id).unwrap();
+ let trait_ref = cx.tcx.impl_trait_ref(impl_def_id).unwrap();
if !matches!(trait_ref.0.self_ty().kind(), ty::Param(_)) {
continue;
}
@@ -105,10 +105,10 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
// the post-inference `trait_ref`, as it's more accurate.
trait_: Some(clean_trait_ref_with_bindings(
cx,
- trait_ref.0,
+ ty::Binder::dummy(trait_ref.0),
ThinVec::new(),
)),
- for_: clean_middle_ty(ty.0, cx, None),
+ for_: clean_middle_ty(ty::Binder::dummy(ty.0), cx, None),
items: cx
.tcx
.associated_items(impl_def_id)
@@ -117,7 +117,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
.collect::<Vec<_>>(),
polarity: ty::ImplPolarity::Positive,
kind: ImplKind::Blanket(Box::new(clean_middle_ty(
- trait_ref.0.self_ty(),
+ ty::Binder::dummy(trait_ref.0.self_ty()),
cx,
None,
))),
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 1843a2120..f1853f369 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -507,7 +507,9 @@ impl<'a> fmt::Display for Display<'a> {
"openbsd" => "OpenBSD",
"redox" => "Redox",
"solaris" => "Solaris",
+ "tvos" => "tvOS",
"wasi" => "WASI",
+ "watchos" => "watchOS",
"windows" => "Windows",
_ => "",
},
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index 7f72d5d39..81f676724 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -1,9 +1,8 @@
use super::*;
-use rustc_ast::attr;
-use rustc_ast::Path;
+use rustc_ast::{LitKind, MetaItemLit, Path, StrStyle};
use rustc_span::create_default_session_globals_then;
-use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::DUMMY_SP;
fn word_cfg(s: &str) -> Cfg {
@@ -22,6 +21,15 @@ fn dummy_meta_item_word(name: &str) -> MetaItem {
}
}
+fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItem {
+ let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP };
+ MetaItem {
+ path: Path::from_ident(Ident::from_str(name)),
+ kind: MetaItemKind::NameValue(lit),
+ span: DUMMY_SP,
+ }
+}
+
macro_rules! dummy_meta_item_list {
($name:ident, [$($list:ident),* $(,)?]) => {
MetaItem {
@@ -242,8 +250,8 @@ fn test_parse_ok() {
let mi = dummy_meta_item_word("all");
assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
- let mi =
- attr::mk_name_value_item_str(Ident::from_str("all"), Symbol::intern("done"), DUMMY_SP);
+ let done = Symbol::intern("done");
+ let mi = dummy_meta_item_name_value("all", done, LitKind::Str(done, StrStyle::Cooked));
assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done")));
let mi = dummy_meta_item_list!(all, [a, b]);
@@ -272,7 +280,7 @@ fn test_parse_ok() {
#[test]
fn test_parse_err() {
create_default_session_globals_then(|| {
- let mi = attr::mk_name_value_item(Ident::from_str("foo"), LitKind::Bool(false), DUMMY_SP);
+ let mi = dummy_meta_item_name_value("foo", kw::False, LitKind::Bool(false));
assert!(Cfg::parse(&mi).is_err());
let mi = dummy_meta_item_list!(not, [a, b]);
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index e7c3e5a45..b3b093312 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -9,7 +9,7 @@ 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;
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::Mutability;
use rustc_metadata::creader::{CStore, LoadedMacro};
use rustc_middle::ty::{self, TyCtxt};
@@ -162,6 +162,7 @@ pub(crate) fn try_inline(
pub(crate) fn try_inline_glob(
cx: &mut DocContext<'_>,
res: Res,
+ current_mod: LocalDefId,
visited: &mut FxHashSet<DefId>,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
) -> Option<Vec<clean::Item>> {
@@ -172,7 +173,16 @@ pub(crate) fn try_inline_glob(
match res {
Res::Def(DefKind::Mod, did) => {
- let mut items = build_module_items(cx, did, visited, inlined_names);
+ // Use the set of module reexports to filter away names that are not actually
+ // reexported by the glob, e.g. because they are shadowed by something else.
+ let reexports = cx
+ .tcx
+ .module_reexports(current_mod)
+ .unwrap_or_default()
+ .iter()
+ .filter_map(|child| child.res.opt_def_id())
+ .collect();
+ let mut items = build_module_items(cx, did, visited, inlined_names, Some(&reexports));
items.drain_filter(|item| {
if let Some(name) = item.name {
// If an item with the same type and name already exists,
@@ -293,7 +303,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(cx.tcx.type_of(did), cx, Some(did));
+ let type_ = clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did));
Box::new(clean::Typedef {
type_,
@@ -325,7 +335,7 @@ 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::SimplifiedTypeGen::*;
+ use rustc_middle::ty::fast_reject::SimplifiedType::*;
let type_ =
if tcx.is_trait(did) { TraitSimplifiedType(did) } else { AdtSimplifiedType(did) };
for &did in tcx.incoherent_impls(type_) {
@@ -376,7 +386,7 @@ pub(crate) fn build_impl(
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_impl");
let tcx = cx.tcx;
- let associated_trait = tcx.impl_trait_ref(did);
+ let associated_trait = tcx.impl_trait_ref(did).map(ty::EarlyBinder::skip_binder);
// Only inline impl if the implemented trait is
// reachable in rustdoc generated documentation
@@ -405,7 +415,7 @@ pub(crate) fn build_impl(
let for_ = match &impl_item {
Some(impl_) => clean_ty(impl_.self_ty, cx),
- None => clean_middle_ty(tcx.type_of(did), cx, Some(did)),
+ None => clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)),
};
// Only inline impl if the implementing type is
@@ -496,7 +506,8 @@ pub(crate) fn build_impl(
),
};
let polarity = tcx.impl_polarity(did);
- let trait_ = associated_trait.map(|t| clean_trait_ref_with_bindings(cx, t, ThinVec::new()));
+ let trait_ = associated_trait
+ .map(|t| clean_trait_ref_with_bindings(cx, ty::Binder::dummy(t), ThinVec::new()));
if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
super::build_deref_target_impls(cx, &trait_items, ret);
}
@@ -562,7 +573,7 @@ fn build_module(
did: DefId,
visited: &mut FxHashSet<DefId>,
) -> clean::Module {
- let items = build_module_items(cx, did, visited, &mut FxHashSet::default());
+ let items = build_module_items(cx, did, visited, &mut FxHashSet::default(), None);
let span = clean::Span::new(cx.tcx.def_span(did));
clean::Module { items, span }
@@ -573,6 +584,7 @@ fn build_module_items(
did: DefId,
visited: &mut FxHashSet<DefId>,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
+ allowed_def_ids: Option<&FxHashSet<DefId>>,
) -> Vec<clean::Item> {
let mut items = Vec::new();
@@ -582,6 +594,11 @@ fn build_module_items(
for &item in cx.tcx.module_children(did).iter() {
if item.vis.is_public() {
let res = item.res.expect_non_local();
+ if let Some(def_id) = res.opt_def_id()
+ && let Some(allowed_def_ids) = allowed_def_ids
+ && !allowed_def_ids.contains(&def_id) {
+ continue;
+ }
if let Some(def_id) = res.mod_def_id() {
// If we're inlining a glob import, it's possible to have
// two distinct modules with the same name. We don't want to
@@ -599,7 +616,9 @@ fn build_module_items(
items.push(clean::Item {
name: None,
attrs: Box::new(clean::Attributes::default()),
- item_id: ItemId::Primitive(prim_ty, did.krate),
+ // We can use the item's `DefId` directly since the only information ever used
+ // from it is `DefId.krate`.
+ item_id: ItemId::DefId(did),
kind: Box::new(clean::ImportItem(clean::Import::new_simple(
item.ident.name,
clean::ImportSource {
@@ -640,14 +659,14 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
clean::Constant {
- type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+ type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
kind: clean::ConstantKind::Extern { def_id },
}
}
fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
clean::Static {
- type_: clean_middle_ty(cx.tcx.type_of(did), cx, Some(did)),
+ type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did)),
mutability: if mutable { Mutability::Mut } else { Mutability::Not },
expr: None,
}
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2a2a9470d..0f0e16265 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -22,6 +22,7 @@ use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::ty::fold::TypeFolder;
use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::TypeVisitable;
use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::hygiene::{AstPass, MacroKind};
@@ -127,7 +128,7 @@ fn clean_generic_bound<'tcx>(
hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
- let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
+ let trait_ref = ty::TraitRef::identity(cx.tcx, def_id);
let generic_args = clean_generic_args(generic_args, cx);
let GenericArgs::AngleBracketed { bindings, .. } = generic_args
@@ -156,17 +157,18 @@ fn clean_generic_bound<'tcx>(
pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
cx: &mut DocContext<'tcx>,
- trait_ref: ty::TraitRef<'tcx>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
bindings: ThinVec<TypeBinding>,
) -> Path {
- let kind = cx.tcx.def_kind(trait_ref.def_id).into();
+ 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.substs);
+ 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));
- debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
+ debug!(?trait_ref);
path
}
@@ -187,7 +189,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
})
.collect();
- let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref.skip_binder(), bindings);
+ let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings);
GenericBound::TraitBound(
PolyTrait { trait_, generic_params: late_bound_regions },
hir::TraitBoundModifier::None,
@@ -212,19 +214,19 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
Constant {
- type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+ type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
kind: ConstantKind::Anonymous { body: constant.value.body },
}
}
pub(crate) fn clean_middle_const<'tcx>(
- constant: ty::Const<'tcx>,
+ constant: ty::Binder<'tcx, ty::Const<'tcx>>,
cx: &mut DocContext<'tcx>,
) -> Constant {
// FIXME: instead of storing the stringified expression, store `self` directly instead.
Constant {
- type_: clean_middle_ty(constant.ty(), cx, None),
- kind: ConstantKind::TyConst { expr: constant.to_string().into() },
+ type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None),
+ kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() },
}
}
@@ -333,7 +335,7 @@ fn clean_poly_trait_predicate<'tcx>(
let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref);
Some(WherePredicate::BoundPredicate {
- ty: clean_middle_ty(poly_trait_ref.skip_binder().self_ty(), cx, None),
+ ty: clean_middle_ty(poly_trait_ref.self_ty(), cx, None),
bounds: vec![clean_poly_trait_ref_with_bindings(cx, poly_trait_ref, ThinVec::new())],
bound_params: Vec::new(),
})
@@ -359,7 +361,7 @@ fn clean_type_outlives_predicate<'tcx>(
let ty::OutlivesPredicate(ty, lt) = pred;
Some(WherePredicate::BoundPredicate {
- ty: clean_middle_ty(ty, cx, None),
+ ty: clean_middle_ty(ty::Binder::dummy(ty), cx, None),
bounds: vec![GenericBound::Outlives(
clean_middle_region(lt).expect("failed to clean lifetimes"),
)],
@@ -367,10 +369,13 @@ fn clean_type_outlives_predicate<'tcx>(
})
}
-fn clean_middle_term<'tcx>(term: ty::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
- match term.unpack() {
- ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)),
- ty::TermKind::Const(c) => Term::Constant(clean_middle_const(c, cx)),
+fn clean_middle_term<'tcx>(
+ term: ty::Binder<'tcx, ty::Term<'tcx>>,
+ cx: &mut DocContext<'tcx>,
+) -> Term {
+ match term.skip_binder().unpack() {
+ ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(term.rebind(ty), cx, None)),
+ ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c), cx)),
}
}
@@ -379,7 +384,10 @@ fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Te
hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
hir::Term::Const(c) => {
let def_id = cx.tcx.hir().local_def_id(c.hir_id);
- Term::Constant(clean_middle_const(ty::Const::from_anon_const(cx.tcx, def_id), cx))
+ Term::Constant(clean_middle_const(
+ ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, def_id)),
+ cx,
+ ))
}
}
}
@@ -398,32 +406,31 @@ fn clean_projection_predicate<'tcx>(
})
.collect();
- let ty::ProjectionPredicate { projection_ty, term } = pred.skip_binder();
-
WherePredicate::EqPredicate {
- lhs: Box::new(clean_projection(projection_ty, cx, None)),
- rhs: Box::new(clean_middle_term(term, cx)),
+ lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)),
+ rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)),
bound_params: late_bound_regions,
}
}
fn clean_projection<'tcx>(
- ty: ty::ProjectionTy<'tcx>,
+ ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
cx: &mut DocContext<'tcx>,
def_id: Option<DefId>,
) -> Type {
- if cx.tcx.def_kind(ty.item_def_id) == DefKind::ImplTraitPlaceholder {
+ if cx.tcx.def_kind(ty.skip_binder().def_id) == DefKind::ImplTraitPlaceholder {
let bounds = cx
.tcx
- .explicit_item_bounds(ty.item_def_id)
+ .explicit_item_bounds(ty.skip_binder().def_id)
.iter()
- .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.substs))
+ .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.skip_binder().substs))
.collect::<Vec<_>>();
return clean_middle_opaque_bounds(cx, bounds);
}
- let trait_ = clean_trait_ref_with_bindings(cx, ty.trait_ref(cx.tcx), ThinVec::new());
- let self_type = clean_middle_ty(ty.self_ty(), cx, None);
+ let trait_ =
+ clean_trait_ref_with_bindings(cx, ty.map_bound(|ty| ty.trait_ref(cx.tcx)), ThinVec::new());
+ let self_type = clean_middle_ty(ty.map_bound(|ty| ty.self_ty()), cx, None);
let self_def_id = if let Some(def_id) = def_id {
cx.tcx.opt_parent(def_id).or(Some(def_id))
} else {
@@ -446,15 +453,16 @@ fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type
}
fn projection_to_path_segment<'tcx>(
- ty: ty::ProjectionTy<'tcx>,
+ ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
cx: &mut DocContext<'tcx>,
) -> PathSegment {
- let item = cx.tcx.associated_item(ty.item_def_id);
- let generics = cx.tcx.generics_of(ty.item_def_id);
+ let item = cx.tcx.associated_item(ty.skip_binder().def_id);
+ let generics = cx.tcx.generics_of(ty.skip_binder().def_id);
PathSegment {
name: item.name,
args: GenericArgs::AngleBracketed {
- args: substs_to_args(cx, &ty.substs[generics.parent_count..], false).into(),
+ args: substs_to_args(cx, ty.map_bound(|ty| &ty.substs[generics.parent_count..]), false)
+ .into(),
bindings: Default::default(),
},
}
@@ -470,7 +478,11 @@ fn clean_generic_param_def<'tcx>(
}
ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
let default = if has_default {
- Some(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id)))
+ Some(clean_middle_ty(
+ ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+ cx,
+ Some(def.def_id),
+ ))
} else {
None
};
@@ -488,9 +500,15 @@ fn clean_generic_param_def<'tcx>(
def.name,
GenericParamDefKind::Const {
did: def.def_id,
- ty: Box::new(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id))),
+ ty: Box::new(clean_middle_ty(
+ ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+ cx,
+ Some(def.def_id),
+ )),
default: match has_default {
- true => Some(Box::new(cx.tcx.const_param_default(def.def_id).to_string())),
+ true => Some(Box::new(
+ cx.tcx.const_param_default(def.def_id).subst_identity().to_string(),
+ )),
false => None,
},
},
@@ -733,8 +751,10 @@ fn clean_ty_generics<'tcx>(
.collect::<ThinVec<GenericParamDef>>();
// param index -> [(trait DefId, associated type name & generics, type, higher-ranked params)]
- let mut impl_trait_proj =
- FxHashMap::<u32, Vec<(DefId, PathSegment, Ty<'_>, Vec<GenericParamDef>)>>::default();
+ let mut impl_trait_proj = FxHashMap::<
+ u32,
+ Vec<(DefId, PathSegment, ty::Binder<'_, Ty<'_>>, Vec<GenericParamDef>)>,
+ >::default();
let where_predicates = preds
.predicates
@@ -783,8 +803,8 @@ fn clean_ty_generics<'tcx>(
let proj = projection.map(|p| {
(
- clean_projection(p.skip_binder().projection_ty, cx, None),
- p.skip_binder().term,
+ 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
@@ -795,7 +815,7 @@ fn clean_ty_generics<'tcx>(
impl_trait_proj.entry(param_idx).or_default().push((
trait_did,
name,
- rhs.ty().unwrap(),
+ rhs.map_bound(|rhs| rhs.ty().unwrap()),
p.get_bound_params()
.into_iter()
.flatten()
@@ -1066,7 +1086,7 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
// We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
// but shouldn't change any code meaning.
- let output = match clean_middle_ty(sig.skip_binder().output(), cx, None) {
+ let output = match clean_middle_ty(sig.output(), cx, None) {
Type::Tuple(inner) if inner.is_empty() => DefaultReturn,
ty => Return(ty),
};
@@ -1076,11 +1096,10 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
c_variadic: sig.skip_binder().c_variadic,
inputs: Arguments {
values: sig
- .skip_binder()
.inputs()
.iter()
.map(|t| Argument {
- type_: clean_middle_ty(*t, cx, None),
+ type_: clean_middle_ty(t.map_bound(|t| *t), cx, None),
name: names
.next()
.map(|i| i.name)
@@ -1134,7 +1153,8 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
hir::TraitItemKind::Type(bounds, Some(default)) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
- let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, default), cx, None);
+ let item_type =
+ clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, default)), cx, None);
AssocTypeItem(
Box::new(Typedef {
type_: clean_ty(default, cx),
@@ -1173,7 +1193,8 @@ pub(crate) fn clean_impl_item<'tcx>(
hir::ImplItemKind::Type(hir_ty) => {
let type_ = clean_ty(hir_ty, cx);
let generics = clean_generics(impl_.generics, cx);
- let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+ let item_type =
+ clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
AssocTypeItem(
Box::new(Typedef { type_, generics, item_type: Some(item_type) }),
Vec::new(),
@@ -1192,7 +1213,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
let tcx = cx.tcx;
let kind = match assoc_item.kind {
ty::AssocKind::Const => {
- let ty = clean_middle_ty(tcx.type_of(assoc_item.def_id), cx, Some(assoc_item.def_id));
+ let ty = clean_middle_ty(
+ ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+ cx,
+ Some(assoc_item.def_id),
+ );
let provided = match assoc_item.container {
ty::ImplContainer => true,
@@ -1375,7 +1400,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
AssocTypeItem(
Box::new(Typedef {
type_: clean_middle_ty(
- tcx.type_of(assoc_item.def_id),
+ ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
cx,
Some(assoc_item.def_id),
),
@@ -1393,7 +1418,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
AssocTypeItem(
Box::new(Typedef {
type_: clean_middle_ty(
- tcx.type_of(assoc_item.def_id),
+ ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
cx,
Some(assoc_item.def_id),
),
@@ -1437,8 +1462,11 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
hir::QPath::Resolved(Some(qself), p) => {
// Try to normalize `<X as Y>::T` to a type
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
- if let Some(normalized_value) = normalize(cx, ty) {
- return clean_middle_ty(normalized_value, cx, None);
+ // `hir_to_ty` can return projection types with escaping vars for GATs, e.g. `<() as Trait>::Gat<'_>`
+ if !ty.has_escaping_bound_vars() {
+ if let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty)) {
+ return clean_middle_ty(normalized_value, cx, None);
+ }
}
let trait_segments = &p.segments[..p.segments.len() - 1];
@@ -1461,11 +1489,13 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
hir::QPath::TypeRelative(qself, segment) => {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
let res = match ty.kind() {
- ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id),
+ ty::Alias(ty::Projection, proj) => {
+ Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id)
+ }
// Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
ty::Error(_) => return Type::Infer,
// Otherwise, this is an inherent associated type.
- _ => return clean_middle_ty(ty, cx, None),
+ _ => return clean_middle_ty(ty::Binder::dummy(ty), cx, None),
};
let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx);
register_res(cx, trait_.res);
@@ -1584,7 +1614,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
match ty.kind {
TyKind::Never => Primitive(PrimitiveType::Never),
TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(clean_ty(m.ty, cx))),
- TyKind::Rptr(ref l, ref m) => {
+ TyKind::Ref(ref l, ref m) => {
let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(*l, cx)) };
BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) }
}
@@ -1632,7 +1662,10 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
}
/// Returns `None` if the type could not be normalized
-fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+fn normalize<'tcx>(
+ cx: &mut DocContext<'tcx>,
+ ty: ty::Binder<'tcx, Ty<'tcx>>,
+) -> Option<ty::Binder<'tcx, Ty<'tcx>>> {
// HACK: low-churn fix for #79459 while we wait for a trait normalization fix
if !cx.tcx.sess.opts.unstable_opts.normalize_docs {
return None;
@@ -1660,14 +1693,14 @@ fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>>
}
}
+#[instrument(level = "trace", skip(cx), ret)]
pub(crate) fn clean_middle_ty<'tcx>(
- ty: Ty<'tcx>,
+ bound_ty: ty::Binder<'tcx, Ty<'tcx>>,
cx: &mut DocContext<'tcx>,
def_id: Option<DefId>,
) -> Type {
- trace!("cleaning type: {:?}", ty);
- let ty = normalize(cx, ty).unwrap_or(ty);
- match *ty.kind() {
+ let bound_ty = normalize(cx, bound_ty).unwrap_or(bound_ty);
+ match *bound_ty.skip_binder().kind() {
ty::Never => Primitive(PrimitiveType::Never),
ty::Bool => Primitive(PrimitiveType::Bool),
ty::Char => Primitive(PrimitiveType::Char),
@@ -1675,20 +1708,23 @@ pub(crate) fn clean_middle_ty<'tcx>(
ty::Uint(uint_ty) => Primitive(uint_ty.into()),
ty::Float(float_ty) => Primitive(float_ty.into()),
ty::Str => Primitive(PrimitiveType::Str),
- ty::Slice(ty) => Slice(Box::new(clean_middle_ty(ty, cx, None))),
+ ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None))),
ty::Array(ty, mut n) => {
n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
let n = print_const(cx, n);
- Array(Box::new(clean_middle_ty(ty, cx, None)), n.into())
+ Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)), n.into())
+ }
+ ty::RawPtr(mt) => {
+ RawPointer(mt.mutbl, Box::new(clean_middle_ty(bound_ty.rebind(mt.ty), cx, None)))
}
- ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))),
ty::Ref(r, ty, mutbl) => BorrowedRef {
lifetime: clean_middle_region(r),
mutability: mutbl,
- type_: Box::new(clean_middle_ty(ty, cx, None)),
+ type_: Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)),
},
ty::FnDef(..) | ty::FnPtr(_) => {
- let sig = ty.fn_sig(cx.tcx);
+ // FIXME: should we merge the outer and inner binders somehow?
+ let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
BareFunction(Box::new(BareFunctionDecl {
unsafety: sig.unsafety(),
@@ -1705,12 +1741,18 @@ 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(), substs);
+ let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(substs));
Type::Path { path }
}
ty::Foreign(did) => {
inline::record_extern_fqn(cx, did, ItemType::ForeignType);
- let path = external_path(cx, did, false, ThinVec::new(), InternalSubsts::empty());
+ let path = external_path(
+ cx,
+ did,
+ false,
+ ThinVec::new(),
+ ty::Binder::dummy(InternalSubsts::empty()),
+ );
Type::Path { path }
}
ty::Dynamic(obj, ref reg, _) => {
@@ -1721,11 +1763,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
let did = obj
.principal_def_id()
.or_else(|| dids.next())
- .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", ty));
+ .unwrap_or_else(|| panic!("found trait object `{bound_ty:?}` with no traits?"));
let substs = match obj.principal() {
- Some(principal) => principal.skip_binder().substs,
+ Some(principal) => principal.map_bound(|p| p.substs),
// marker traits have no substs.
- _ => cx.tcx.intern_substs(&[]),
+ _ => ty::Binder::dummy(InternalSubsts::empty()),
};
inline::record_extern_fqn(cx, did, ItemType::Trait);
@@ -1736,7 +1778,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
let lifetime = clean_middle_region(*reg);
let mut bounds = dids
.map(|did| {
- let empty = cx.tcx.intern_substs(&[]);
+ let empty = ty::Binder::dummy(InternalSubsts::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() }
@@ -1747,15 +1789,17 @@ pub(crate) fn clean_middle_ty<'tcx>(
.projection_bounds()
.map(|pb| TypeBinding {
assoc: projection_to_path_segment(
- pb.skip_binder()
- // HACK(compiler-errors): Doesn't actually matter what self
- // type we put here, because we're only using the GAT's substs.
- .with_self_ty(cx.tcx, cx.tcx.types.self_param)
- .projection_ty,
+ 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.
+ .with_self_ty(cx.tcx, cx.tcx.types.self_param)
+ .projection_ty
+ }),
cx,
),
kind: TypeBindingKind::Equality {
- term: clean_middle_term(pb.skip_binder().term, cx),
+ term: clean_middle_term(pb.map_bound(|pb| pb.term), cx),
},
})
.collect();
@@ -1779,9 +1823,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
DynTrait(bounds, lifetime)
}
- ty::Tuple(t) => Tuple(t.iter().map(|t| clean_middle_ty(t, cx, None)).collect()),
+ ty::Tuple(t) => {
+ Tuple(t.iter().map(|t| clean_middle_ty(bound_ty.rebind(t), cx, None)).collect())
+ }
- ty::Projection(ref data) => clean_projection(*data, cx, def_id),
+ ty::Alias(ty::Projection, ref data) => clean_projection(bound_ty.rebind(*data), cx, def_id),
ty::Param(ref p) => {
if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
@@ -1791,7 +1837,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
}
}
- ty::Opaque(def_id, substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the bounds associated with the def_id.
let bounds = cx
@@ -1809,7 +1855,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
ty::Placeholder(..) => panic!("Placeholder"),
ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
ty::Infer(..) => panic!("Infer"),
- ty::Error(_) => panic!("Error"),
+ ty::Error(_) => rustc_errors::FatalError.raise(),
}
}
@@ -1854,9 +1900,12 @@ fn clean_middle_opaque_bounds<'tcx>(
{
if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
Some(TypeBinding {
- assoc: projection_to_path_segment(proj.projection_ty, cx),
+ assoc: projection_to_path_segment(
+ bound.kind().rebind(proj.projection_ty),
+ cx,
+ ),
kind: TypeBindingKind::Equality {
- term: clean_middle_term(proj.term, cx),
+ term: clean_middle_term(bound.kind().rebind(proj.term), cx),
},
})
} else {
@@ -1887,7 +1936,7 @@ pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext
clean_field_with_def_id(
field.did,
field.name,
- clean_middle_ty(cx.tcx.type_of(field.did), cx, Some(field.did)),
+ clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(field.did)), cx, Some(field.did)),
cx,
)
}
@@ -1902,20 +1951,27 @@ pub(crate) fn clean_field_with_def_id(
}
pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item {
+ let discriminant = match variant.discr {
+ ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
+ ty::VariantDiscr::Relative(_) => None,
+ };
+
let kind = match variant.ctor_kind() {
- Some(CtorKind::Const) => Variant::CLike(match variant.discr {
- ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
- ty::VariantDiscr::Relative(_) => None,
- }),
- Some(CtorKind::Fn) => Variant::Tuple(
+ Some(CtorKind::Const) => VariantKind::CLike,
+ Some(CtorKind::Fn) => VariantKind::Tuple(
variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
),
- None => Variant::Struct(VariantStruct {
- ctor_kind: None,
+ None => VariantKind::Struct(VariantStruct {
fields: variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
}),
};
- Item::from_def_id_and_parts(variant.def_id, Some(variant.name), VariantItem(kind), cx)
+
+ Item::from_def_id_and_parts(
+ variant.def_id,
+ Some(variant.name),
+ VariantItem(Variant { kind, discriminant }),
+ cx,
+ )
}
fn clean_variant_data<'tcx>(
@@ -1923,19 +1979,22 @@ fn clean_variant_data<'tcx>(
disr_expr: &Option<hir::AnonConst>,
cx: &mut DocContext<'tcx>,
) -> Variant {
- match variant {
- hir::VariantData::Struct(..) => Variant::Struct(VariantStruct {
- ctor_kind: None,
+ let discriminant = disr_expr.map(|disr| Discriminant {
+ expr: Some(disr.body),
+ value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(),
+ });
+
+ let kind = match variant {
+ hir::VariantData::Struct(..) => VariantKind::Struct(VariantStruct {
fields: variant.fields().iter().map(|x| clean_field(x, cx)).collect(),
}),
hir::VariantData::Tuple(..) => {
- Variant::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect())
+ VariantKind::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect())
}
- hir::VariantData::Unit(..) => Variant::CLike(disr_expr.map(|disr| Discriminant {
- expr: Some(disr.body),
- value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(),
- })),
- }
+ hir::VariantData::Unit(..) => VariantKind::CLike,
+ };
+
+ Variant { discriminant, kind }
}
fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
@@ -2052,10 +2111,12 @@ fn get_all_import_attributes<'hir>(
) {
let hir_map = tcx.hir();
let mut visitor = OneLevelVisitor::new(hir_map, target_hir_id);
+ let mut visited = FxHashSet::default();
// If the item is an import and has at least a path with two parts, we go into it.
while let hir::ItemKind::Use(path, _) = item.kind &&
path.segments.len() > 1 &&
- let hir::def::Res::Def(_, def_id) = path.segments[path.segments.len() - 2].res
+ let hir::def::Res::Def(_, def_id) = path.segments[path.segments.len() - 2].res &&
+ visited.insert(def_id)
{
if let Some(hir::Node::Item(parent_item)) = hir_map.get_if_local(def_id) {
// We add the attributes from this import into the list.
@@ -2100,7 +2161,7 @@ fn clean_maybe_renamed_item<'tcx>(
}),
ItemKind::TyAlias(hir_ty, generics) => {
let rustdoc_ty = clean_ty(hir_ty, cx);
- let ty = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+ let ty = clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
TypedefItem(Box::new(Typedef {
type_: rustdoc_ty,
generics: clean_generics(generics, cx),
@@ -2211,7 +2272,9 @@ fn clean_impl<'tcx>(
let for_ = clean_ty(impl_.self_ty, cx);
let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) {
- DefKind::TyAlias => Some(clean_middle_ty(tcx.type_of(did), cx, Some(did))),
+ DefKind::TyAlias => {
+ Some(clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)))
+ }
_ => None,
});
let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
@@ -2380,7 +2443,8 @@ fn clean_use_statement_inner<'tcx>(
let inner = if kind == hir::UseKind::Glob {
if !denied {
let mut visited = FxHashSet::default();
- if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited, inlined_names)
+ if let Some(items) =
+ inline::try_inline_glob(cx, path.res, current_mod, &mut visited, inlined_names)
{
return items;
}
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index e96a9bab7..dbbc25739 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -46,7 +46,7 @@ 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(|&(ref lhs, ref rhs, ref bound_params)| {
+ equalities.retain(|(lhs, rhs, bound_params)| {
let Some((ty, trait_did, name)) = lhs.projection() else { return true; };
let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
let bound_params = bound_params
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 2590bb0df..87de41fde 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -10,7 +10,6 @@ use std::{cmp, fmt, iter};
use arrayvec::ArrayVec;
use thin_vec::ThinVec;
-use rustc_ast::attr;
use rustc_ast::util::comments::beautify_doc_string;
use rustc_ast::{self as ast, AttrStyle};
use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
@@ -27,7 +26,6 @@ use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::{self, DefIdTree, TyCtxt, Visibility};
use rustc_session::Session;
use rustc_span::hygiene::MacroKind;
-use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{self, FileName, Loc};
use rustc_target::abi::VariantIdx;
@@ -64,8 +62,6 @@ pub(crate) enum ItemId {
Auto { trait_: DefId, for_: DefId },
/// Identifier that is used for blanket implementations.
Blanket { impl_id: DefId, for_: DefId },
- /// Identifier for primitive types.
- Primitive(PrimitiveType, CrateNum),
}
impl ItemId {
@@ -75,7 +71,6 @@ impl ItemId {
ItemId::Auto { for_: id, .. }
| ItemId::Blanket { for_: id, .. }
| ItemId::DefId(id) => id.is_local(),
- ItemId::Primitive(_, krate) => krate == LOCAL_CRATE,
}
}
@@ -100,7 +95,6 @@ impl ItemId {
ItemId::Auto { for_: id, .. }
| ItemId::Blanket { for_: id, .. }
| ItemId::DefId(id) => id.krate,
- ItemId::Primitive(_, krate) => krate,
}
}
}
@@ -682,7 +676,8 @@ impl Item {
}
let header = match *self.kind {
ItemKind::ForeignFunctionItem(_) => {
- let abi = tcx.fn_sig(self.item_id.as_def_id().unwrap()).abi();
+ let def_id = self.item_id.as_def_id().unwrap();
+ let abi = tcx.fn_sig(def_id).abi();
hir::FnHeader {
unsafety: if abi == Abi::RustIntrinsic {
intrinsic_operation_unsafety(tcx, self.item_id.as_def_id().unwrap())
@@ -690,7 +685,14 @@ impl Item {
hir::Unsafety::Unsafe
},
abi,
- constness: hir::Constness::NotConst,
+ constness: if abi == Abi::RustIntrinsic
+ && tcx.is_const_fn(def_id)
+ && is_unstable_const_fn(tcx, def_id).is_none()
+ {
+ hir::Constness::Const
+ } else {
+ hir::Constness::NotConst
+ },
asyncness: hir::IsAsync::NotAsync,
}
}
@@ -709,15 +711,13 @@ impl Item {
let def_id = match self.item_id {
// Anything but DefId *shouldn't* matter, but return a reasonable value anyway.
ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
- // Primitives and Keywords are written in the source code as private modules.
- // The modules need to be private so that nobody actually uses them, but the
- // keywords and primitives that they are documenting are public.
- ItemId::Primitive(..) => return Some(Visibility::Public),
ItemId::DefId(def_id) => def_id,
};
match *self.kind {
- // Explication on `ItemId::Primitive` just above.
+ // Primitives and Keywords are written in the source code as private modules.
+ // The modules need to be private so that nobody actually uses them, but the
+ // keywords and primitives that they are documenting are public.
ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Some(Visibility::Public),
// Variant fields inherit their enum's visibility.
StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
@@ -809,8 +809,11 @@ impl ItemKind {
match self {
StructItem(s) => s.fields.iter(),
UnionItem(u) => u.fields.iter(),
- VariantItem(Variant::Struct(v)) => v.fields.iter(),
- VariantItem(Variant::Tuple(v)) => v.iter(),
+ VariantItem(v) => match &v.kind {
+ VariantKind::CLike => [].iter(),
+ VariantKind::Tuple(t) => t.iter(),
+ VariantKind::Struct(s) => s.fields.iter(),
+ },
EnumItem(e) => e.variants.iter(),
TraitItem(t) => t.items.iter(),
ImplItem(i) => i.items.iter(),
@@ -826,7 +829,6 @@ impl ItemKind {
| TyMethodItem(_)
| MethodItem(_, _)
| StructFieldItem(_)
- | VariantItem(_)
| ForeignFunctionItem(_)
| ForeignStaticItem(_)
| ForeignTypeItem
@@ -982,12 +984,12 @@ impl AttributesExt for [ast::Attribute] {
// #[doc(cfg(target_feature = "feat"))] attributes as well
for attr in self.lists(sym::target_feature) {
if attr.has_name(sym::enable) {
- if let Some(feat) = attr.value_str() {
- let meta = attr::mk_name_value_item_str(
- Ident::with_dummy_span(sym::target_feature),
- feat,
- DUMMY_SP,
- );
+ if attr.value_str().is_some() {
+ // Clone `enable = "feat"`, change to `target_feature = "feat"`.
+ // Unwrap is safe because `value_str` succeeded above.
+ let mut meta = attr.meta_item().unwrap().clone();
+ meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
+
if let Ok(feat_cfg) = Cfg::parse(&meta) {
cfg &= feat_cfg;
}
@@ -1345,7 +1347,7 @@ pub(crate) enum GenericBound {
impl GenericBound {
pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
let did = cx.tcx.require_lang_item(LangItem::Sized, None);
- let empty = cx.tcx.intern_substs(&[]);
+ let empty = ty::Binder::dummy(ty::InternalSubsts::empty());
let path = external_path(cx, did, false, ThinVec::new(), empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
GenericBound::TraitBound(
@@ -1742,7 +1744,7 @@ impl Type {
fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
let t: PrimitiveType = match *self {
Type::Path { ref path } => return Some(path.def_id()),
- DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()),
+ DynTrait(ref bounds, _) => return bounds.get(0).map(|b| b.trait_.def_id()),
Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
@@ -1872,7 +1874,7 @@ impl PrimitiveType {
}
pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
- use ty::fast_reject::SimplifiedTypeGen::*;
+ use ty::fast_reject::SimplifiedType::*;
use ty::{FloatTy, IntTy, UintTy};
use PrimitiveType::*;
static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
@@ -2111,7 +2113,6 @@ impl Union {
/// only as a variant in an enum.
#[derive(Clone, Debug)]
pub(crate) struct VariantStruct {
- pub(crate) ctor_kind: Option<CtorKind>,
pub(crate) fields: Vec<Item>,
}
@@ -2138,17 +2139,23 @@ impl Enum {
}
#[derive(Clone, Debug)]
-pub(crate) enum Variant {
- CLike(Option<Discriminant>),
+pub(crate) struct Variant {
+ pub kind: VariantKind,
+ pub discriminant: Option<Discriminant>,
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum VariantKind {
+ CLike,
Tuple(Vec<Item>),
Struct(VariantStruct),
}
impl Variant {
pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
- match *self {
- Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()),
- Self::CLike(..) | Self::Tuple(_) => None,
+ match &self.kind {
+ VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
+ VariantKind::CLike | VariantKind::Tuple(_) => None,
}
}
}
@@ -2489,6 +2496,17 @@ impl Import {
pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
Self { kind: ImportKind::Glob, source, should_be_displayed }
}
+
+ pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
+ match self.source.did {
+ Some(did) => tcx
+ .get_attrs(did, sym::doc)
+ .filter_map(ast::Attribute::meta_item_list)
+ .flatten()
+ .has_word(sym::hidden),
+ None => false,
+ }
+ }
}
#[derive(Clone, Debug)]
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 246560bad..a12f764fa 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -78,12 +78,16 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
pub(crate) fn substs_to_args<'tcx>(
cx: &mut DocContext<'tcx>,
- substs: &[ty::subst::GenericArg<'tcx>],
+ substs: ty::Binder<'tcx, &[ty::subst::GenericArg<'tcx>]>,
mut skip_first: bool,
) -> Vec<GenericArg> {
let mut ret_val =
- Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 }));
- ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() {
+ Vec::with_capacity(substs.skip_binder().len().saturating_sub(if skip_first {
+ 1
+ } else {
+ 0
+ }));
+ ret_val.extend(substs.iter().filter_map(|kind| match kind.skip_binder().unpack() {
GenericArgKind::Lifetime(lt) => {
Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
}
@@ -91,8 +95,12 @@ pub(crate) fn substs_to_args<'tcx>(
skip_first = false;
None
}
- GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty(ty, cx, None))),
- GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(clean_middle_const(ct, cx)))),
+ GenericArgKind::Type(ty) => {
+ Some(GenericArg::Type(clean_middle_ty(kind.rebind(ty), cx, None)))
+ }
+ GenericArgKind::Const(ct) => {
+ Some(GenericArg::Const(Box::new(clean_middle_const(kind.rebind(ct), cx))))
+ }
}));
ret_val
}
@@ -102,15 +110,20 @@ fn external_generic_args<'tcx>(
did: DefId,
has_self: bool,
bindings: ThinVec<TypeBinding>,
- substs: SubstsRef<'tcx>,
+ substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
) -> GenericArgs {
- let args = substs_to_args(cx, substs, has_self);
+ let args = substs_to_args(cx, substs.map_bound(|substs| &substs[..]), has_self);
if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
+ let ty = substs
+ .iter()
+ .nth(if has_self { 1 } else { 0 })
+ .unwrap()
+ .map_bound(|arg| arg.expect_ty());
let inputs =
// The trait's first substitution is the one after self, if there is one.
- match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() {
- ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(t, cx, None)).collect::<Vec<_>>().into(),
+ match ty.skip_binder().kind() {
+ ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None)).collect::<Vec<_>>().into(),
_ => return GenericArgs::AngleBracketed { args: args.into(), bindings },
};
let output = bindings.into_iter().next().and_then(|binding| match binding.kind {
@@ -130,7 +143,7 @@ pub(super) fn external_path<'tcx>(
did: DefId,
has_self: bool,
bindings: ThinVec<TypeBinding>,
- substs: SubstsRef<'tcx>,
+ substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
) -> Path {
let def_kind = cx.tcx.def_kind(did);
let name = cx.tcx.item_name(did);
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index da0df596c..2153e7d8c 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -225,7 +225,6 @@ pub(crate) fn create_config(
// Add the doc cfg into the doc build.
cfgs.push("doc".to_string());
- let cpath = Some(input.clone());
let input = Input::File(input);
// By default, rustdoc ignores all lints.
@@ -277,7 +276,6 @@ pub(crate) fn create_config(
crate_cfg: interface::parse_cfgspecs(cfgs),
crate_check_cfg: interface::parse_check_cfg(check_cfgs),
input,
- input_path: cpath,
output_file: None,
output_dir: None,
file_loader: None,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 81d9c4644..c1a652c75 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -95,7 +95,6 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
crate_cfg: interface::parse_cfgspecs(cfgs),
crate_check_cfg: interface::parse_check_cfg(options.check_cfgs.clone()),
input,
- input_path: None,
output_file: None,
output_dir: None,
file_loader: None,
@@ -115,9 +114,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
let (tests, unused_extern_reports, compiling_test_count) =
interface::run_compiler(config, |compiler| {
compiler.enter(|queries| {
- let mut global_ctxt = queries.global_ctxt()?.take();
-
- let collector = global_ctxt.enter(|tcx| {
+ let collector = queries.global_ctxt()?.enter(|tcx| {
let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
let opts = scrape_test_config(crate_attrs);
@@ -156,9 +153,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
let unused_extern_reports = collector.unused_extern_reports.clone();
let compiling_test_count = collector.compiling_test_count.load(Ordering::SeqCst);
- let ret: Result<_, ErrorGuaranteed> =
- Ok((collector.tests, unused_extern_reports, compiling_test_count));
- ret
+ Ok((collector.tests, unused_extern_reports, compiling_test_count))
})
})?;
@@ -1225,7 +1220,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
) {
let ast_attrs = self.tcx.hir().attrs(hir_id);
if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
- if !cfg.matches(&self.sess.parse_sess, Some(self.sess.features_untracked())) {
+ if !cfg.matches(&self.sess.parse_sess, Some(self.tcx.features())) {
return;
}
}
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index c6f1f9de5..656aeefb0 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -37,17 +37,21 @@ pub(crate) trait DocFolder: Sized {
i.items = i.items.into_iter().filter_map(|x| self.fold_item(x)).collect();
ImplItem(i)
}
- VariantItem(i) => match i {
- Variant::Struct(mut j) => {
- j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
- VariantItem(Variant::Struct(j))
- }
- Variant::Tuple(fields) => {
- let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
- VariantItem(Variant::Tuple(fields))
- }
- Variant::CLike(disr) => VariantItem(Variant::CLike(disr)),
- },
+ VariantItem(Variant { kind, discriminant }) => {
+ let kind = match kind {
+ VariantKind::Struct(mut j) => {
+ j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
+ VariantKind::Struct(j)
+ }
+ VariantKind::Tuple(fields) => {
+ let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
+ VariantKind::Tuple(fields)
+ }
+ VariantKind::CLike => VariantKind::CLike,
+ };
+
+ VariantItem(Variant { kind, discriminant })
+ }
ExternCrateItem { src: _ }
| ImportItem(_)
| FunctionItem(_)
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index d027fb6e8..1c78c5b8d 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -242,7 +242,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
}
// Index this method for searching later on.
- if let Some(ref s) = item.name.or_else(|| {
+ if let Some(s) = item.name.or_else(|| {
if item.is_stripped() {
None
} else if let clean::ImportItem(ref i) = *item.kind &&
@@ -296,7 +296,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
// for where the type was defined. On the other
// hand, `paths` always has the right
// information if present.
- Some(&(ref fqp, _)) => Some(&fqp[..fqp.len() - 1]),
+ Some((fqp, _)) => Some(&fqp[..fqp.len() - 1]),
None => None,
};
((did, path), true)
@@ -317,14 +317,15 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
short_markdown_summary(x.as_str(), &item.link_names(self.cache))
});
let ty = item.type_();
- let name = s.to_string();
- if ty != ItemType::StructField || u16::from_str_radix(&name, 10).is_err() {
+ if ty != ItemType::StructField
+ || u16::from_str_radix(s.as_str(), 10).is_err()
+ {
// In case this is a field from a tuple struct, we don't add it into
// the search index because its name is something like "0", which is
// not useful for rustdoc search.
self.cache.search_index.push(IndexItem {
ty,
- name,
+ name: s,
path: join_with_double_colon(path),
desc,
parent,
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index f21e60a64..2f1f4cbf3 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -177,6 +177,9 @@ impl ItemType {
ItemType::TraitAlias => "traitalias",
}
}
+ pub(crate) fn is_method(&self) -> bool {
+ matches!(*self, ItemType::Method | ItemType::TyMethod)
+ }
}
impl fmt::Display for ItemType {
diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs
index b236bd7be..e607a16ad 100644
--- a/src/librustdoc/formats/mod.rs
+++ b/src/librustdoc/formats/mod.rs
@@ -53,12 +53,6 @@ impl Impl {
ItemId::Blanket { impl_id, .. } => impl_id,
ItemId::Auto { trait_, .. } => trait_,
ItemId::DefId(def_id) => def_id,
- ItemId::Primitive(_, _) => {
- panic!(
- "Unexpected ItemId::Primitive in expect_def_id: {:?}",
- self.impl_item.item_id
- )
- }
}
}
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 39e2a9022..d3dc4065d 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -569,7 +569,7 @@ fn generate_macro_def_id_path(
root_path: Option<&str>,
) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
let tcx = cx.shared.tcx;
- let crate_name = tcx.crate_name(def_id.krate).to_string();
+ let crate_name = tcx.crate_name(def_id.krate);
let cache = cx.cache();
let fqp: Vec<Symbol> = tcx
@@ -584,7 +584,7 @@ fn generate_macro_def_id_path(
}
})
.collect();
- let mut relative = fqp.iter().map(|elem| elem.to_string());
+ let mut relative = fqp.iter().copied();
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) {
@@ -602,9 +602,9 @@ fn generate_macro_def_id_path(
};
let mut path = if is_macro_2 {
- once(crate_name.clone()).chain(relative).collect()
+ once(crate_name).chain(relative).collect()
} else {
- vec![crate_name.clone(), relative.next_back().unwrap()]
+ vec![crate_name, relative.next_back().unwrap()]
};
if path.len() < 2 {
// The minimum we can have is the crate name followed by the macro name. If shorter, then
@@ -614,17 +614,22 @@ fn generate_macro_def_id_path(
}
if let Some(last) = path.last_mut() {
- *last = format!("macro.{}.html", last);
+ *last = Symbol::intern(&format!("macro.{}.html", last.as_str()));
}
let url = match cache.extern_locations[&def_id.krate] {
ExternalLocation::Remote(ref s) => {
// `ExternalLocation::Remote` always end with a `/`.
- format!("{}{}", s, path.join("/"))
+ format!("{}{}", s, path.iter().map(|p| p.as_str()).join("/"))
}
ExternalLocation::Local => {
// `root_path` always end with a `/`.
- format!("{}{}/{}", root_path.unwrap_or(""), crate_name, path.join("/"))
+ format!(
+ "{}{}/{}",
+ root_path.unwrap_or(""),
+ crate_name,
+ path.iter().map(|p| p.as_str()).join("/")
+ )
}
ExternalLocation::Unknown => {
debug!("crate {} not in cache when linkifying macros", crate_name);
@@ -957,7 +962,7 @@ fn fmt_type<'cx>(
clean::Tuple(ref typs) => {
match &typs[..] {
&[] => primitive_link(f, PrimitiveType::Unit, "()", cx),
- &[ref one] => {
+ [one] => {
if let clean::Generic(name) = one {
primitive_link(f, PrimitiveType::Tuple, &format!("({name},)"), cx)
} else {
@@ -1050,7 +1055,7 @@ fn fmt_type<'cx>(
_ => String::new(),
};
let m = mutability.print_with_space();
- let amp = if f.alternate() { "&".to_string() } else { "&amp;".to_string() };
+ let amp = if f.alternate() { "&" } else { "&amp;" };
match **ty {
clean::DynTrait(ref bounds, ref trait_lt)
if bounds.len() > 1 || trait_lt.is_some() =>
@@ -1655,10 +1660,10 @@ impl clean::types::Term {
&'a self,
cx: &'a Context<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
- match self {
- clean::types::Term::Type(ty) => ty.print(cx),
- _ => todo!(),
- }
+ display_fn(move |f| match self {
+ clean::types::Term::Type(ty) => fmt::Display::fmt(&ty.print(cx), f),
+ clean::types::Term::Constant(ct) => fmt::Display::fmt(&ct.print(cx.tcx()), f),
+ })
}
}
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index cd8c8c463..8a9e6caf6 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -21,15 +21,15 @@ use rustc_span::{BytePos, Span, DUMMY_SP};
use super::format::{self, Buffer};
/// This type is needed in case we want to render links on items to allow to go to their definition.
-pub(crate) struct HrefContext<'a, 'b, 'c> {
- pub(crate) context: &'a Context<'b>,
+pub(crate) struct HrefContext<'a, 'tcx> {
+ pub(crate) context: &'a Context<'tcx>,
/// This span contains the current file we're going through.
pub(crate) file_span: Span,
/// This field is used to know "how far" from the top of the directory we are to link to either
/// documentation pages or other source pages.
- pub(crate) root_path: &'c str,
+ pub(crate) root_path: &'a str,
/// This field is used to calculate precise local URLs.
- pub(crate) current_href: &'c str,
+ pub(crate) current_href: String,
}
/// Decorations are represented as a map from CSS class to vector of character ranges.
@@ -70,7 +70,7 @@ pub(crate) fn render_source_with_highlighting(
src: &str,
out: &mut Buffer,
line_numbers: Buffer,
- href_context: HrefContext<'_, '_, '_>,
+ href_context: HrefContext<'_, '_>,
decoration_info: DecorationInfo,
extra: Option<&str>,
) {
@@ -137,7 +137,7 @@ fn can_merge(class1: Option<Class>, class2: Option<Class>, text: &str) -> bool {
/// This type is used as a conveniency to prevent having to pass all its fields as arguments into
/// the various functions (which became its methods).
-struct TokenHandler<'a, 'b, 'c, 'd, 'e> {
+struct TokenHandler<'a, 'tcx> {
out: &'a mut Buffer,
/// It contains the closing tag and the associated `Class`.
closing_tags: Vec<(&'static str, Class)>,
@@ -149,11 +149,11 @@ struct TokenHandler<'a, 'b, 'c, 'd, 'e> {
current_class: Option<Class>,
/// We need to keep the `Class` for each element because it could contain a `Span` which is
/// used to generate links.
- pending_elems: Vec<(&'b str, Option<Class>)>,
- href_context: Option<HrefContext<'c, 'd, 'e>>,
+ pending_elems: Vec<(&'a str, Option<Class>)>,
+ href_context: Option<HrefContext<'a, 'tcx>>,
}
-impl<'a, 'b, 'c, 'd, 'e> TokenHandler<'a, 'b, 'c, 'd, 'e> {
+impl<'a, 'tcx> TokenHandler<'a, 'tcx> {
fn handle_exit_span(&mut self) {
// We can't get the last `closing_tags` element using `pop()` because `closing_tags` is
// being used in `write_pending_elems`.
@@ -205,7 +205,7 @@ impl<'a, 'b, 'c, 'd, 'e> TokenHandler<'a, 'b, 'c, 'd, 'e> {
}
}
-impl<'a, 'b, 'c, 'd, 'e> Drop for TokenHandler<'a, 'b, 'c, 'd, 'e> {
+impl<'a, 'tcx> Drop for TokenHandler<'a, 'tcx> {
/// When leaving, we need to flush all pending data to not have missing content.
fn drop(&mut self) {
if self.pending_exit_span.is_some() {
@@ -230,7 +230,7 @@ impl<'a, 'b, 'c, 'd, 'e> Drop for TokenHandler<'a, 'b, 'c, 'd, 'e> {
fn write_code(
out: &mut Buffer,
src: &str,
- href_context: Option<HrefContext<'_, '_, '_>>,
+ href_context: Option<HrefContext<'_, '_>>,
decoration_info: Option<DecorationInfo>,
) {
// This replace allows to fix how the code source with DOS backline characters is displayed.
@@ -514,18 +514,18 @@ impl Decorations {
/// Processes program tokens, classifying strings of text by highlighting
/// category (`Class`).
-struct Classifier<'a> {
- tokens: PeekIter<'a>,
+struct Classifier<'src> {
+ tokens: PeekIter<'src>,
in_attribute: bool,
in_macro: bool,
in_macro_nonterminal: bool,
byte_pos: u32,
file_span: Span,
- src: &'a str,
+ src: &'src str,
decorations: Option<Decorations>,
}
-impl<'a> Classifier<'a> {
+impl<'src> Classifier<'src> {
/// Takes as argument the source code to HTML-ify, the rust edition to use and the source code
/// file span which will be used later on by the `span_correspondance_map`.
fn new(src: &str, file_span: Span, decoration_info: Option<DecorationInfo>) -> Classifier<'_> {
@@ -603,7 +603,7 @@ impl<'a> Classifier<'a> {
///
/// It returns the token's kind, the token as a string and its byte position in the source
/// string.
- fn next(&mut self) -> Option<(TokenKind, &'a str, u32)> {
+ fn next(&mut self) -> Option<(TokenKind, &'src str, u32)> {
if let Some((kind, text)) = self.tokens.next() {
let before = self.byte_pos;
self.byte_pos += text.len() as u32;
@@ -618,7 +618,7 @@ impl<'a> Classifier<'a> {
/// The general structure for this method is to iterate over each token,
/// possibly giving it an HTML span with a class specifying what flavor of
/// token is used.
- fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'a>)) {
+ fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'src>)) {
loop {
if let Some(decs) = self.decorations.as_mut() {
let byte_pos = self.byte_pos;
@@ -666,8 +666,8 @@ impl<'a> Classifier<'a> {
fn advance(
&mut self,
token: TokenKind,
- text: &'a str,
- sink: &mut dyn FnMut(Highlight<'a>),
+ text: &'src str,
+ sink: &mut dyn FnMut(Highlight<'src>),
before: u32,
) {
let lookahead = self.peek();
@@ -881,7 +881,7 @@ impl<'a> Classifier<'a> {
fn enter_span(
out: &mut Buffer,
klass: Class,
- href_context: &Option<HrefContext<'_, '_, '_>>,
+ href_context: &Option<HrefContext<'_, '_>>,
) -> &'static str {
string_without_closing_tag(out, "", Some(klass), href_context, true).expect(
"internal error: enter_span was called with Some(klass) but did not return a \
@@ -914,7 +914,7 @@ fn string<T: Display>(
out: &mut Buffer,
text: T,
klass: Option<Class>,
- href_context: &Option<HrefContext<'_, '_, '_>>,
+ href_context: &Option<HrefContext<'_, '_>>,
open_tag: bool,
) {
if let Some(closing_tag) = string_without_closing_tag(out, text, klass, href_context, open_tag)
@@ -936,7 +936,7 @@ fn string_without_closing_tag<T: Display>(
out: &mut Buffer,
text: T,
klass: Option<Class>,
- href_context: &Option<HrefContext<'_, '_, '_>>,
+ href_context: &Option<HrefContext<'_, '_>>,
open_tag: bool,
) -> Option<&'static str> {
let Some(klass) = klass
@@ -985,7 +985,7 @@ fn string_without_closing_tag<T: Display>(
// https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338
match href {
LinkFromSrc::Local(span) => {
- context.href_from_span_relative(*span, href_context.current_href)
+ context.href_from_span_relative(*span, &href_context.current_href)
}
LinkFromSrc::External(def_id) => {
format::href_with_root_path(*def_id, context, Some(href_context.root_path))
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 1e1c657b0..4ff67fe15 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -30,7 +30,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::HirId;
use rustc_middle::ty::TyCtxt;
use rustc_span::edition::Edition;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
use once_cell::sync::Lazy;
use std::borrow::Cow;
@@ -198,7 +198,7 @@ fn slugify(c: char) -> Option<char> {
#[derive(Clone, Debug)]
pub struct Playground {
- pub crate_name: Option<String>,
+ pub crate_name: Option<Symbol>,
pub url: String,
}
@@ -236,12 +236,12 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
return event;
};
- let mut origtext = String::new();
+ let mut original_text = String::new();
for event in &mut self.inner {
match event {
Event::End(Tag::CodeBlock(..)) => break,
Event::Text(ref s) => {
- origtext.push_str(s);
+ original_text.push_str(s);
}
_ => {}
}
@@ -258,7 +258,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
<pre class=\"language-{}\"><code>{}</code></pre>\
</div>",
lang,
- Escape(&origtext),
+ Escape(&original_text),
)
.into(),
));
@@ -268,7 +268,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
CodeBlockKind::Indented => Default::default(),
};
- let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
+ let lines = original_text.lines().filter_map(|l| map_line(l).for_html());
let text = lines.intersperse("\n".into()).collect::<String>();
compile_fail = parse_result.compile_fail;
@@ -285,12 +285,12 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
if url.is_empty() {
return None;
}
- let test = origtext
+ let test = original_text
.lines()
.map(|l| map_line(l).for_code())
.intersperse("\n".into())
.collect::<String>();
- let krate = krate.as_ref().map(|s| &**s);
+ let krate = krate.as_ref().map(|s| s.as_str());
let (test, _, _) =
doctest::make_test(&test, krate, false, &Default::default(), edition, None);
let channel = if test.contains("#![feature(") { "&amp;version=nightly" } else { "" };
@@ -567,11 +567,12 @@ struct SummaryLine<'a, I: Iterator<Item = Event<'a>>> {
inner: I,
started: bool,
depth: u32,
+ skipped_tags: u32,
}
impl<'a, I: Iterator<Item = Event<'a>>> SummaryLine<'a, I> {
fn new(iter: I) -> Self {
- SummaryLine { inner: iter, started: false, depth: 0 }
+ SummaryLine { inner: iter, started: false, depth: 0, skipped_tags: 0 }
}
}
@@ -601,6 +602,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for SummaryLine<'a, I> {
let is_allowed_tag = match event {
Event::Start(ref c) => {
if is_forbidden_tag(c) {
+ self.skipped_tags += 1;
return None;
}
self.depth += 1;
@@ -608,6 +610,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for SummaryLine<'a, I> {
}
Event::End(ref c) => {
if is_forbidden_tag(c) {
+ self.skipped_tags += 1;
return None;
}
self.depth -= 1;
@@ -616,6 +619,9 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for SummaryLine<'a, I> {
}
_ => true,
};
+ if !is_allowed_tag {
+ self.skipped_tags += 1;
+ }
return if !is_allowed_tag {
if is_start {
Some(Event::Start(Tag::Paragraph))
@@ -1096,11 +1102,11 @@ impl MarkdownItemInfo<'_> {
}
impl MarkdownSummaryLine<'_> {
- pub(crate) fn into_string(self) -> String {
+ pub(crate) fn into_string_with_has_more_content(self) -> (String, bool) {
let MarkdownSummaryLine(md, links) = self;
// This is actually common enough to special-case
if md.is_empty() {
- return String::new();
+ return (String::new(), false);
}
let mut replacer = |broken_link: BrokenLink<'_>| {
@@ -1110,17 +1116,26 @@ impl MarkdownSummaryLine<'_> {
.map(|link| (link.href.as_str().into(), link.new_text.as_str().into()))
};
- let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
+ let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer))
+ .peekable();
+ let mut summary = SummaryLine::new(p);
let mut s = String::new();
- let without_paragraphs = LinkReplacer::new(SummaryLine::new(p), links).filter(|event| {
+ let without_paragraphs = LinkReplacer::new(&mut summary, links).filter(|event| {
!matches!(event, Event::Start(Tag::Paragraph) | Event::End(Tag::Paragraph))
});
html::push_html(&mut s, without_paragraphs);
- s
+ let has_more_content =
+ matches!(summary.inner.peek(), Some(Event::Start(_))) || summary.skipped_tags > 0;
+
+ (s, has_more_content)
+ }
+
+ pub(crate) fn into_string(self) -> String {
+ self.into_string_with_has_more_content().0
}
}
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index 68b31a6ee..5878c5826 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -345,4 +345,12 @@ fn test_ascii_with_prepending_hashtag() {
#..#.####.####.####..##..
</code></pre></div>",
);
+ t(
+ r#"```markdown
+# hello
+```"#,
+ "<div class=\"example-wrap\"><pre class=\"language-markdown\"><code>\
+# hello
+</code></pre></div>",
+ );
}
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 73690c86f..5cefe9475 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -309,7 +309,7 @@ impl<'tcx> Context<'tcx> {
pub(crate) fn href_from_span(&self, span: clean::Span, with_lines: bool) -> Option<String> {
let mut root = self.root_path();
- let mut path = String::new();
+ let mut path: String;
let cnum = span.cnum(self.sess());
// We can safely ignore synthetic `SourceFile`s.
@@ -340,10 +340,24 @@ impl<'tcx> Context<'tcx> {
ExternalLocation::Unknown => return None,
};
- sources::clean_path(&src_root, file, false, |component| {
- path.push_str(&component.to_string_lossy());
+ let href = RefCell::new(PathBuf::new());
+ sources::clean_path(
+ &src_root,
+ file,
+ |component| {
+ href.borrow_mut().push(component);
+ },
+ || {
+ href.borrow_mut().pop();
+ },
+ );
+
+ path = href.into_inner().to_string_lossy().to_string();
+
+ if let Some(c) = path.as_bytes().last() && *c != b'/' {
path.push('/');
- });
+ }
+
let mut fname = file.file_name().expect("source has no filename").to_os_string();
fname.push(".html");
path.push_str(&fname.to_string_lossy());
@@ -450,8 +464,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
// If user passed in `--playground-url` arg, we fill in crate name here
let mut playground = None;
if let Some(url) = playground_url {
- playground =
- Some(markdown::Playground { crate_name: Some(krate.name(tcx).to_string()), url });
+ playground = Some(markdown::Playground { crate_name: Some(krate.name(tcx)), url });
}
let mut layout = layout::Layout {
logo: String::new(),
@@ -477,7 +490,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
}
(sym::html_playground_url, Some(s)) => {
playground = Some(markdown::Playground {
- crate_name: Some(krate.name(tcx).to_string()),
+ crate_name: Some(krate.name(tcx)),
url: s.to_string(),
});
}
@@ -625,7 +638,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
write!(
buf,
"<div class=\"main-heading\">\
- <h1 class=\"fqn\">Rustdoc settings</h1>\
+ <h1>Rustdoc settings</h1>\
<span class=\"out-of-band\">\
<a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
Back\
@@ -637,7 +650,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
You need to enable Javascript be able to update your settings.\
</section>\
</noscript>\
- <link rel=\"stylesheet\" type=\"text/css\" \
+ <link rel=\"stylesheet\" \
href=\"{static_root_path}{settings_css}\">\
<script defer src=\"{static_root_path}{settings_js}\"></script>",
static_root_path = page.get_static_root_path(),
@@ -663,7 +676,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
write!(
buf,
"<div class=\"main-heading\">\
- <h1 class=\"fqn\">Rustdoc help</h1>\
+ <h1>Rustdoc help</h1>\
<span class=\"out-of-band\">\
<a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
Back\
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 36d15ec3b..4fa33e890 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -100,7 +100,7 @@ pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ {
#[derive(Debug)]
pub(crate) struct IndexItem {
pub(crate) ty: ItemType,
- pub(crate) name: String,
+ pub(crate) name: Symbol,
pub(crate) path: String,
pub(crate) desc: String,
pub(crate) parent: Option<DefId>,
@@ -364,7 +364,7 @@ impl AllTypes {
}
}
- f.write_str("<h1 class=\"fqn\">List of all items</h1>");
+ f.write_str("<h1>List of all items</h1>");
// Note: print_entries does not escape the title, because we know the current set of titles
// doesn't require escaping.
print_entries(f, &self.structs, ItemSection::Structs);
@@ -394,7 +394,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
let mut ids = IdMap::default();
format!(
"<div class=\"main-heading\">\
- <h1 class=\"fqn\">About scraped examples</h1>\
+ <h1>About scraped examples</h1>\
</div>\
<div>{}</div>",
Markdown {
@@ -467,9 +467,10 @@ fn document_short(
return;
}
if let Some(s) = item.doc_value() {
- let mut summary_html = MarkdownSummaryLine(&s, &item.links(cx)).into_string();
+ let (mut summary_html, has_more_content) =
+ MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content();
- if s.contains('\n') {
+ if has_more_content {
let link = format!(r#" <a{}>Read more</a>"#, assoc_href_attr(item, link, cx));
if let Some(idx) = summary_html.rfind("</p>") {
@@ -512,7 +513,7 @@ fn document_full_inner(
debug!("Doc block: =====\n{}\n=====", s);
if is_collapsible {
w.write_str(
- "<details class=\"rustdoc-toggle top-doc\" open>\
+ "<details class=\"toggle top-doc\" open>\
<summary class=\"hideme\">\
<span>Expand description</span>\
</summary>",
@@ -1342,7 +1343,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
write!(
&mut out,
"<h3>Notable traits for <code>{}</code></h3>\
- <pre class=\"content\"><code>",
+ <pre><code>",
impl_.for_.print(cx)
);
}
@@ -1512,9 +1513,8 @@ fn render_impl(
let toggled = !doc_buffer.is_empty();
if toggled {
- let method_toggle_class =
- if item_type == ItemType::Method { " method-toggle" } else { "" };
- write!(w, "<details class=\"rustdoc-toggle{}\" open><summary>", method_toggle_class);
+ let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
+ write!(w, "<details class=\"toggle{}\" open><summary>", method_toggle_class);
}
match &*item.kind {
clean::MethodItem(..) | clean::TyMethodItem(_) => {
@@ -1730,7 +1730,7 @@ fn render_impl(
close_tags.insert_str(0, "</details>");
write!(
w,
- "<details class=\"rustdoc-toggle implementors-toggle\"{}>",
+ "<details class=\"toggle implementors-toggle\"{}>",
if rendering_params.toggle_open_by_default { " open" } else { "" }
);
write!(w, "<summary>")
@@ -2769,8 +2769,8 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
let mut work = VecDeque::new();
let mut process_path = |did: DefId| {
- let get_extern = || cache.external_paths.get(&did).map(|s| s.0.clone());
- let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern);
+ let get_extern = || cache.external_paths.get(&did).map(|s| &s.0);
+ let fqp = cache.exact_paths.get(&did).or_else(get_extern);
if let Some(path) = fqp {
out.push(join_with_double_colon(&path));
@@ -2921,7 +2921,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
// Look for the example file in the source map if it exists, otherwise return a dummy span
let file_span = (|| {
let source_map = tcx.sess.source_map();
- let crate_src = tcx.sess.local_crate_source_file.as_ref()?;
+ let crate_src = tcx.sess.local_crate_source_file()?;
let abs_crate_src = crate_src.canonicalize().ok()?;
let crate_root = abs_crate_src.parent()?.parent()?;
let rel_path = path.strip_prefix(crate_root).ok()?;
@@ -2999,14 +2999,13 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
if it.peek().is_some() {
write!(
w,
- "<details class=\"rustdoc-toggle more-examples-toggle\">\
+ "<details class=\"toggle more-examples-toggle\">\
<summary class=\"hideme\">\
<span>More examples</span>\
</summary>\
<div class=\"hide-more\">Hide additional examples</div>\
<div class=\"more-scraped-examples\">\
- <div class=\"toggle-line\"><div class=\"toggle-line-inner\"></div></div>\
- <div class=\"more-scraped-examples-inner\">"
+ <div class=\"toggle-line\"><div class=\"toggle-line-inner\"></div></div>"
);
// Only generate inline code for MAX_FULL_EXAMPLES number of examples. Otherwise we could
@@ -3030,7 +3029,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
write!(w, "</ul></div>");
}
- write!(w, "</div></div></details>");
+ write!(w, "</div></details>");
}
write!(w, "</div>");
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index acbe3f228..f824c9e3a 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -204,7 +204,7 @@ fn should_hide_fields(n_fields: usize) -> bool {
fn toggle_open(w: &mut Buffer, text: impl fmt::Display) {
write!(
w,
- "<details class=\"rustdoc-toggle type-contents-toggle\">\
+ "<details class=\"toggle type-contents-toggle\">\
<summary class=\"hideme\">\
<span>Show {}</span>\
</summary>",
@@ -531,7 +531,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx));
wrap_into_item_decl(w, |w| {
- wrap_item(w, "fn", |w| {
+ wrap_item(w, |w| {
render_attributes_in_pre(w, it, "");
w.reserve(header_len);
write!(
@@ -570,7 +570,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
// Output the trait definition
wrap_into_item_decl(w, |w| {
- wrap_item(w, "trait", |w| {
+ wrap_item(w, |w| {
render_attributes_in_pre(w, it, "");
write!(
w,
@@ -732,7 +732,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
document(&mut content, cx, m, Some(t), HeadingOffset::H5);
let toggled = !content.is_empty();
if toggled {
- write!(w, "<details class=\"rustdoc-toggle method-toggle\" open><summary>");
+ let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
+ write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>");
}
write!(w, "<section id=\"{}\" class=\"method has-srclink\">", id);
render_rightside(w, cx, m, t, RenderMode::Normal);
@@ -1026,8 +1027,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
.chain(std::iter::once("implementors"))
.collect();
if let Some(did) = it.item_id.as_def_id() &&
- let get_extern = { || cache.external_paths.get(&did).map(|s| s.0.clone()) } &&
- let Some(fqp) = cache.exact_paths.get(&did).cloned().or_else(get_extern) {
+ let get_extern = { || cache.external_paths.get(&did).map(|s| &s.0) } &&
+ let Some(fqp) = cache.exact_paths.get(&did).or_else(get_extern) {
js_src_path.extend(fqp[..fqp.len() - 1].iter().copied());
js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), fqp.last().unwrap()));
} else {
@@ -1050,7 +1051,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
wrap_into_item_decl(w, |w| {
- wrap_item(w, "trait-alias", |w| {
+ wrap_item(w, |w| {
render_attributes_in_pre(w, it, "");
write!(
w,
@@ -1074,7 +1075,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &
fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
wrap_into_item_decl(w, |w| {
- wrap_item(w, "opaque", |w| {
+ wrap_item(w, |w| {
render_attributes_in_pre(w, it, "");
write!(
w,
@@ -1098,7 +1099,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &cl
fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) {
fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
- wrap_item(w, "typedef", |w| {
+ wrap_item(w, |w| {
render_attributes_in_pre(w, it, "");
write!(w, "{}", visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx));
write!(
@@ -1127,7 +1128,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
wrap_into_item_decl(w, |w| {
- wrap_item(w, "union", |w| {
+ wrap_item(w, |w| {
render_attributes_in_pre(w, it, "");
render_union(w, it, Some(&s.generics), &s.fields, "", cx);
});
@@ -1192,7 +1193,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
let tcx = cx.tcx();
let count_variants = e.variants().count();
wrap_into_item_decl(w, |w| {
- wrap_item(w, "enum", |w| {
+ wrap_item(w, |w| {
render_attributes_in_pre(w, it, "");
write!(
w,
@@ -1219,25 +1220,16 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
w.write_str(" ");
let name = v.name.unwrap();
match *v.kind {
- clean::VariantItem(ref var) => match var {
- // FIXME(#101337): Show discriminant
- clean::Variant::CLike(..) => write!(w, "{}", name),
- clean::Variant::Tuple(ref s) => {
+ // FIXME(#101337): Show discriminant
+ clean::VariantItem(ref var) => match var.kind {
+ clean::VariantKind::CLike => write!(w, "{}", name),
+ clean::VariantKind::Tuple(ref s) => {
write!(w, "{}(", name);
print_tuple_struct_fields(w, cx, s);
w.write_str(")");
}
- clean::Variant::Struct(ref s) => {
- render_struct(
- w,
- v,
- None,
- s.ctor_kind,
- &s.fields,
- " ",
- false,
- cx,
- );
+ clean::VariantKind::Struct(ref s) => {
+ render_struct(w, v, None, None, &s.fields, " ", false, cx);
}
},
_ => unreachable!(),
@@ -1285,25 +1277,28 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
" rightside",
);
write!(w, "<h3 class=\"code-header\">{name}", name = variant.name.unwrap());
- if let clean::VariantItem(clean::Variant::Tuple(ref s)) = *variant.kind {
+
+ let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() };
+
+ if let clean::VariantKind::Tuple(ref s) = variant_data.kind {
w.write_str("(");
print_tuple_struct_fields(w, cx, s);
w.write_str(")");
}
w.write_str("</h3></section>");
- use crate::clean::Variant;
-
- let heading_and_fields = match &*variant.kind {
- clean::VariantItem(Variant::Struct(s)) => Some(("Fields", &s.fields)),
- // Documentation on tuple variant fields is rare, so to reduce noise we only emit
- // the section if at least one field is documented.
- clean::VariantItem(Variant::Tuple(fields))
- if fields.iter().any(|f| f.doc_value().is_some()) =>
- {
- Some(("Tuple Fields", fields))
+ let heading_and_fields = match &variant_data.kind {
+ clean::VariantKind::Struct(s) => Some(("Fields", &s.fields)),
+ clean::VariantKind::Tuple(fields) => {
+ // Documentation on tuple variant fields is rare, so to reduce noise we only emit
+ // the section if at least one field is documented.
+ if fields.iter().any(|f| f.doc_value().is_some()) {
+ Some(("Tuple Fields", fields))
+ } else {
+ None
+ }
}
- _ => None,
+ clean::VariantKind::CLike => None,
};
if let Some((heading, fields)) = heading_and_fields {
@@ -1362,17 +1357,17 @@ fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &c
let name = it.name.expect("proc-macros always have names");
match m.kind {
MacroKind::Bang => {
- wrap_item(w, "macro", |w| {
+ wrap_item(w, |w| {
write!(w, "{}!() {{ /* proc-macro */ }}", name);
});
}
MacroKind::Attr => {
- wrap_item(w, "attr", |w| {
+ wrap_item(w, |w| {
write!(w, "#[{}]", name);
});
}
MacroKind::Derive => {
- wrap_item(w, "derive", |w| {
+ wrap_item(w, |w| {
write!(w, "#[derive({})]", name);
if !m.helpers.is_empty() {
w.push_str("\n{\n");
@@ -1406,7 +1401,7 @@ fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {
wrap_into_item_decl(w, |w| {
- wrap_item(w, "const", |w| {
+ wrap_item(w, |w| {
let tcx = cx.tcx();
render_attributes_in_code(w, it);
@@ -1456,7 +1451,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle
fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
wrap_into_item_decl(w, |w| {
- wrap_item(w, "struct", |w| {
+ wrap_item(w, |w| {
render_attributes_in_code(w, it);
render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
});
@@ -1509,7 +1504,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
wrap_into_item_decl(w, |w| {
- wrap_item(w, "static", |w| {
+ wrap_item(w, |w| {
render_attributes_in_code(w, it);
write!(
w,
@@ -1526,7 +1521,7 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
wrap_into_item_decl(w, |w| {
- wrap_item(w, "foreigntype", |w| {
+ wrap_item(w, |w| {
w.write_str("extern {\n");
render_attributes_in_code(w, it);
write!(
@@ -1623,11 +1618,11 @@ where
w.write_str("</div>")
}
-fn wrap_item<F>(w: &mut Buffer, item_name: &str, f: F)
+fn wrap_item<F>(w: &mut Buffer, f: F)
where
F: FnOnce(&mut Buffer),
{
- w.write_fmt(format_args!("<pre class=\"rust {}\"><code>", item_name));
+ w.write_str(r#"<pre class="rust"><code>"#);
f(w);
w.write_str("</code></pre>");
}
@@ -1845,7 +1840,7 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) {
if item.is_non_exhaustive() {
write!(
w,
- "<details class=\"rustdoc-toggle non-exhaustive\">\
+ "<details class=\"toggle non-exhaustive\">\
<summary class=\"hideme\"><span>{}</span></summary>\
<div class=\"docblock\">",
{
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 8eb9c07f8..5b0caac09 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -3,7 +3,6 @@ use std::collections::BTreeMap;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::TyCtxt;
-use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::symbol::Symbol;
use serde::ser::{Serialize, SerializeStruct, Serializer};
@@ -24,18 +23,19 @@ pub(crate) fn build_index<'tcx>(
tcx: TyCtxt<'tcx>,
) -> String {
let mut itemid_to_pathid = FxHashMap::default();
+ let mut primitives = FxHashMap::default();
let mut crate_paths = vec![];
// Attach all orphan items to the type's definition if the type
// has since been learned.
for &OrphanImplItem { parent, ref item, ref impl_generics } in &cache.orphan_impl_items {
- if let Some(&(ref fqp, _)) = cache.paths.get(&parent) {
+ if let Some((fqp, _)) = cache.paths.get(&parent) {
let desc = item
.doc_value()
.map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(cache)));
cache.search_index.push(IndexItem {
ty: item.type_(),
- name: item.name.unwrap().to_string(),
+ name: item.name.unwrap(),
path: join_with_double_colon(&fqp[..fqp.len() - 1]),
desc,
parent: Some(parent),
@@ -58,8 +58,8 @@ pub(crate) fn build_index<'tcx>(
// Sort search index items. This improves the compressibility of the search index.
cache.search_index.sort_unstable_by(|k1, k2| {
// `sort_unstable_by_key` produces lifetime errors
- let k1 = (&k1.path, &k1.name, &k1.ty, &k1.parent);
- let k2 = (&k2.path, &k2.name, &k2.ty, &k2.parent);
+ let k1 = (&k1.path, k1.name.as_str(), &k1.ty, &k1.parent);
+ let k2 = (&k2.path, k2.name.as_str(), &k2.ty, &k2.parent);
std::cmp::Ord::cmp(&k1, &k2)
});
@@ -78,16 +78,45 @@ pub(crate) fn build_index<'tcx>(
// First, on function signatures
let mut search_index = std::mem::replace(&mut cache.search_index, Vec::new());
for item in search_index.iter_mut() {
+ fn insert_into_map<F: std::hash::Hash + Eq>(
+ ty: &mut RenderType,
+ map: &mut FxHashMap<F, usize>,
+ itemid: F,
+ lastpathid: &mut usize,
+ crate_paths: &mut Vec<(ItemType, Symbol)>,
+ item_type: ItemType,
+ path: Symbol,
+ ) {
+ match map.entry(itemid) {
+ Entry::Occupied(entry) => ty.id = Some(RenderTypeId::Index(*entry.get())),
+ Entry::Vacant(entry) => {
+ let pathid = *lastpathid;
+ entry.insert(pathid);
+ *lastpathid += 1;
+ crate_paths.push((item_type, path));
+ ty.id = Some(RenderTypeId::Index(pathid));
+ }
+ }
+ }
+
fn convert_render_type(
ty: &mut RenderType,
cache: &mut Cache,
itemid_to_pathid: &mut FxHashMap<ItemId, usize>,
+ primitives: &mut FxHashMap<Symbol, usize>,
lastpathid: &mut usize,
crate_paths: &mut Vec<(ItemType, Symbol)>,
) {
if let Some(generics) = &mut ty.generics {
for item in generics {
- convert_render_type(item, cache, itemid_to_pathid, lastpathid, crate_paths);
+ convert_render_type(
+ item,
+ cache,
+ itemid_to_pathid,
+ primitives,
+ lastpathid,
+ crate_paths,
+ );
}
}
let Cache { ref paths, ref external_paths, .. } = *cache;
@@ -95,33 +124,37 @@ pub(crate) fn build_index<'tcx>(
assert!(ty.generics.is_some());
return;
};
- let (itemid, path, item_type) = match id {
+ match id {
RenderTypeId::DefId(defid) => {
if let Some(&(ref fqp, item_type)) =
paths.get(&defid).or_else(|| external_paths.get(&defid))
{
- (ItemId::DefId(defid), *fqp.last().unwrap(), item_type)
+ insert_into_map(
+ ty,
+ itemid_to_pathid,
+ ItemId::DefId(defid),
+ lastpathid,
+ crate_paths,
+ item_type,
+ *fqp.last().unwrap(),
+ );
} else {
ty.id = None;
- return;
}
}
- RenderTypeId::Primitive(primitive) => (
- ItemId::Primitive(primitive, LOCAL_CRATE),
- primitive.as_sym(),
- ItemType::Primitive,
- ),
- RenderTypeId::Index(_) => return,
- };
- match itemid_to_pathid.entry(itemid) {
- Entry::Occupied(entry) => ty.id = Some(RenderTypeId::Index(*entry.get())),
- Entry::Vacant(entry) => {
- let pathid = *lastpathid;
- entry.insert(pathid);
- *lastpathid += 1;
- crate_paths.push((item_type, path));
- ty.id = Some(RenderTypeId::Index(pathid));
+ RenderTypeId::Primitive(primitive) => {
+ let sym = primitive.as_sym();
+ insert_into_map(
+ ty,
+ primitives,
+ sym,
+ lastpathid,
+ crate_paths,
+ ItemType::Primitive,
+ sym,
+ );
}
+ RenderTypeId::Index(_) => {}
}
}
if let Some(search_type) = &mut item.search_type {
@@ -130,6 +163,7 @@ pub(crate) fn build_index<'tcx>(
item,
cache,
&mut itemid_to_pathid,
+ &mut primitives,
&mut lastpathid,
&mut crate_paths,
);
@@ -139,6 +173,7 @@ pub(crate) fn build_index<'tcx>(
item,
cache,
&mut itemid_to_pathid,
+ &mut primitives,
&mut lastpathid,
&mut crate_paths,
);
@@ -205,7 +240,7 @@ pub(crate) fn build_index<'tcx>(
)?;
crate_data.serialize_field(
"n",
- &self.items.iter().map(|item| &item.name).collect::<Vec<_>>(),
+ &self.items.iter().map(|item| item.name.as_str()).collect::<Vec<_>>(),
)?;
crate_data.serialize_field(
"q",
@@ -264,7 +299,7 @@ pub(crate) fn build_index<'tcx>(
)?;
crate_data.serialize_field(
"p",
- &self.paths.iter().map(|(it, s)| (it, s.to_string())).collect::<Vec<_>>(),
+ &self.paths.iter().map(|(it, s)| (it, s.as_str())).collect::<Vec<_>>(),
)?;
if has_aliases {
crate_data.serialize_field("a", &self.aliases)?;
@@ -322,8 +357,7 @@ fn get_index_type_id(clean_type: &clean::Type) -> Option<RenderTypeId> {
match *clean_type {
clean::Type::Path { ref path, .. } => Some(RenderTypeId::DefId(path.def_id())),
clean::DynTrait(ref bounds, _) => {
- let path = &bounds[0].trait_;
- Some(RenderTypeId::DefId(path.def_id()))
+ bounds.get(0).map(|b| RenderTypeId::DefId(b.trait_.def_id()))
}
clean::Primitive(p) => Some(RenderTypeId::Primitive(p)),
clean::BorrowedRef { ref type_, .. } | clean::RawPointer(_, ref type_) => {
@@ -539,7 +573,7 @@ fn get_fn_inputs_and_outputs<'tcx>(
let decl = &func.decl;
let combined_generics;
- let (self_, generics) = if let Some(&(ref impl_self, ref impl_generics)) = impl_generics {
+ let (self_, generics) = if let Some((impl_self, impl_generics)) = impl_generics {
match (impl_generics.is_empty(), func.generics.is_empty()) {
(true, _) => (Some(impl_self), &func.generics),
(_, true) => (Some(impl_self), impl_generics),
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 94d8a9fec..bc8badad3 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -1,8 +1,9 @@
+use std::cell::RefCell;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::path::{Component, Path};
-use std::rc::Rc;
+use std::rc::{Rc, Weak};
use itertools::Itertools;
use rustc_data_structures::flock;
@@ -184,23 +185,26 @@ pub(super) fn write_shared(
use std::ffi::OsString;
- #[derive(Debug)]
+ #[derive(Debug, Default)]
struct Hierarchy {
+ parent: Weak<Self>,
elem: OsString,
- children: FxHashMap<OsString, Hierarchy>,
- elems: FxHashSet<OsString>,
+ children: RefCell<FxHashMap<OsString, Rc<Self>>>,
+ elems: RefCell<FxHashSet<OsString>>,
}
impl Hierarchy {
- fn new(elem: OsString) -> Hierarchy {
- Hierarchy { elem, children: FxHashMap::default(), elems: FxHashSet::default() }
+ fn with_parent(elem: OsString, parent: &Rc<Self>) -> Self {
+ Self { elem, parent: Rc::downgrade(parent), ..Self::default() }
}
fn to_json_string(&self) -> String {
- let mut subs: Vec<&Hierarchy> = self.children.values().collect();
+ let borrow = self.children.borrow();
+ let mut subs: Vec<_> = borrow.values().collect();
subs.sort_unstable_by(|a, b| a.elem.cmp(&b.elem));
let mut files = self
.elems
+ .borrow()
.iter()
.map(|s| format!("\"{}\"", s.to_str().expect("invalid osstring conversion")))
.collect::<Vec<_>>();
@@ -220,36 +224,52 @@ pub(super) fn write_shared(
files = files
)
}
- }
- if cx.include_sources {
- let mut hierarchy = Hierarchy::new(OsString::new());
- for source in cx
- .shared
- .local_sources
- .iter()
- .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root).ok())
- {
- let mut h = &mut hierarchy;
- let mut elems = source
+ fn add_path(self: &Rc<Self>, path: &Path) {
+ let mut h = Rc::clone(&self);
+ let mut elems = path
.components()
.filter_map(|s| match s {
Component::Normal(s) => Some(s.to_owned()),
+ Component::ParentDir => Some(OsString::from("..")),
_ => None,
})
.peekable();
loop {
let cur_elem = elems.next().expect("empty file path");
+ if cur_elem == ".." {
+ if let Some(parent) = h.parent.upgrade() {
+ h = parent;
+ }
+ continue;
+ }
if elems.peek().is_none() {
- h.elems.insert(cur_elem);
+ h.elems.borrow_mut().insert(cur_elem);
break;
} else {
- let e = cur_elem.clone();
- h = h.children.entry(cur_elem.clone()).or_insert_with(|| Hierarchy::new(e));
+ let entry = Rc::clone(
+ h.children
+ .borrow_mut()
+ .entry(cur_elem.clone())
+ .or_insert_with(|| Rc::new(Self::with_parent(cur_elem, &h))),
+ );
+ h = entry;
}
}
}
+ }
+ if cx.include_sources {
+ let hierarchy = Rc::new(Hierarchy::default());
+ for source in cx
+ .shared
+ .local_sources
+ .iter()
+ .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root).ok())
+ {
+ hierarchy.add_path(source);
+ }
+ let hierarchy = Rc::try_unwrap(hierarchy).unwrap();
let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix));
let make_sources = || {
let (mut all_sources, _krates) =
@@ -325,7 +345,7 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
};
let content = format!(
- "<h1 class=\"fqn\">List of all crates</h1><ul class=\"all-items\">{}</ul>",
+ "<h1>List of all crates</h1><ul class=\"all-items\">{}</ul>",
krates
.iter()
.map(|s| {
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 54e296959..799c497d1 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -13,6 +13,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::source_map::FileName;
+use std::cell::RefCell;
use std::ffi::OsStr;
use std::fs;
use std::path::{Component, Path, PathBuf};
@@ -72,12 +73,22 @@ impl LocalSourcesCollector<'_, '_> {
return;
}
- let mut href = String::new();
- clean_path(self.src_root, &p, false, |component| {
- href.push_str(&component.to_string_lossy());
- href.push('/');
- });
+ let href = RefCell::new(PathBuf::new());
+ clean_path(
+ &self.src_root,
+ &p,
+ |component| {
+ href.borrow_mut().push(component);
+ },
+ || {
+ href.borrow_mut().pop();
+ },
+ );
+ let mut href = href.into_inner().to_string_lossy().to_string();
+ if let Some(c) = href.as_bytes().last() && *c != b'/' {
+ href.push('/');
+ }
let mut src_fname = p.file_name().expect("source has no filename").to_os_string();
src_fname.push(".html");
href.push_str(&src_fname.to_string_lossy());
@@ -180,13 +191,28 @@ impl SourceCollector<'_, '_> {
let shared = Rc::clone(&self.cx.shared);
// Create the intermediate directories
- let mut cur = self.dst.clone();
- let mut root_path = String::from("../../");
- clean_path(&shared.src_root, &p, false, |component| {
- cur.push(component);
- root_path.push_str("../");
- });
+ let cur = RefCell::new(PathBuf::new());
+ let root_path = RefCell::new(PathBuf::new());
+
+ clean_path(
+ &shared.src_root,
+ &p,
+ |component| {
+ cur.borrow_mut().push(component);
+ root_path.borrow_mut().push("..");
+ },
+ || {
+ cur.borrow_mut().pop();
+ root_path.borrow_mut().pop();
+ },
+ );
+ let root_path = PathBuf::from("../../").join(root_path.into_inner());
+ let mut root_path = root_path.to_string_lossy();
+ if let Some(c) = root_path.as_bytes().last() && *c != b'/' {
+ root_path += "/";
+ }
+ let mut cur = self.dst.join(cur.into_inner());
shared.ensure_dir(&cur)?;
let src_fname = p.file_name().expect("source has no filename").to_os_string();
@@ -232,11 +258,13 @@ impl SourceCollector<'_, '_> {
/// Takes a path to a source file and cleans the path to it. This canonicalizes
/// things like ".." to components which preserve the "top down" hierarchy of a
/// static HTML tree. Each component in the cleaned path will be passed as an
-/// argument to `f`. The very last component of the path (ie the file name) will
-/// be passed to `f` if `keep_filename` is true, and ignored otherwise.
-pub(crate) fn clean_path<F>(src_root: &Path, p: &Path, keep_filename: bool, mut f: F)
+/// argument to `f`. The very last component of the path (ie the file name) is ignored.
+/// If a `..` is encountered, the `parent` closure will be called to allow the callee to
+/// handle it.
+pub(crate) fn clean_path<F, P>(src_root: &Path, p: &Path, mut f: F, mut parent: P)
where
F: FnMut(&OsStr),
+ P: FnMut(),
{
// make it relative, if possible
let p = p.strip_prefix(src_root).unwrap_or(p);
@@ -244,12 +272,12 @@ where
let mut iter = p.components().peekable();
while let Some(c) = iter.next() {
- if !keep_filename && iter.peek().is_none() {
+ if iter.peek().is_none() {
break;
}
match c {
- Component::ParentDir => f("up".as_ref()),
+ Component::ParentDir => parent(),
Component::Normal(c) => f(c),
_ => continue,
}
@@ -276,7 +304,7 @@ pub(crate) fn print_src(
let mut line_numbers = Buffer::empty_from(buf);
let extra;
line_numbers.write_str("<pre class=\"src-line-numbers\">");
- let current_href = &context
+ let current_href = context
.href_from_span(clean::Span::new(file_span), false)
.expect("only local crates should have sources emitted");
match source_context {
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index afcb40224..a93f60da2 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -76,8 +76,6 @@
}
* {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
box-sizing: border-box;
}
@@ -110,11 +108,7 @@ body {
/* Then override it with `anywhere`, which is required to make non-Safari browsers break
more aggressively when we want them to. */
overflow-wrap: anywhere;
-
- -webkit-font-feature-settings: "kern", "liga";
- -moz-font-feature-settings: "kern", "liga";
font-feature-settings: "kern", "liga";
-
background-color: var(--main-background-color);
color: var(--main-color);
}
@@ -145,7 +139,7 @@ h1, h2, h3, h4 {
.docblock > h6:first-child {
margin-top: 0;
}
-h1.fqn {
+.main-heading h1 {
margin: 0;
padding: 0;
flex-grow: 1;
@@ -212,7 +206,7 @@ pre.rust a,
.mobile-topbar h2 a,
h1 a,
.search-results a,
-.item-left .stab,
+.stab,
.result-name .primitive > i, .result-name .keyword > i {
color: var(--main-color);
}
@@ -259,6 +253,7 @@ h1 a,
a {
color: var(--link-color);
+ text-decoration: none;
}
ol, ul {
@@ -322,11 +317,7 @@ main {
margin-right: auto;
}
-.source .width-limiter {
- max-width: unset;
-}
-
-details:not(.rustdoc-toggle) summary {
+details:not(.toggle) summary {
margin-bottom: .6em;
}
@@ -342,26 +333,35 @@ code, pre, a.test-arrow, .code-header {
}
pre {
padding: 14px;
+ line-height: 1.5; /* https://github.com/rust-lang/rust/issues/105906 */
}
.item-decl pre {
overflow-x: auto;
}
+/* This rule allows to have scrolling on the X axis. */
+.item-decl .type-contents-toggle {
+ contain: initial;
+}
.source .content pre {
padding: 20px;
}
+.rustdoc.source .example-wrap > pre.src-line-numbers {
+ padding: 20px 0 20px 4px;
+}
img {
max-width: 100%;
}
-.source .content {
- overflow: visible;
-}
-
.sub-logo-container, .logo-container {
/* zero text boxes so that computed line height = image height exactly */
line-height: 0;
+ display: block;
+}
+
+.sub-logo-container {
+ margin-right: 32px;
}
.sub-logo-container > img {
@@ -374,10 +374,6 @@ img {
filter: var(--rust-logo-filter);
}
-.sidebar, .mobile-topbar, .sidebar-menu-toggle {
- background-color: var(--sidebar-background-color);
-}
-
.sidebar {
font-size: 0.875rem;
flex: 0 0 200px;
@@ -396,15 +392,16 @@ img {
overflow-y: hidden;
}
-.source .sidebar, #sidebar-toggle, #source-sidebar {
+.sidebar, .mobile-topbar, .sidebar-menu-toggle,
+#src-sidebar-toggle, #source-sidebar {
background-color: var(--sidebar-background-color);
}
-#sidebar-toggle > button:hover, #sidebar-toggle > button:focus {
+#src-sidebar-toggle > button:hover, #src-sidebar-toggle > button:focus {
background-color: var(--sidebar-background-color-hover);
}
-.source .sidebar > *:not(#sidebar-toggle) {
+.source .sidebar > *:not(#src-sidebar-toggle) {
visibility: hidden;
}
@@ -413,7 +410,7 @@ img {
flex-basis: 300px;
}
-.source-sidebar-expanded .source .sidebar > *:not(#sidebar-toggle) {
+.source-sidebar-expanded .source .sidebar > *:not(#src-sidebar-toggle) {
visibility: visible;
}
@@ -500,11 +497,11 @@ ul.block, .block li {
padding-left: 24px;
}
-.sidebar a, .sidebar .current {
+.sidebar a {
color: var(--sidebar-link-color);
}
.sidebar .current,
-.sidebar a:hover {
+.sidebar a:hover:not(.logo-container) {
background-color: var(--sidebar-current-link-background-color);
}
@@ -522,11 +519,6 @@ ul.block, .block li {
display: none;
}
-.source .content pre.rust {
- overflow: auto;
- padding-left: 0;
-}
-
.rustdoc .example-wrap {
display: flex;
position: relative;
@@ -547,29 +539,26 @@ ul.block, .block li {
.rustdoc .example-wrap > pre.example-line-numbers,
.rustdoc .example-wrap > pre.src-line-numbers {
flex-grow: 0;
+ min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */
overflow: initial;
text-align: right;
-webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
user-select: none;
+ padding: 14px 8px;
+ color: var(--src-line-numbers-span-color);
}
-.example-line-numbers {
- border: 1px solid;
- padding: 13px 8px;
- border-top-left-radius: 5px;
- border-bottom-left-radius: 5px;
- border-color: var(--example-line-numbers-border-color);
+.rustdoc .example-wrap > pre.src-line-numbers {
+ padding: 14px 0;
}
-
.src-line-numbers a, .src-line-numbers span {
color: var(--src-line-numbers-span-color);
+ padding: 0 8px;
}
.src-line-numbers :target {
background-color: transparent;
border-right: none;
- padding-right: 0;
+ padding: 0 8px;
}
.src-line-numbers .line-highlighted {
background-color: var(--src-line-number-highlighted-background-color);
@@ -582,12 +571,10 @@ ul.block, .block li {
.docblock-short {
overflow-wrap: break-word;
overflow-wrap: anywhere;
- overflow: hidden;
- text-overflow: ellipsis;
}
/* Wrap non-pre code blocks (`text`) but not (```text```). */
-.docblock > :not(pre) > code,
-.docblock-short > code {
+.docblock :not(pre) > code,
+.docblock-short code {
white-space: pre-wrap;
}
@@ -679,13 +666,6 @@ nav.sub {
.source nav.sub {
margin: 0 0 15px 0;
}
-.source .search-form {
- margin-left: 32px;
-}
-
-a {
- text-decoration: none;
-}
.small-section-header {
/* fields use <span> tags, but should get their own lines */
@@ -693,14 +673,10 @@ a {
position: relative;
}
-.small-section-header:hover > .anchor {
+.small-section-header:hover > .anchor, .impl:hover > .anchor,
+.trait-impl:hover > .anchor, .variant:hover > .anchor {
display: initial;
}
-
-.impl:hover > .anchor, .trait-impl:hover > .anchor, .variant:hover > .anchor {
- display: inline-block;
- position: absolute;
-}
.anchor {
display: none;
position: absolute;
@@ -731,7 +707,7 @@ h2.small-section-header > .anchor {
/* In most contexts we use `overflow-wrap: anywhere` to ensure that we can wrap
as much as needed on mobile (see
- src/test/rustdoc-gui/type-declaration-overflow.goml for an example of why
+ tests/rustdoc-gui/type-declaration-overflow.goml for an example of why
this matters). The `anywhere` value means:
"Soft wrap opportunities introduced by the word break are considered when
@@ -903,10 +879,11 @@ so that we can apply CSS-filters to change the arrow color in themes */
top: 100%;
right: 0;
z-index: 2;
- display: block;
margin-top: 7px;
border-radius: 3px;
border: 1px solid var(--border-color);
+ background-color: var(--main-background-color);
+ color: var(--main-color);
--popover-arrow-offset: 11px;
}
@@ -917,16 +894,12 @@ so that we can apply CSS-filters to change the arrow color in themes */
right: var(--popover-arrow-offset);
border: solid var(--border-color);
border-width: 1px 1px 0 0;
+ background-color: var(--main-background-color);
padding: 4px;
transform: rotate(-45deg);
top: -5px;
}
-.popover, .popover::before {
- background-color: var(--main-background-color);
- color: var(--main-color);
-}
-
/* use larger max-width for help popover, but not for help.html */
#help.popover {
max-width: 600px;
@@ -960,22 +933,29 @@ so that we can apply CSS-filters to change the arrow color in themes */
}
.item-info .stab {
- width: fit-content;
/* This min-height is needed to unify the height of the stab elements because some of them
have emojis.
*/
min-height: 36px;
display: flex;
- align-items: center;
- white-space: pre-wrap;
-}
-.stab {
padding: 3px;
margin-bottom: 5px;
+}
+.item-left .stab {
+ margin-left: 0.3125em;
+}
+.stab {
+ padding: 0 2px;
font-size: 0.875rem;
font-weight: normal;
color: var(--main-color);
background-color: var(--stab-background-color);
+ width: fit-content;
+ align-items: center;
+ white-space: pre-wrap;
+ border-radius: 3px;
+ display: inline-flex;
+ vertical-align: text-bottom;
}
.stab.portability > code {
@@ -988,12 +968,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
margin-right: 0.3rem;
}
-/* This is to prevent the `.stab` elements to overflow the .docblock elements. */
-.docblock .stab {
- padding: 0 0.125em;
- margin-bottom: 0;
-}
-
/* Black one-pixel outline around emoji shapes */
.emoji {
text-shadow:
@@ -1003,16 +977,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
0 -1px 0 black;
}
-.item-left .stab {
- border-radius: 3px;
- display: inline-block;
- line-height: 1.2;
- margin-bottom: 0;
- margin-left: 0.3125em;
- padding: 2px;
- vertical-align: text-bottom;
-}
-
.module-item.unstable,
.import-item.unstable {
opacity: 0.65;
@@ -1084,6 +1048,10 @@ pre.rust .doccomment {
color: var(--code-highlight-doc-comment-color);
}
+.rustdoc.source .example-wrap pre.rust a {
+ background: var(--codeblock-link-background);
+}
+
.example-wrap.compile_fail,
.example-wrap.should_panic {
border-left: 2px solid var(--codeblock-error-color);
@@ -1127,9 +1095,7 @@ pre.rust .doccomment {
top: 5px;
}
-.example-wrap .tooltip::after {
- display: none;
- text-align: center;
+.example-wrap .tooltip:hover::after {
padding: 5px 3px 3px 3px;
border-radius: 6px;
margin-left: 5px;
@@ -1143,35 +1109,30 @@ pre.rust .doccomment {
color: var(--tooltip-color);
}
-.example-wrap .tooltip::before {
+.example-wrap .tooltip:hover::before {
content: " ";
position: absolute;
top: 50%;
left: 16px;
margin-top: -5px;
- display: none;
z-index: 1;
border: 5px solid transparent;
border-right-color: var(--tooltip-background-color);
}
-.example-wrap.ignore .tooltip::after {
+.example-wrap.ignore .tooltip:hover::after {
content: "This example is not tested";
}
-.example-wrap.compile_fail .tooltip::after {
+.example-wrap.compile_fail .tooltip:hover::after {
content: "This example deliberately fails to compile";
}
-.example-wrap.should_panic .tooltip::after {
+.example-wrap.should_panic .tooltip:hover::after {
content: "This example panics";
}
-.example-wrap.edition .tooltip::after {
+.example-wrap.edition .tooltip:hover::after {
content: "This code runs with edition " attr(data-edition);
}
-.example-wrap .tooltip:hover::before, .example-wrap .tooltip:hover::after {
- display: inline;
-}
-
.example-wrap.compile_fail .tooltip,
.example-wrap.should_panic .tooltip,
.example-wrap.ignore .tooltip {
@@ -1253,11 +1214,11 @@ a.test-arrow:hover {
content: "\00a0";
}
-.notable .docblock {
+.notable .content {
margin: 0.25em 0.5em;
}
-.notable .docblock pre, .notable .docblock code {
+.notable .content pre, .notable .content code {
background: transparent;
margin: 0;
padding: 0;
@@ -1265,6 +1226,10 @@ a.test-arrow:hover {
white-space: pre-wrap;
}
+.notable .content > h3:first-child {
+ margin: 0 0 5px 0;
+}
+
.search-failed {
text-align: center;
margin-top: 20px;
@@ -1282,14 +1247,14 @@ a.test-arrow:hover {
margin-right: auto;
}
-#titles {
+#search-tabs {
display: flex;
flex-direction: row;
gap: 1px;
margin-bottom: 4px;
}
-#titles > button {
+#search-tabs button {
text-align: center;
font-size: 1.125rem;
border: 0;
@@ -1299,12 +1264,12 @@ a.test-arrow:hover {
color: inherit;
}
-#titles > button > div.count {
- display: inline-block;
+#search-tabs .count {
font-size: 1rem;
+ color: var(--search-tab-title-count-color);
}
-#sidebar-toggle {
+#src-sidebar-toggle {
position: sticky;
top: 0;
left: 0;
@@ -1333,7 +1298,7 @@ a.test-arrow:hover {
#source-sidebar div.files > a.selected {
background-color: var(--source-sidebar-background-selected);
}
-#sidebar-toggle > button {
+#src-sidebar-toggle > button {
font-size: inherit;
font-weight: bold;
background: none;
@@ -1346,15 +1311,11 @@ a.test-arrow:hover {
-webkit-appearance: none;
opacity: 1;
}
+
#settings-menu, #help-button {
margin-left: 4px;
display: flex;
}
-
-#settings-menu > a, #help-button > a, #copy-path {
- width: 33px;
-}
-
#settings-menu > a, #help-button > a {
display: flex;
align-items: center;
@@ -1366,6 +1327,7 @@ a.test-arrow:hover {
/* Rare exception to specifying font sizes in rem. Since this is acting
as an icon, it's okay to specify their sizes in pixels. */
font-size: 20px;
+ width: 33px;
}
#settings-menu > a:hover, #settings-menu > a:focus,
@@ -1381,6 +1343,7 @@ a.test-arrow:hover {
padding: 0;
padding-left: 2px;
border: 0;
+ width: 33px;
}
#copy-path > img {
filter: var(--copy-path-img-filter);
@@ -1409,8 +1372,7 @@ kbd {
vertical-align: middle;
border: solid 1px var(--border-color);
border-radius: 3px;
- cursor: default;
- color: var(--kbd--color);
+ color: var(--kbd-color);
background-color: var(--kbd-background);
box-shadow: inset 0 -1px 0 var(--kbd-box-shadow-color);
}
@@ -1423,31 +1385,10 @@ details.dir-entry {
padding-left: 4px;
}
-details.dir-entry > summary::after {
- content: " ►";
- position: absolute;
- left: -15px;
- top: 0px;
- font-size: 80%;
- padding: 2px 0px;
- /* set width to cover gap between arrow and text */
- width: 25px;
-}
-
-details[open].dir-entry > summary::after {
- content: " ▼";
-}
-
-details.dir-entry > summary::-webkit-details-marker,
-details.dir-entry > summary::marker {
- display: none;
-}
-
details.dir-entry > summary {
- margin: 0 0 0 13px;
- list-style: none;
+ margin: 0 0 0 -4px;
+ padding: 0 0 0 4px;
cursor: pointer;
- position: relative;
}
details.dir-entry div.folders, details.dir-entry div.files {
@@ -1464,7 +1405,7 @@ details.dir-entry a {
Unfortunately we can't yet specify contain: content or contain: strict
because the [-]/[+] toggles extend past the boundaries of the <details>
https://developer.mozilla.org/en-US/docs/Web/CSS/contain */
-details.rustdoc-toggle {
+details.toggle {
contain: layout;
position: relative;
}
@@ -1472,26 +1413,26 @@ details.rustdoc-toggle {
/* The hideme class is used on summary tags that contain a span with
placeholder text shown only when the toggle is closed. For instance,
"Expand description" or "Show methods". */
-details.rustdoc-toggle > summary.hideme {
+details.toggle > summary.hideme {
cursor: pointer;
font-size: 1rem;
}
-details.rustdoc-toggle > summary {
+details.toggle > summary {
list-style: none;
/* focus outline is shown on `::before` instead of this */
outline: none;
}
-details.rustdoc-toggle > summary::-webkit-details-marker,
-details.rustdoc-toggle > summary::marker {
+details.toggle > summary::-webkit-details-marker,
+details.toggle > summary::marker {
display: none;
}
-details.rustdoc-toggle > summary.hideme > span {
+details.toggle > summary.hideme > span {
margin-left: 9px;
}
-details.rustdoc-toggle > summary::before {
+details.toggle > summary::before {
background: url("toggle-plus-1092eb4930d581b0.svg") no-repeat top left;
content: "";
cursor: pointer;
@@ -1503,14 +1444,14 @@ details.rustdoc-toggle > summary::before {
filter: var(--toggle-filter);
}
-details.rustdoc-toggle > summary.hideme > span,
+details.toggle > summary.hideme > span,
.more-examples-toggle summary, .more-examples-toggle .hide-more {
color: var(--toggles-color);
}
/* Screen readers see the text version at the end the line.
Visual readers see the icon at the start of the line, but small and transparent. */
-details.rustdoc-toggle > summary::after {
+details.toggle > summary::after {
content: "Expand";
overflow: hidden;
width: 0;
@@ -1518,17 +1459,17 @@ details.rustdoc-toggle > summary::after {
position: absolute;
}
-details.rustdoc-toggle > summary.hideme::after {
+details.toggle > summary.hideme::after {
/* "hideme" toggles already have a description when they're contracted */
content: "";
}
-details.rustdoc-toggle > summary:focus::before,
-details.rustdoc-toggle > summary:hover::before {
+details.toggle > summary:focus::before,
+details.toggle > summary:hover::before {
opacity: 1;
}
-details.rustdoc-toggle > summary:focus-visible::before {
+details.toggle > summary:focus-visible::before {
/* The SVG is black, and gets turned white using a filter in the dark themes.
Do the same with the outline.
The dotted 1px style is copied from Firefox's focus ring style.
@@ -1541,17 +1482,17 @@ details.non-exhaustive {
margin-bottom: 8px;
}
-details.rustdoc-toggle > summary.hideme::before {
+details.toggle > summary.hideme::before {
position: relative;
}
-details.rustdoc-toggle > summary:not(.hideme)::before {
+details.toggle > summary:not(.hideme)::before {
position: absolute;
left: -24px;
top: 4px;
}
-.impl-items > details.rustdoc-toggle > summary:not(.hideme)::before {
+.impl-items > details.toggle > summary:not(.hideme)::before {
position: absolute;
left: -24px;
}
@@ -1561,19 +1502,19 @@ details.rustdoc-toggle > summary:not(.hideme)::before {
affect the layout of the items to its right. To do that, we use
absolute positioning. Note that we also set position: relative
on the parent <details> to make this work properly. */
-details.rustdoc-toggle[open] > summary.hideme {
+details.toggle[open] > summary.hideme {
position: absolute;
}
-details.rustdoc-toggle[open] > summary.hideme > span {
+details.toggle[open] > summary.hideme > span {
display: none;
}
-details.rustdoc-toggle[open] > summary::before {
+details.toggle[open] > summary::before {
background: url("toggle-minus-31bbd6e4c77f5c96.svg") no-repeat top left;
}
-details.rustdoc-toggle[open] > summary::after {
+details.toggle[open] > summary::after {
content: "Collapse";
}
@@ -1633,7 +1574,7 @@ in storage.js
/* Hide the logo and item name from the sidebar. Those are displayed
in the mobile-topbar instead. */
- .sidebar .sidebar-logo,
+ .sidebar .logo-container,
.sidebar .location {
display: none;
}
@@ -1662,14 +1603,10 @@ in storage.js
.sidebar.shown,
.source-sidebar-expanded .source .sidebar,
- .sidebar:focus-within {
+ .rustdoc:not(.source) .sidebar:focus-within {
left: 0;
}
- .rustdoc.source > .sidebar {
- width: 0;
- }
-
.mobile-topbar h2 {
padding-bottom: 0;
margin: auto 0.5em auto auto;
@@ -1719,30 +1656,25 @@ in storage.js
margin-top: 1em;
}
- .content {
- margin-left: 0px;
- }
-
.anchor {
display: none !important;
}
- #titles > button > div.count {
+ #search-tabs .count {
display: block;
}
- #main-content > details.rustdoc-toggle > summary::before,
- #main-content > div > details.rustdoc-toggle > summary::before {
+ #main-content > details.toggle > summary::before,
+ #main-content > div > details.toggle > summary::before {
left: -11px;
}
- #sidebar-toggle {
+ #src-sidebar-toggle {
position: fixed;
left: 1px;
top: 100px;
width: 30px;
font-size: 1.5rem;
- text-align: center;
padding: 0;
z-index: 10;
border-top-right-radius: 3px;
@@ -1751,7 +1683,7 @@ in storage.js
border-left: 0;
}
- .source-sidebar-expanded #sidebar-toggle {
+ .source-sidebar-expanded #src-sidebar-toggle {
left: unset;
top: unset;
width: unset;
@@ -1787,12 +1719,12 @@ in storage.js
}
/* Position of the "[-]" element. */
- details.rustdoc-toggle:not(.top-doc) > summary {
+ details.toggle:not(.top-doc) > summary {
margin-left: 10px;
}
- .impl-items > details.rustdoc-toggle > summary:not(.hideme)::before,
- #main-content > details.rustdoc-toggle:not(.top-doc) > summary::before,
- #main-content > div > details.rustdoc-toggle > summary::before {
+ .impl-items > details.toggle > summary:not(.hideme)::before,
+ #main-content > details.toggle:not(.top-doc) > summary::before,
+ #main-content > div > details.toggle > summary::before {
left: -11px;
}
@@ -1825,8 +1757,8 @@ in storage.js
@media print {
nav.sidebar, nav.sub, .out-of-band, a.srclink, #copy-path,
- details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle > summary::before,
- details.rustdoc-toggle.top-doc > summary {
+ details.toggle[open] > summary::before, details.toggle > summary::before,
+ details.toggle.top-doc > summary {
display: none;
}
@@ -1861,13 +1793,6 @@ in storage.js
height: 35px;
width: 35px;
}
-
- #sidebar-toggle {
- top: 10px;
- }
- .source-sidebar-expanded #sidebar-toggle {
- top: unset;
- }
}
.variant,
@@ -1875,23 +1800,24 @@ in storage.js
.impl,
#implementors-list > .docblock,
.impl-items > section,
-.impl-items > .rustdoc-toggle > summary,
+.impl-items > .toggle > summary,
.methods > section,
-.methods > .rustdoc-toggle > summary
+.methods > .toggle > summary
{
margin-bottom: 0.75em;
}
.variants > .docblock,
-.impl-items > .rustdoc-toggle[open]:not(:last-child),
-.methods > .rustdoc-toggle[open]:not(:last-child),
+.implementors-toggle > .docblock,
+.impl-items > .toggle[open]:not(:last-child),
+.methods > .toggle[open]:not(:last-child),
.implementors-toggle[open]:not(:last-child) {
margin-bottom: 2em;
}
-#trait-implementations-list .impl-items > .rustdoc-toggle:not(:last-child),
-#synthetic-implementations-list .impl-items > .rustdoc-toggle:not(:last-child),
-#blanket-implementations-list .impl-items > .rustdoc-toggle:not(:last-child) {
+#trait-implementations-list .impl-items > .toggle:not(:last-child),
+#synthetic-implementations-list .impl-items > .toggle:not(:last-child),
+#blanket-implementations-list .impl-items > .toggle:not(:last-child) {
margin-bottom: 1em;
}
@@ -1904,9 +1830,13 @@ in storage.js
font-size: 12px;
position: relative;
bottom: 1px;
- border-width: 1px;
- border-style: solid;
+ border: 1px solid var(--scrape-example-help-border-color);
border-radius: 50px;
+ color: var(--scrape-example-help-color);
+}
+.scraped-example-list .scrape-help:hover {
+ border-color: var(--scrape-example-help-hover-border-color);
+ color: var(--scrape-example-help-hover-color);
}
.scraped-example {
@@ -1982,21 +1912,8 @@ in storage.js
bottom: 0;
}
-.scraped-example .code-wrapper .src-line-numbers {
- margin: 0;
- padding: 14px 0;
-}
-
-.scraped-example .code-wrapper .src-line-numbers a,
-.scraped-example .code-wrapper .src-line-numbers span {
- padding: 0 14px;
-}
-
.scraped-example .code-wrapper .example-wrap {
- display: grid;
- grid-template-columns: max-content auto;
width: 100%;
- overflow-x: auto;
overflow-y: hidden;
margin-bottom: 0;
}
@@ -2005,12 +1922,12 @@ in storage.js
overflow-x: hidden;
}
-.scraped-example .code-wrapper .example-wrap pre.rust {
- overflow-x: inherit;
- width: inherit;
- overflow-y: hidden;
+.scraped-example .example-wrap .rust span.highlight {
+ background: var(--scrape-example-code-line-highlight);
+}
+.scraped-example .example-wrap .rust span.highlight.focus {
+ background: var(--scrape-example-code-line-highlight-focus);
}
-
.more-examples-toggle {
max-width: calc(100% + 25px);
@@ -2020,25 +1937,19 @@ in storage.js
.more-examples-toggle .hide-more {
margin-left: 25px;
- margin-bottom: 5px;
cursor: pointer;
}
.more-scraped-examples {
- margin-left: 5px;
- display: flex;
- flex-direction: row;
-}
-
-.more-scraped-examples-inner {
- /* 20px is width of toggle-line + toggle-line-inner */
- width: calc(100% - 20px);
+ margin-left: 25px;
+ position: relative;
}
.toggle-line {
- align-self: stretch;
- margin-right: 10px;
- margin-top: 5px;
+ position: absolute;
+ top: 5px;
+ bottom: 0;
+ right: calc(100% + 10px);
padding: 0 4px;
cursor: pointer;
}
@@ -2046,18 +1957,19 @@ in storage.js
.toggle-line-inner {
min-width: 2px;
height: 100%;
+ background: var(--scrape-example-toggle-line-background);
}
-.more-scraped-examples .scraped-example {
- margin-bottom: 20px;
+.toggle-line:hover .toggle-line-inner {
+ background: var(--scrape-example-toggle-line-hover-background);
}
-.more-scraped-examples .scraped-example:last-child {
- margin-bottom: 0;
+.more-scraped-examples .scraped-example, .example-links {
+ margin-top: 20px;
}
-.example-links a {
- margin-top: 20px;
+.more-scraped-examples .scraped-example:first-child {
+ margin-top: 5px;
}
.example-links ul {
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index 1f6fb961e..4e9803fe2 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -1,15 +1,10 @@
.setting-line {
- margin: 0.6em 0 0.6em 0.3em;
+ margin: 1.2em 0.6em;
position: relative;
}
-.setting-line .choices {
- display: flex;
- flex-wrap: wrap;
-}
-
.setting-line .radio-line input,
-.setting-line .toggle input {
+.setting-line .settings-toggle input {
margin-right: 0.3em;
height: 1.2rem;
width: 1.2rem;
@@ -22,27 +17,23 @@
.setting-line .radio-line input {
border-radius: 50%;
}
-.setting-line .toggle input:checked {
+.setting-line .settings-toggle input:checked {
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\
<path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\
<path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>');
}
.setting-line .radio-line input + span,
-.setting-line .toggle span {
+.setting-line .settings-toggle span {
padding-bottom: 1px;
}
-.radio-line .setting-name {
- width: 100%;
-}
-
.radio-line .choice {
margin-top: 0.1em;
margin-bottom: 0.1em;
min-width: 3.8em;
padding: 0.3em;
- display: flex;
+ display: inline-flex;
align-items: center;
cursor: pointer;
}
@@ -50,7 +41,7 @@
margin-left: 0.5em;
}
-.toggle {
+.settings-toggle {
position: relative;
width: 100%;
margin-right: 20px;
@@ -59,25 +50,15 @@
cursor: pointer;
}
-.setting-line > .sub-settings {
- padding-left: 42px;
- width: 100%;
- display: block;
-}
-
-#settings .setting-line {
- margin: 1.2em 0.6em;
-}
-
.setting-line .radio-line input:checked {
box-shadow: inset 0 0 0 3px var(--main-background-color);
background-color: var(--settings-input-color);
}
-.setting-line .toggle input:checked {
+.setting-line .settings-toggle input:checked {
background-color: var(--settings-input-color);
}
.setting-line .radio-line input:focus,
-.setting-line .toggle input:focus {
+.setting-line .settings-toggle input:focus {
box-shadow: 0 0 1px 1px var(--settings-input-color);
}
/* In here we combine both `:focus` and `:checked` properties. */
@@ -86,6 +67,6 @@
0 0 2px 2px var(--settings-input-color);
}
.setting-line .radio-line input:hover,
-.setting-line .toggle input:hover {
+.setting-line .settings-toggle input:hover {
border-color: var(--settings-input-color) !important;
}
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 0436fe013..979e7e0f9 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -45,6 +45,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
--search-color: #fff;
--search-results-alias-color: #c5c5c5;
--search-results-grey-color: #999;
+ --search-tab-title-count-color: #888;
--stab-background-color: #314559;
--stab-code-color: #e6e1cf;
--code-highlight-kw-color: #ff7733;
@@ -61,7 +62,6 @@ Original by Dempfi (https://github.com/dempfi/ayu)
--code-highlight-question-mark-color: #ff9011;
--code-highlight-comment-color: #788797;
--code-highlight-doc-comment-color: #a1ac88;
- --example-line-numbers-border-color: none;
--src-line-numbers-span-color: #5c6773;
--src-line-number-highlighted-background-color: rgba(255, 236, 164, 0.06);
--test-arrow-color: #788797;
@@ -88,6 +88,15 @@ Original by Dempfi (https://github.com/dempfi/ayu)
--source-sidebar-background-selected: #14191f;
--source-sidebar-background-hover: #14191f;
--table-alt-row-background-color: #191f26;
+ --codeblock-link-background: #333;
+ --scrape-example-toggle-line-background: #999;
+ --scrape-example-toggle-line-hover-background: #c5c5c5;
+ --scrape-example-code-line-highlight: rgb(91, 59, 1);
+ --scrape-example-code-line-highlight-focus: rgb(124, 75, 15);
+ --scrape-example-help-border-color: #aaa;
+ --scrape-example-help-color: #eee;
+ --scrape-example-help-hover-border-color: #fff;
+ --scrape-example-help-hover-color: #fff;
}
h1, h2, h3, h4 {
@@ -130,7 +139,7 @@ pre, .rustdoc.source .example-wrap {
.src-line-numbers .line-highlighted {
color: #708090;
- padding-right: 4px;
+ padding-right: 7px;
border-right: 1px solid #ffb44c;
}
@@ -150,55 +159,37 @@ pre, .rustdoc.source .example-wrap {
color: #c5c5c5;
}
-.content .item-info::before { color: #ccc; }
-
.sidebar h2 a,
.sidebar h3 a {
color: white;
}
-body.source .example-wrap pre.rust a {
- background: #333;
-}
-
-.module-item .stab,
-.import-item .stab {
- color: #000;
-}
.result-name .primitive > i, .result-name .keyword > i {
color: #788797;
}
-#titles > button.selected {
+#search-tabs > button.selected {
background-color: #141920 !important;
border-bottom: 1px solid #ffb44c !important;
border-top: none;
}
-#titles > button:not(.selected) {
+#search-tabs > button:not(.selected) {
background-color: transparent !important;
border: none;
}
-#titles > button:hover {
+#search-tabs > button:hover {
border-bottom: 1px solid rgba(242, 151, 24, 0.3);
}
-#titles > button > div.count {
- color: #888;
-}
-
/* rules that this theme does not need to set, here to satisfy the rule checker */
/* note that a lot of these are partially set in some way (meaning they are set
individually rather than as a group) */
/* FIXME: these rules should be at the bottom of the file but currently must be
above the `@media (max-width: 700px)` rules due to a bug in the css checker */
/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
-pre.rust .lifetime {}
-pre.rust .kw {}
-#titles > button:hover, #titles > button.selected {}
-pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val, pre.rust .attribute {}
-pre.rust .kw-2, pre.rust .prelude-ty {}
+#search-tabs > button:hover, #search-tabs > button.selected {}
#settings-menu > a img {
filter: invert(100);
@@ -213,29 +204,9 @@ pre.rust .kw-2, pre.rust .prelude-ty {}
color: #ffb44c;
}
-.scraped-example-list .scrape-help {
- border-color: #aaa;
- color: #eee;
-}
-.scraped-example-list .scrape-help:hover {
- border-color: white;
- color: white;
-}
-.scraped-example .example-wrap .rust span.highlight {
- background: rgb(91, 59, 1);
-}
-.scraped-example .example-wrap .rust span.highlight.focus {
- background: rgb(124, 75, 15);
-}
-.scraped-example:not(.expanded) .code-wrapper:before {
+.scraped-example:not(.expanded) .code-wrapper::before {
background: linear-gradient(to bottom, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0));
}
-.scraped-example:not(.expanded) .code-wrapper:after {
+.scraped-example:not(.expanded) .code-wrapper::after {
background: linear-gradient(to top, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0));
}
-.toggle-line-inner {
- background: #999;
-}
-.toggle-line:hover .toggle-line-inner {
- background: #c5c5c5;
-}
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index d945e956c..fb15863b0 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -40,6 +40,7 @@
--search-color: #111;
--search-results-alias-color: #fff;
--search-results-grey-color: #ccc;
+ --search-tab-title-count-color: #888;
--stab-background-color: #314559;
--stab-code-color: #e6e1cf;
--code-highlight-kw-color: #ab8ac1;
@@ -56,7 +57,6 @@
--code-highlight-question-mark-color: #ff9011;
--code-highlight-comment-color: #8d8d8b;
--code-highlight-doc-comment-color: #8ca375;
- --example-line-numbers-border-color: #4a4949;
--src-line-numbers-span-color: #3b91e2;
--src-line-number-highlighted-background-color: #0a042f;
--test-arrow-color: #dedede;
@@ -83,51 +83,30 @@
--source-sidebar-background-selected: #333;
--source-sidebar-background-hover: #444;
--table-alt-row-background-color: #2A2A2A;
+ --codeblock-link-background: #333;
+ --scrape-example-toggle-line-background: #999;
+ --scrape-example-toggle-line-hover-background: #c5c5c5;
+ --scrape-example-code-line-highlight: rgb(91, 59, 1);
+ --scrape-example-code-line-highlight-focus: rgb(124, 75, 15);
+ --scrape-example-help-border-color: #aaa;
+ --scrape-example-help-color: #eee;
+ --scrape-example-help-hover-border-color: #fff;
+ --scrape-example-help-hover-color: #fff;
}
-.content .item-info::before { color: #ccc; }
-
-body.source .example-wrap pre.rust a {
- background: #333;
-}
-
-#titles > button:not(.selected) {
+#search-tabs > button:not(.selected) {
background-color: #252525;
border-top-color: #252525;
}
-#titles > button:hover, #titles > button.selected {
+#search-tabs > button:hover, #search-tabs > button.selected {
border-top-color: #0089ff;
background-color: #353535;
}
-#titles > button > div.count {
- color: #888;
-}
-
-.scraped-example-list .scrape-help {
- border-color: #aaa;
- color: #eee;
-}
-.scraped-example-list .scrape-help:hover {
- border-color: white;
- color: white;
-}
-.scraped-example .example-wrap .rust span.highlight {
- background: rgb(91, 59, 1);
-}
-.scraped-example .example-wrap .rust span.highlight.focus {
- background: rgb(124, 75, 15);
-}
-.scraped-example:not(.expanded) .code-wrapper:before {
+.scraped-example:not(.expanded) .code-wrapper::before {
background: linear-gradient(to bottom, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0));
}
-.scraped-example:not(.expanded) .code-wrapper:after {
+.scraped-example:not(.expanded) .code-wrapper::after {
background: linear-gradient(to top, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0));
}
-.toggle-line-inner {
- background: #999;
-}
-.toggle-line:hover .toggle-line-inner {
- background: #c5c5c5;
-}
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 58955a793..053fa78d1 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -40,6 +40,7 @@
--search-color: #000;
--search-results-alias-color: #000;
--search-results-grey-color: #999;
+ --search-tab-title-count-color: #888;
--stab-background-color: #fff5d6;
--stab-code-color: #000;
--code-highlight-kw-color: #8959a8;
@@ -56,7 +57,6 @@
--code-highlight-question-mark-color: #ff9011;
--code-highlight-comment-color: #8e908c;
--code-highlight-doc-comment-color: #4d4d4c;
- --example-line-numbers-border-color: #c7c7c7;
--src-line-numbers-span-color: #c67e2d;
--src-line-number-highlighted-background-color: #fdffd3;
--test-arrow-color: #f5f5f5;
@@ -80,51 +80,30 @@
--source-sidebar-background-selected: #fff;
--source-sidebar-background-hover: #e0e0e0;
--table-alt-row-background-color: #F5F5F5;
+ --codeblock-link-background: #eee;
+ --scrape-example-toggle-line-background: #ccc;
+ --scrape-example-toggle-line-hover-background: #999;
+ --scrape-example-code-line-highlight: #fcffd6;
+ --scrape-example-code-line-highlight-focus: #f6fdb0;
+ --scrape-example-help-border-color: #555;
+ --scrape-example-help-color: #333;
+ --scrape-example-help-hover-border-color: #000;
+ --scrape-example-help-hover-color: #000;
}
-.content .item-info::before { color: #ccc; }
-
-body.source .example-wrap pre.rust a {
- background: #eee;
-}
-
-#titles > button:not(.selected) {
+#search-tabs > button:not(.selected) {
background-color: #e6e6e6;
border-top-color: #e6e6e6;
}
-#titles > button:hover, #titles > button.selected {
+#search-tabs > button:hover, #search-tabs > button.selected {
background-color: #ffffff;
border-top-color: #0089ff;
}
-#titles > button > div.count {
- color: #888;
-}
-
-.scraped-example-list .scrape-help {
- border-color: #555;
- color: #333;
-}
-.scraped-example-list .scrape-help:hover {
- border-color: black;
- color: black;
-}
-.scraped-example .example-wrap .rust span.highlight {
- background: #fcffd6;
-}
-.scraped-example .example-wrap .rust span.highlight.focus {
- background: #f6fdb0;
-}
-.scraped-example:not(.expanded) .code-wrapper:before {
+.scraped-example:not(.expanded) .code-wrapper::before {
background: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
}
-.scraped-example:not(.expanded) .code-wrapper:after {
+.scraped-example:not(.expanded) .code-wrapper::after {
background: linear-gradient(to top, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
}
-.toggle-line-inner {
- background: #ccc;
-}
-.toggle-line:hover .toggle-line-inner {
- background: #999;
-}
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 152116089..604ab147f 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -184,7 +184,6 @@ function browserSupportsHistoryApi() {
function loadCss(cssUrl) {
const link = document.createElement("link");
link.href = cssUrl;
- link.type = "text/css";
link.rel = "stylesheet";
document.getElementsByTagName("head")[0].appendChild(link);
}
@@ -391,7 +390,8 @@ function loadCss(cssUrl) {
}
if (document.activeElement.tagName === "INPUT" &&
- document.activeElement.type !== "checkbox") {
+ document.activeElement.type !== "checkbox" &&
+ document.activeElement.type !== "radio") {
switch (getVirtualKey(ev)) {
case "Escape":
handleEscape(ev);
@@ -527,7 +527,7 @@ function loadCss(cssUrl) {
}
let currentNbImpls = implementors.getElementsByClassName("impl").length;
- const traitName = document.querySelector("h1.fqn > .trait").textContent;
+ const traitName = document.querySelector(".main-heading h1 > .trait").textContent;
const baseIdName = "impl-" + traitName + "-";
const libs = Object.getOwnPropertyNames(imp);
// We don't want to include impls from this JS file, when the HTML already has them.
@@ -564,7 +564,7 @@ function loadCss(cssUrl) {
onEachLazy(code.getElementsByTagName("a"), elem => {
const href = elem.getAttribute("href");
- if (href && href.indexOf("http") !== 0) {
+ if (href && !/^(?:[a-z+]+:)?\/\//.test(href)) {
elem.setAttribute("href", window.rootPath + href);
}
});
@@ -621,7 +621,7 @@ function loadCss(cssUrl) {
function expandAllDocs() {
const innerToggle = document.getElementById(toggleAllDocsId);
removeClass(innerToggle, "will-expand");
- onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
+ onEachLazy(document.getElementsByClassName("toggle"), e => {
if (!hasClass(e, "type-contents-toggle") && !hasClass(e, "more-examples-toggle")) {
e.open = true;
}
@@ -633,7 +633,7 @@ function loadCss(cssUrl) {
function collapseAllDocs() {
const innerToggle = document.getElementById(toggleAllDocsId);
addClass(innerToggle, "will-expand");
- onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
+ onEachLazy(document.getElementsByClassName("toggle"), e => {
if (e.parentNode.id !== "implementations-list" ||
(!hasClass(e, "implementors-toggle") &&
!hasClass(e, "type-contents-toggle"))
@@ -681,7 +681,7 @@ function loadCss(cssUrl) {
setImplementorsTogglesOpen("blanket-implementations-list", false);
}
- onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
+ onEachLazy(document.getElementsByClassName("toggle"), e => {
if (!hideLargeItemContents && hasClass(e, "type-contents-toggle")) {
e.open = true;
}
@@ -804,29 +804,22 @@ function loadCss(cssUrl) {
}
});
- function handleClick(id, f) {
- const elem = document.getElementById(id);
- if (elem) {
- elem.addEventListener("click", f);
- }
+ const mainElem = document.getElementById(MAIN_ID);
+ if (mainElem) {
+ mainElem.addEventListener("click", hideSidebar);
}
- handleClick(MAIN_ID, () => {
- hideSidebar();
- });
- onEachLazy(document.getElementsByTagName("a"), el => {
+ onEachLazy(document.querySelectorAll("a[href^='#']"), el => {
// For clicks on internal links (<A> tags with a hash property), we expand the section we're
// jumping to *before* jumping there. We can't do this in onHashChange, because it changes
// the height of the document so we wind up scrolled to the wrong place.
- if (el.hash) {
- el.addEventListener("click", () => {
- expandSection(el.hash.slice(1));
- hideSidebar();
- });
- }
+ el.addEventListener("click", () => {
+ expandSection(el.hash.slice(1));
+ hideSidebar();
+ });
});
- onEachLazy(document.querySelectorAll(".rustdoc-toggle > summary:not(.hideme)"), el => {
+ onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"), el => {
el.addEventListener("click", e => {
if (e.target.tagName !== "SUMMARY" && e.target.tagName !== "A") {
e.preventDefault();
@@ -850,7 +843,7 @@ function loadCss(cssUrl) {
window.hideAllModals(false);
const ty = e.getAttribute("data-ty");
const wrapper = document.createElement("div");
- wrapper.innerHTML = "<div class=\"docblock\">" + window.NOTABLE_TRAITS[ty] + "</div>";
+ wrapper.innerHTML = "<div class=\"content\">" + window.NOTABLE_TRAITS[ty] + "</div>";
wrapper.className = "notable popover";
const focusCatcher = document.createElement("div");
focusCatcher.setAttribute("tabindex", "0");
@@ -948,7 +941,7 @@ function loadCss(cssUrl) {
return;
}
if (!this.NOTABLE_FORCE_VISIBLE &&
- !elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT)) {
+ !elemIsInParent(ev.relatedTarget, window.CURRENT_NOTABLE_ELEMENT)) {
hideNotable(true);
}
};
@@ -1043,9 +1036,6 @@ function loadCss(cssUrl) {
help_button.appendChild(container);
container.onblur = helpBlurHandler;
- container.onclick = event => {
- event.preventDefault();
- };
help_button.onblur = helpBlurHandler;
help_button.children[0].onblur = helpBlurHandler;
}
@@ -1093,6 +1083,9 @@ function loadCss(cssUrl) {
* Show the help popup menu.
*/
function showHelp() {
+ // Prevent `blur` events from being dispatched as a result of closing
+ // other modals.
+ getHelpButton().querySelector("a").focus();
const menu = getHelpMenu(true);
if (menu.style.display === "none") {
window.hideAllModals();
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 23ae4e970..88592fa0c 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -49,7 +49,7 @@ function printTab(nb) {
let iter = 0;
let foundCurrentTab = false;
let foundCurrentResultSet = false;
- onEachLazy(document.getElementById("titles").childNodes, elem => {
+ onEachLazy(document.getElementById("search-tabs").childNodes, elem => {
if (nb === iter) {
addClass(elem, "selected");
foundCurrentTab = true;
@@ -781,7 +781,29 @@ function initSearch(rawSearchIndex) {
return a - b;
}
- // Sort by non levenshtein results and then levenshtein results by the distance
+ // sort by index of keyword in item name (no literal occurrence goes later)
+ a = (aaa.index < 0);
+ b = (bbb.index < 0);
+ if (a !== b) {
+ return a - b;
+ }
+
+ // Sort by distance in the path part, if specified
+ // (less changes required to match means higher rankings)
+ a = aaa.path_lev;
+ b = bbb.path_lev;
+ if (a !== b) {
+ return a - b;
+ }
+
+ // (later literal occurrence, if any, goes later)
+ a = aaa.index;
+ b = bbb.index;
+ if (a !== b) {
+ return a - b;
+ }
+
+ // Sort by distance in the name part, the last part of the path
// (less changes required to match means higher rankings)
a = (aaa.lev);
b = (bbb.lev);
@@ -810,19 +832,6 @@ function initSearch(rawSearchIndex) {
return (a > b ? +1 : -1);
}
- // sort by index of keyword in item name (no literal occurrence goes later)
- a = (aaa.index < 0);
- b = (bbb.index < 0);
- if (a !== b) {
- return a - b;
- }
- // (later literal occurrence, if any, goes later)
- a = aaa.index;
- b = bbb.index;
- if (a !== b) {
- return a - b;
- }
-
// special precedence for primitive and keyword pages
if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
(aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
@@ -1230,15 +1239,19 @@ function initSearch(rawSearchIndex) {
* * `id` is the index in both `searchWords` and `searchIndex` arrays for this element.
* * `index` is an `integer`` used to sort by the position of the word in the item's name.
* * `lev` is the main metric used to sort the search results.
+ * * `path_lev` is zero if a single-component search query is used, otherwise it's the
+ * distance computed for everything other than the last path component.
*
* @param {Results} results
* @param {string} fullId
* @param {integer} id
* @param {integer} index
* @param {integer} lev
+ * @param {integer} path_lev
*/
- function addIntoResults(results, fullId, id, index, lev) {
- if (lev === 0 || (!parsedQuery.literalSearch && lev <= MAX_LEV_DISTANCE)) {
+ function addIntoResults(results, fullId, id, index, lev, path_lev) {
+ const inBounds = lev <= MAX_LEV_DISTANCE || index !== -1;
+ if (lev === 0 || (!parsedQuery.literalSearch && inBounds)) {
if (results[fullId] !== undefined) {
const result = results[fullId];
if (result.dontValidate || result.lev <= lev) {
@@ -1250,6 +1263,7 @@ function initSearch(rawSearchIndex) {
index: index,
dontValidate: parsedQuery.literalSearch,
lev: lev,
+ path_lev: path_lev,
};
}
}
@@ -1280,68 +1294,68 @@ function initSearch(rawSearchIndex) {
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
return;
}
- let lev, lev_add = 0, index = -1;
+ let lev, index = -1, path_lev = 0;
const fullId = row.id;
+ const searchWord = searchWords[pos];
const in_args = findArg(row, elem, parsedQuery.typeFilter);
const returned = checkReturned(row, elem, parsedQuery.typeFilter);
- addIntoResults(results_in_args, fullId, pos, index, in_args);
- addIntoResults(results_returned, fullId, pos, index, returned);
+ // path_lev is 0 because no parent path information is currently stored
+ // in the search index
+ addIntoResults(results_in_args, fullId, pos, -1, in_args, 0);
+ addIntoResults(results_returned, fullId, pos, -1, returned, 0);
if (!typePassesFilter(parsedQuery.typeFilter, row.ty)) {
return;
}
- const searchWord = searchWords[pos];
- if (parsedQuery.literalSearch) {
- if (searchWord === elem.name) {
- addIntoResults(results_others, fullId, pos, -1, 0);
- }
- return;
+ const row_index = row.normalizedName.indexOf(elem.pathLast);
+ const word_index = searchWord.indexOf(elem.pathLast);
+
+ // lower indexes are "better" matches
+ // rank based on the "best" match
+ if (row_index === -1) {
+ index = word_index;
+ } else if (word_index === -1) {
+ index = row_index;
+ } else if (word_index < row_index) {
+ index = word_index;
+ } else {
+ index = row_index;
}
// No need to check anything else if it's a "pure" generics search.
if (elem.name.length === 0) {
if (row.type !== null) {
lev = checkGenerics(row.type, elem, MAX_LEV_DISTANCE + 1);
- addIntoResults(results_others, fullId, pos, index, lev);
+ // path_lev is 0 because we know it's empty
+ addIntoResults(results_others, fullId, pos, index, lev, 0);
}
return;
}
if (elem.fullPath.length > 1) {
- lev = checkPath(elem.pathWithoutLast, row);
- if (lev > MAX_LEV_DISTANCE || (parsedQuery.literalSearch && lev !== 0)) {
+ path_lev = checkPath(elem.pathWithoutLast, row);
+ if (path_lev > MAX_LEV_DISTANCE) {
return;
- } else if (lev > 0) {
- lev_add = lev / 10;
}
}
- if (searchWord.indexOf(elem.pathLast) > -1 ||
- row.normalizedName.indexOf(elem.pathLast) > -1
- ) {
- index = row.normalizedName.indexOf(elem.pathLast);
- }
- lev = levenshtein(searchWord, elem.pathLast);
- if (lev > 0 && elem.pathLast.length > 2 && searchWord.indexOf(elem.pathLast) > -1) {
- if (elem.pathLast.length < 6) {
- lev = 1;
- } else {
- lev = 0;
+ if (parsedQuery.literalSearch) {
+ if (searchWord === elem.name) {
+ addIntoResults(results_others, fullId, pos, index, 0, path_lev);
}
- }
- lev += lev_add;
- if (lev > MAX_LEV_DISTANCE) {
return;
- } else if (index !== -1 && elem.fullPath.length < 2) {
- lev -= 1;
}
- if (lev < 0) {
- lev = 0;
+
+ lev = levenshtein(searchWord, elem.pathLast);
+
+ if (index === -1 && lev + path_lev > MAX_LEV_DISTANCE) {
+ return;
}
- addIntoResults(results_others, fullId, pos, index, lev);
+
+ addIntoResults(results_others, fullId, pos, index, lev, path_lev);
}
/**
@@ -1386,7 +1400,7 @@ function initSearch(rawSearchIndex) {
return;
}
const lev = Math.round(totalLev / nbLev);
- addIntoResults(results, row.id, pos, 0, lev);
+ addIntoResults(results, row.id, pos, 0, lev, 0);
}
function innerRunQuery() {
@@ -1490,7 +1504,7 @@ function initSearch(rawSearchIndex) {
function focusSearchResult() {
const target = searchState.focusedByTab[searchState.currentTab] ||
document.querySelectorAll(".search-results.active a").item(0) ||
- document.querySelectorAll("#titles > button").item(searchState.currentTab);
+ document.querySelectorAll("#search-tabs button").item(searchState.currentTab);
searchState.focusedByTab[searchState.currentTab] = null;
if (target) {
target.focus();
@@ -1645,9 +1659,9 @@ function initSearch(rawSearchIndex) {
function makeTabHeader(tabNb, text, nbElems) {
if (searchState.currentTab === tabNb) {
return "<button class=\"selected\">" + text +
- " <div class=\"count\">(" + nbElems + ")</div></button>";
+ " <span class=\"count\">(" + nbElems + ")</span></button>";
}
- return "<button>" + text + " <div class=\"count\">(" + nbElems + ")</div></button>";
+ return "<button>" + text + " <span class=\"count\">(" + nbElems + ")</span></button>";
}
/**
@@ -1712,12 +1726,12 @@ function initSearch(rawSearchIndex) {
let output = `<h1 class="search-results-title">Results${crates}</h1>`;
if (results.query.error !== null) {
output += `<h3>Query parser error: "${results.query.error}".</h3>`;
- output += "<div id=\"titles\">" +
+ output += "<div id=\"search-tabs\">" +
makeTabHeader(0, "In Names", ret_others[1]) +
"</div>";
currentTab = 0;
} else if (results.query.foundElems <= 1 && results.query.returned.length === 0) {
- output += "<div id=\"titles\">" +
+ output += "<div id=\"search-tabs\">" +
makeTabHeader(0, "In Names", ret_others[1]) +
makeTabHeader(1, "In Parameters", ret_in_args[1]) +
makeTabHeader(2, "In Return Types", ret_returned[1]) +
@@ -1727,7 +1741,7 @@ function initSearch(rawSearchIndex) {
results.query.elems.length === 0 ? "In Function Return Types" :
results.query.returned.length === 0 ? "In Function Parameters" :
"In Function Signatures";
- output += "<div id=\"titles\">" +
+ output += "<div id=\"search-tabs\">" +
makeTabHeader(0, signatureTabTitle, ret_others[1]) +
"</div>";
currentTab = 0;
@@ -1747,7 +1761,7 @@ function initSearch(rawSearchIndex) {
search.appendChild(resultsElem);
// Reset focused elements.
searchState.showResults(search);
- const elems = document.getElementById("titles").childNodes;
+ const elems = document.getElementById("search-tabs").childNodes;
searchState.focusedByTab = [];
let i = 0;
for (const elem of elems) {
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 589bfc793..84df1b7d3 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -135,7 +135,7 @@
// This is a select setting.
output += `\
<div class="radio-line" id="${js_data_name}">
- <span class="setting-name">${setting_name}</span>
+ <div class="setting-name">${setting_name}</div>
<div class="choices">`;
onEach(setting["options"], option => {
const checked = option === setting["default"] ? " checked" : "";
@@ -150,10 +150,10 @@
});
output += "</div></div>";
} else {
- // This is a toggle.
+ // This is a checkbox toggle.
const checked = setting["default"] === true ? " checked" : "";
output += `\
-<label class="toggle">\
+<label class="settings-toggle">\
<input type="checkbox" id="${js_data_name}"${checked}>\
<span class="label">${setting_name}</span>\
</label>`;
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 5db768c1c..0e1c864e6 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -83,7 +83,7 @@ function toggleSidebar() {
function createSidebarToggle() {
const sidebarToggle = document.createElement("div");
- sidebarToggle.id = "sidebar-toggle";
+ sidebarToggle.id = "src-sidebar-toggle";
const inner = document.createElement("button");
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index aa3bf827d..fddda293b 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -72,34 +72,30 @@
{%- if page.css_class != "source" -%}
<nav class="mobile-topbar"> {#- -#}
<button class="sidebar-menu-toggle">&#9776;</button> {#- -#}
- <a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
- <div class="logo-container"> {#- -#}
- {%- if !layout.logo.is_empty() -%}
- <img src="{{layout.logo}}" alt="logo"> {#- -#}
- {%- else -%}
- <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
- {%- endif -%}
- </div> {#- -#}
+ <a class="logo-container" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
+ {%- if !layout.logo.is_empty() -%}
+ <img src="{{layout.logo}}" alt="logo"> {#- -#}
+ {%- else -%}
+ <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
+ {%- endif -%}
</a> {#- -#}
<h2></h2> {#- -#}
</nav> {#- -#}
{%- endif -%}
<nav class="sidebar"> {#- -#}
{%- if page.css_class != "source" -%}
- <a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
- <div class="logo-container"> {#- -#}
- {%- if !layout.logo.is_empty() %}
- <img src="{{layout.logo}}" alt="logo"> {#- -#}
- {%- else -%}
- <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
- {%- endif -%}
- </div> {#- -#}
+ <a class="logo-container" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
+ {%- if !layout.logo.is_empty() %}
+ <img src="{{layout.logo}}" alt="logo"> {#- -#}
+ {%- else -%}
+ <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
+ {%- endif -%}
</a> {#- -#}
{%- endif -%}
{{- sidebar|safe -}}
</nav> {#- -#}
<main> {#- -#}
- <div class="width-limiter"> {#- -#}
+ {%- if page.css_class != "source" -%}<div class="width-limiter">{%- endif -%}
<nav class="sub"> {#- -#}
{%- if page.css_class == "source" -%}
<a class="sub-logo-container" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
@@ -132,7 +128,7 @@
</form> {#- -#}
</nav> {#- -#}
<section id="main-content" class="content">{{- content|safe -}}</section> {#- -#}
- </div> {#- -#}
+ {%- if page.css_class != "source" -%}</div>{%- endif -%}
</main> {#- -#}
{{- layout.external_html.after_content|safe -}}
<div id="rustdoc-vars" {# -#}
diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html
index 611d124d4..ee2880bf6 100644
--- a/src/librustdoc/html/templates/print_item.html
+++ b/src/librustdoc/html/templates/print_item.html
@@ -1,5 +1,5 @@
<div class="main-heading"> {#- -#}
- <h1 class="fqn"> {#- -#}
+ <h1> {#- -#}
{{-typ-}}
{#- The breadcrumbs of the item path, like std::string -#}
{%- for component in path_components -%}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index d7184053c..bd95ec186 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -8,8 +8,9 @@ use std::convert::From;
use std::fmt;
use rustc_ast::ast;
-use rustc_hir::{def::CtorKind, def_id::DefId};
+use rustc_hir::{def::CtorKind, def::DefKind, def_id::DefId};
use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::symbol::sym;
use rustc_span::{Pos, Symbol};
use rustc_target::spec::abi::Abi as RustcAbi;
@@ -217,13 +218,27 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
impl<'a> fmt::Display for DisplayDefId<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let name = match self.2 {
+ let DisplayDefId(def_id, tcx, name) = self;
+ let name = match name {
Some(name) => format!(":{}", name.as_u32()),
- None => self
- .1
- .opt_item_name(self.0)
- .map(|n| format!(":{}", n.as_u32()))
- .unwrap_or_default(),
+ None => {
+ // We need this workaround because primitive types' DefId actually refers to
+ // their parent module, which isn't present in the output JSON items. So
+ // instead, we directly get the primitive symbol and convert it to u32 to
+ // generate the ID.
+ if matches!(tcx.def_kind(def_id), DefKind::Mod) &&
+ let Some(prim) = tcx.get_attrs(*def_id, sym::doc)
+ .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
+ .filter(|attr| attr.has_name(sym::primitive))
+ .find_map(|attr| attr.value_str()) {
+ format!(":{}", prim.as_u32())
+ } else {
+ tcx
+ .opt_item_name(*def_id)
+ .map(|n| format!(":{}", n.as_u32()))
+ .unwrap_or_default()
+ }
+ }
};
write!(f, "{}:{}{}", self.0.krate.as_u32(), u32::from(self.0.index), name)
}
@@ -237,7 +252,6 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
ItemId::Auto { for_, trait_ } => {
Id(format!("a:{}-{}", DisplayDefId(trait_, tcx, None), DisplayDefId(for_, tcx, name)))
}
- ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())),
}
}
@@ -646,15 +660,20 @@ impl FromWithTcx<clean::Enum> for Enum {
impl FromWithTcx<clean::Variant> for Variant {
fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
- use clean::Variant::*;
- match variant {
- CLike(disr) => Variant::Plain(disr.map(|disr| disr.into_tcx(tcx))),
- Tuple(fields) => Variant::Tuple(ids_keeping_stripped(fields, tcx)),
- Struct(s) => Variant::Struct {
+ use clean::VariantKind::*;
+
+ let discriminant = variant.discriminant.map(|d| d.into_tcx(tcx));
+
+ let kind = match variant.kind {
+ CLike => VariantKind::Plain,
+ Tuple(fields) => VariantKind::Tuple(ids_keeping_stripped(fields, tcx)),
+ Struct(s) => VariantKind::Struct {
fields_stripped: s.has_stripped_entries(),
fields: ids(s.fields, tcx),
},
- }
+ };
+
+ Variant { kind, discriminant }
}
}
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index ef1d7da5a..86454e1f2 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -772,7 +772,6 @@ fn main_args(at_args: &[String]) -> MainResult {
let crate_version = options.crate_version.clone();
let output_format = options.output_format;
- let externs = options.externs.clone();
let scrape_examples_options = options.scrape_examples_options.clone();
let bin_crate = options.bin_crate;
@@ -800,13 +799,12 @@ fn main_args(at_args: &[String]) -> MainResult {
// FIXME(#83761): Resolver cloning can lead to inconsistencies between data in the
// two copies because one of the copies can be modified after `TyCtxt` construction.
let (resolver, resolver_caches) = {
- let (krate, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek();
+ let expansion = abort_on_err(queries.expansion(), sess);
+ let (krate, resolver, _) = &*expansion.borrow();
let resolver_caches = resolver.borrow_mut().access(|resolver| {
collect_intra_doc_links::early_resolve_intra_doc_links(
resolver,
- sess,
krate,
- externs,
render_options.document_private,
)
});
@@ -817,7 +815,7 @@ fn main_args(at_args: &[String]) -> MainResult {
sess.fatal("Compilation failed, aborting rustdoc");
}
- let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).peek_mut();
+ let global_ctxt = abort_on_err(queries.global_ctxt(), sess);
global_ctxt.enter(|tcx| {
let (krate, render_opts, mut cache) = sess.time("run_global_ctxt", || {
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 044e05144..5f4ad6d2a 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -53,7 +53,7 @@ pub(crate) fn render<P: AsRef<Path>>(
let mut css = String::new();
for name in &options.markdown_css {
- write!(css, r#"<link rel="stylesheet" type="text/css" href="{name}">"#)
+ write!(css, r#"<link rel="stylesheet" href="{name}">"#)
.expect("Writing to a String can't fail");
}
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 057d2fdd9..6aa2dda98 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -82,7 +82,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.item_id.expect_def_id().expect_local());
// check if parent is trait impl
- if let Some(parent_hir_id) = cx.tcx.hir().find_parent_node(hir_id) {
+ if let Some(parent_hir_id) = cx.tcx.hir().opt_parent_id(hir_id) {
if let Some(parent_node) = cx.tcx.hir().find(parent_hir_id) {
if matches!(
parent_node,
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 37a28b6b7..075951312 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -538,11 +538,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) | ty::Foreign(did) => {
Res::from_def_id(self.cx.tcx, did)
}
- ty::Projection(_)
+ ty::Alias(..)
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(_)
- | ty::Opaque(..)
| ty::Dynamic(..)
| ty::Param(_)
| ty::Bound(..)
@@ -787,7 +786,7 @@ fn trait_impls_for<'a>(
tcx.find_map_relevant_impl(trait_, ty, |impl_| {
let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
// Check if these are the same type.
- let impl_type = trait_ref.self_ty();
+ let impl_type = trait_ref.skip_binder().self_ty();
trace!(
"comparing type {} with kind {:?} against type {:?}",
impl_type,
diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs
index 1b373cfe5..42677bd84 100644
--- a/src/librustdoc/passes/collect_intra_doc_links/early.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs
@@ -12,8 +12,6 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, CRATE_DEF_ID};
use rustc_hir::TraitCandidate;
use rustc_middle::ty::{DefIdTree, Visibility};
use rustc_resolve::{ParentScope, Resolver};
-use rustc_session::config::Externs;
-use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::{Symbol, SyntaxContext};
@@ -22,16 +20,13 @@ use std::mem;
pub(crate) fn early_resolve_intra_doc_links(
resolver: &mut Resolver<'_>,
- sess: &Session,
krate: &ast::Crate,
- externs: Externs,
document_private_items: bool,
) -> ResolverCaches {
let parent_scope =
ParentScope::module(resolver.expect_module(CRATE_DEF_ID.to_def_id()), resolver);
let mut link_resolver = EarlyDocLinkResolver {
resolver,
- sess,
parent_scope,
visited_mods: Default::default(),
markdown_links: Default::default(),
@@ -52,7 +47,9 @@ pub(crate) fn early_resolve_intra_doc_links(
// the known necessary crates. Load them all unconditionally until we find a way to fix this.
// DO NOT REMOVE THIS without first testing on the reproducer in
// https://github.com/jyn514/objr/commit/edcee7b8124abf0e4c63873e8422ff81beb11ebb
- for (extern_name, _) in externs.iter().filter(|(_, entry)| entry.add_prelude) {
+ for (extern_name, _) in
+ link_resolver.resolver.sess().opts.externs.iter().filter(|(_, entry)| entry.add_prelude)
+ {
link_resolver.resolver.resolve_rustdoc_path(extern_name, TypeNS, parent_scope);
}
@@ -73,7 +70,6 @@ fn doc_attrs<'a>(attrs: impl Iterator<Item = &'a ast::Attribute>) -> Attributes
struct EarlyDocLinkResolver<'r, 'ra> {
resolver: &'r mut Resolver<'ra>,
- sess: &'r Session,
parent_scope: ParentScope<'ra>,
visited_mods: DefIdSet,
markdown_links: FxHashMap<String, Vec<PreprocessedMarkdownLink>>,
@@ -166,7 +162,7 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
fn resolve_doc_links_extern_impl(&mut self, def_id: DefId, is_inherent: bool) {
self.resolve_doc_links_extern_outer_fixme(def_id, def_id);
let assoc_item_def_ids = Vec::from_iter(
- self.resolver.cstore().associated_item_def_ids_untracked(def_id, self.sess),
+ self.resolver.cstore().associated_item_def_ids_untracked(def_id, self.resolver.sess()),
);
for assoc_def_id in assoc_item_def_ids {
if !is_inherent || self.resolver.cstore().visibility_untracked(assoc_def_id).is_public()
@@ -191,7 +187,9 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
return;
}
- let attrs = Vec::from_iter(self.resolver.cstore().item_attrs_untracked(def_id, self.sess));
+ let attrs = Vec::from_iter(
+ self.resolver.cstore().item_attrs_untracked(def_id, self.resolver.sess()),
+ );
let parent_scope = ParentScope::module(
self.resolver.get_nearest_non_block_module(
self.resolver.opt_parent(scope_id).unwrap_or(scope_id),
@@ -205,7 +203,9 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
return;
}
- let attrs = Vec::from_iter(self.resolver.cstore().item_attrs_untracked(def_id, self.sess));
+ let attrs = Vec::from_iter(
+ self.resolver.cstore().item_attrs_untracked(def_id, self.resolver.sess()),
+ );
let parent_scope = ParentScope::module(self.resolver.expect_module(def_id), self.resolver);
self.resolve_doc_links(doc_attrs(attrs.iter()), parent_scope);
}
@@ -321,7 +321,7 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
let field_def_ids = Vec::from_iter(
self.resolver
.cstore()
- .associated_item_def_ids_untracked(def_id, self.sess),
+ .associated_item_def_ids_untracked(def_id, self.resolver.sess()),
);
for field_def_id in field_def_ids {
self.resolve_doc_links_extern_outer(field_def_id, scope_id);
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index d57f981d5..79db3c6c3 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -19,6 +19,12 @@ pub(crate) const COLLECT_TRAIT_IMPLS: Pass = Pass {
};
pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate {
+ // We need to check if there are errors before running this pass because it would crash when
+ // we try to get auto and blanket implementations.
+ if cx.tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
+ return krate;
+ }
+
let synth_impls = cx.sess().time("collect_synthetic_impls", || {
let mut synth = SyntheticImplCollector { cx, impls: Vec::new() };
synth.visit_crate(&krate);
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index 5aa4f238b..7158355ff 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -156,7 +156,9 @@ impl Emitter for BufferEmitter {
let mut buffer = self.buffer.borrow_mut();
let fluent_args = to_fluent_args(diag.args());
- let translated_main_message = self.translate_message(&diag.message[0].0, &fluent_args);
+ let translated_main_message = self
+ .translate_message(&diag.message[0].0, &fluent_args)
+ .unwrap_or_else(|e| panic!("{e}"));
buffer.messages.push(format!("error from rustc: {}", translated_main_message));
if diag.is_error() {
diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs
index 3bac5a8e5..4c992e948 100644
--- a/src/librustdoc/passes/strip_priv_imports.rs
+++ b/src/librustdoc/passes/strip_priv_imports.rs
@@ -12,5 +12,6 @@ pub(crate) const STRIP_PRIV_IMPORTS: Pass = Pass {
};
pub(crate) fn strip_priv_imports(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
- ImportStripper { tcx: cx.tcx }.fold_crate(krate)
+ let is_json_output = cx.output_format.is_json() && !cx.show_coverage;
+ ImportStripper { tcx: cx.tcx, is_json_output }.fold_crate(krate)
}
diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs
index 8fc42462d..bb6dccb7c 100644
--- a/src/librustdoc/passes/strip_private.rs
+++ b/src/librustdoc/passes/strip_private.rs
@@ -28,7 +28,8 @@ pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) ->
is_json_output,
tcx: cx.tcx,
};
- krate = ImportStripper { tcx: cx.tcx }.fold_crate(stripper.fold_crate(krate));
+ krate =
+ ImportStripper { tcx: cx.tcx, is_json_output }.fold_crate(stripper.fold_crate(krate));
}
// strip all impls referencing private items
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index 995fb5dcc..048ed2646 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -97,17 +97,7 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
}
// handled in the `strip-priv-imports` pass
- clean::ExternCrateItem { .. } => {}
- clean::ImportItem(ref imp) => {
- // Because json doesn't inline imports from private modules, we need to mark
- // the imported item as retained so it's impls won't be stripped.
- //
- // FIXME: Is it necessary to check for json output here: See
- // https://github.com/rust-lang/rust/pull/100325#discussion_r941495215
- if let Some(did) = imp.source.did && self.is_json_output {
- self.retained.insert(did.into());
- }
- }
+ clean::ExternCrateItem { .. } | clean::ImportItem(_) => {}
clean::ImplItem(..) => {}
@@ -132,7 +122,10 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
// implementations of traits are always public.
clean::ImplItem(ref imp) if imp.trait_.is_some() => true,
// Variant fields have inherited visibility
- clean::VariantItem(clean::Variant::Struct(..) | clean::Variant::Tuple(..)) => true,
+ clean::VariantItem(clean::Variant {
+ kind: clean::VariantKind::Struct(..) | clean::VariantKind::Tuple(..),
+ ..
+ }) => true,
_ => false,
};
@@ -240,11 +233,25 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
/// This stripper discards all private import statements (`use`, `extern crate`)
pub(crate) struct ImportStripper<'tcx> {
pub(crate) tcx: TyCtxt<'tcx>,
+ pub(crate) is_json_output: bool,
+}
+
+impl<'tcx> ImportStripper<'tcx> {
+ fn import_should_be_hidden(&self, i: &Item, imp: &clean::Import) -> bool {
+ if self.is_json_output {
+ // FIXME: This should be handled the same way as for HTML output.
+ imp.imported_item_is_doc_hidden(self.tcx)
+ } else {
+ i.attrs.lists(sym::doc).has_word(sym::hidden)
+ }
+ }
}
impl<'tcx> DocFolder for ImportStripper<'tcx> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
match *i.kind {
+ clean::ImportItem(imp) if self.import_should_be_hidden(&i, &imp) => None,
+ clean::ImportItem(_) if i.attrs.lists(sym::doc).has_word(sym::hidden) => None,
clean::ExternCrateItem { .. } | clean::ImportItem(..)
if i.visibility(self.tcx) != Some(Visibility::Public) =>
{
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
index d29ceead4..390b94361 100644
--- a/src/librustdoc/visit.rs
+++ b/src/librustdoc/visit.rs
@@ -17,10 +17,10 @@ pub(crate) trait DocVisitor: Sized {
EnumItem(i) => i.variants.iter().for_each(|x| self.visit_item(x)),
TraitItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
ImplItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
- VariantItem(i) => match i {
- Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)),
- Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)),
- Variant::CLike(_) => {}
+ VariantItem(i) => match &i.kind {
+ VariantKind::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)),
+ VariantKind::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)),
+ VariantKind::CLike => {}
},
ExternCrateItem { src: _ }
| ImportItem(_)