Auto merge of #101037 - GuillaumeGomez:rollup-opn6kj1, r=GuillaumeGomez
Rollup of 8 pull requests Successful merges: - #95005 (BTree: evaluate static type-related check at compile time) - #99742 (Add comments about stdout locking) - #100128 (Document that `RawWakerVTable` functions must be thread-safe.) - #100956 (Reduce right-side DOM size) - #101006 (Fix doc cfg on reexports) - #101012 (rustdoc: remove unused CSS for `.variants_table`) - #101023 (rustdoc: remove `type="text/css"` from stylesheet links) - #101031 (Remove unused build dependency) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
42fa8ac723
@ -1280,7 +1280,6 @@ name = "error_index_generator"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustdoc",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -318,7 +318,7 @@ impl<BorrowType: marker::BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type>
|
||||
pub fn ascend(
|
||||
self,
|
||||
) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> {
|
||||
assert!(BorrowType::PERMITS_TRAVERSAL);
|
||||
let _ = BorrowType::TRAVERSAL_PERMIT;
|
||||
// We need to use raw pointers to nodes because, if BorrowType is marker::ValMut,
|
||||
// there might be outstanding mutable references to values that we must not invalidate.
|
||||
let leaf_ptr: *const _ = Self::as_leaf_ptr(&self);
|
||||
@ -1003,7 +1003,7 @@ impl<BorrowType: marker::BorrowType, K, V>
|
||||
/// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should
|
||||
/// both, upon success, do nothing.
|
||||
pub fn descend(self) -> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
|
||||
assert!(BorrowType::PERMITS_TRAVERSAL);
|
||||
let _ = BorrowType::TRAVERSAL_PERMIT;
|
||||
// We need to use raw pointers to nodes because, if BorrowType is
|
||||
// marker::ValMut, there might be outstanding mutable references to
|
||||
// values that we must not invalidate. There's no worry accessing the
|
||||
@ -1666,15 +1666,17 @@ pub mod marker {
|
||||
pub struct ValMut<'a>(PhantomData<&'a mut ()>);
|
||||
|
||||
pub trait BorrowType {
|
||||
// Whether node references of this borrow type allow traversing
|
||||
// to other nodes in the tree.
|
||||
const PERMITS_TRAVERSAL: bool = true;
|
||||
// If node references of this borrow type allow traversing to other
|
||||
// nodes in the tree, this constant can be evaluated. Thus reading it
|
||||
// serves as a compile-time assertion.
|
||||
const TRAVERSAL_PERMIT: () = ();
|
||||
}
|
||||
impl BorrowType for Owned {
|
||||
// Traversal isn't needed, it happens using the result of `borrow_mut`.
|
||||
// Reject evaluation, because traversal isn't needed. Instead traversal
|
||||
// happens using the result of `borrow_mut`.
|
||||
// By disabling traversal, and only creating new references to roots,
|
||||
// we know that every reference of the `Owned` type is to a root node.
|
||||
const PERMITS_TRAVERSAL: bool = false;
|
||||
const TRAVERSAL_PERMIT: () = panic!();
|
||||
}
|
||||
impl BorrowType for Dying {}
|
||||
impl<'a> BorrowType for Immut<'a> {}
|
||||
|
@ -71,6 +71,12 @@ impl RawWaker {
|
||||
/// pointer of a properly constructed [`RawWaker`] object from inside the
|
||||
/// [`RawWaker`] implementation. Calling one of the contained functions using
|
||||
/// any other `data` pointer will cause undefined behavior.
|
||||
///
|
||||
/// These functions must all be thread-safe (even though [`RawWaker`] is
|
||||
/// <code>\![Send] + \![Sync]</code>)
|
||||
/// because [`Waker`] is <code>[Send] + [Sync]</code>, and thus wakers may be moved to
|
||||
/// arbitrary threads or invoked by `&` reference. For example, this means that if the
|
||||
/// `clone` and `drop` functions manage a reference count, they must do so atomically.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
#[derive(PartialEq, Copy, Clone, Debug)]
|
||||
pub struct RawWakerVTable {
|
||||
@ -110,6 +116,12 @@ impl RawWakerVTable {
|
||||
/// Creates a new `RawWakerVTable` from the provided `clone`, `wake`,
|
||||
/// `wake_by_ref`, and `drop` functions.
|
||||
///
|
||||
/// These functions must all be thread-safe (even though [`RawWaker`] is
|
||||
/// <code>\![Send] + \![Sync]</code>)
|
||||
/// because [`Waker`] is <code>[Send] + [Sync]</code>, and thus wakers may be moved to
|
||||
/// arbitrary threads or invoked by `&` reference. For example, this means that if the
|
||||
/// `clone` and `drop` functions manage a reference count, they must do so atomically.
|
||||
///
|
||||
/// # `clone`
|
||||
///
|
||||
/// This function will be called when the [`RawWaker`] gets cloned, e.g. when
|
||||
@ -157,9 +169,9 @@ impl RawWakerVTable {
|
||||
}
|
||||
}
|
||||
|
||||
/// The `Context` of an asynchronous task.
|
||||
/// The context of an asynchronous task.
|
||||
///
|
||||
/// Currently, `Context` only serves to provide access to a `&Waker`
|
||||
/// Currently, `Context` only serves to provide access to a [`&Waker`](Waker)
|
||||
/// which can be used to wake the current task.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub struct Context<'a> {
|
||||
@ -172,7 +184,7 @@ pub struct Context<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Context<'a> {
|
||||
/// Create a new `Context` from a `&Waker`.
|
||||
/// Create a new `Context` from a [`&Waker`](Waker).
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
@ -180,7 +192,7 @@ impl<'a> Context<'a> {
|
||||
Context { waker, _marker: PhantomData }
|
||||
}
|
||||
|
||||
/// Returns a reference to the `Waker` for the current task.
|
||||
/// Returns a reference to the [`Waker`] for the current task.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
@ -202,7 +214,18 @@ impl fmt::Debug for Context<'_> {
|
||||
/// This handle encapsulates a [`RawWaker`] instance, which defines the
|
||||
/// executor-specific wakeup behavior.
|
||||
///
|
||||
/// Implements [`Clone`], [`Send`], and [`Sync`].
|
||||
/// The typical life of a `Waker` is that it is constructed by an executor, wrapped in a
|
||||
/// [`Context`], then passed to [`Future::poll()`]. Then, if the future chooses to return
|
||||
/// [`Poll::Pending`], it must also store the waker somehow and call [`Waker::wake()`] when
|
||||
/// the future should be polled again.
|
||||
///
|
||||
/// Implements [`Clone`], [`Send`], and [`Sync`]; therefore, a waker may be invoked
|
||||
/// from any thread, including ones not in any way managed by the executor. For example,
|
||||
/// this might be done to wake a future when a blocking function call completes on another
|
||||
/// thread.
|
||||
///
|
||||
/// [`Future::poll()`]: core::future::Future::poll
|
||||
/// [`Poll::Pending`]: core::task::Poll::Pending
|
||||
#[repr(transparent)]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub struct Waker {
|
||||
@ -219,18 +242,21 @@ unsafe impl Sync for Waker {}
|
||||
impl Waker {
|
||||
/// Wake up the task associated with this `Waker`.
|
||||
///
|
||||
/// As long as the runtime keeps running and the task is not finished, it is
|
||||
/// guaranteed that each invocation of `wake` (or `wake_by_ref`) will be followed
|
||||
/// by at least one `poll` of the task to which this `Waker` belongs. This makes
|
||||
/// As long as the executor keeps running and the task is not finished, it is
|
||||
/// guaranteed that each invocation of [`wake()`](Self::wake) (or
|
||||
/// [`wake_by_ref()`](Self::wake_by_ref)) will be followed by at least one
|
||||
/// [`poll()`] of the task to which this `Waker` belongs. This makes
|
||||
/// it possible to temporarily yield to other tasks while running potentially
|
||||
/// unbounded processing loops.
|
||||
///
|
||||
/// Note that the above implies that multiple wake-ups may be coalesced into a
|
||||
/// single `poll` invocation by the runtime.
|
||||
/// single [`poll()`] invocation by the runtime.
|
||||
///
|
||||
/// Also note that yielding to competing tasks is not guaranteed: it is the
|
||||
/// executor’s choice which task to run and the executor may choose to run the
|
||||
/// current task again.
|
||||
///
|
||||
/// [`poll()`]: crate::future::Future::poll
|
||||
#[inline]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub fn wake(self) {
|
||||
@ -250,8 +276,8 @@ impl Waker {
|
||||
|
||||
/// Wake up the task associated with this `Waker` without consuming the `Waker`.
|
||||
///
|
||||
/// This is similar to `wake`, but may be slightly less efficient in the case
|
||||
/// where an owned `Waker` is available. This method should be preferred to
|
||||
/// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in
|
||||
/// the case where an owned `Waker` is available. This method should be preferred to
|
||||
/// calling `waker.clone().wake()`.
|
||||
#[inline]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
@ -263,7 +289,7 @@ impl Waker {
|
||||
unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) }
|
||||
}
|
||||
|
||||
/// Returns `true` if this `Waker` and another `Waker` have awoken the same task.
|
||||
/// Returns `true` if this `Waker` and another `Waker` would awake the same task.
|
||||
///
|
||||
/// This function works on a best-effort basis, and may return false even
|
||||
/// when the `Waker`s would awaken the same task. However, if this function
|
||||
|
@ -27,12 +27,23 @@ macro_rules! panic {
|
||||
/// necessary to use [`io::stdout().flush()`][flush] to ensure the output is emitted
|
||||
/// immediately.
|
||||
///
|
||||
/// The `print!` macro will lock the standard output on each call. If you call
|
||||
/// `print!` within a hot loop, this behavior may be the bottleneck of the loop.
|
||||
/// To avoid this, lock stdout with [`io::stdout().lock()`][lock]:
|
||||
/// ```
|
||||
/// use std::io::{stdout, Write};
|
||||
///
|
||||
/// let mut lock = stdout().lock();
|
||||
/// write!(lock, "hello world").unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// Use `print!` only for the primary output of your program. Use
|
||||
/// [`eprint!`] instead to print error and progress messages.
|
||||
///
|
||||
/// [flush]: crate::io::Write::flush
|
||||
/// [`println!`]: crate::println
|
||||
/// [`eprint!`]: crate::eprint
|
||||
/// [lock]: crate::io::Stdout
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@ -75,11 +86,22 @@ macro_rules! print {
|
||||
/// This macro uses the same syntax as [`format!`], but writes to the standard output instead.
|
||||
/// See [`std::fmt`] for more information.
|
||||
///
|
||||
/// The `println!` macro will lock the standard output on each call. If you call
|
||||
/// `println!` within a hot loop, this behavior may be the bottleneck of the loop.
|
||||
/// To avoid this, lock stdout with [`io::stdout().lock()`][lock]:
|
||||
/// ```
|
||||
/// use std::io::{stdout, Write};
|
||||
///
|
||||
/// let mut lock = stdout().lock();
|
||||
/// writeln!(lock, "hello world").unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// Use `println!` only for the primary output of your program. Use
|
||||
/// [`eprintln!`] instead to print error and progress messages.
|
||||
///
|
||||
/// [`std::fmt`]: crate::fmt
|
||||
/// [`eprintln!`]: crate::eprintln
|
||||
/// [lock]: crate::io::Stdout
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
|
@ -300,7 +300,7 @@ pub(crate) fn build_impls(
|
||||
}
|
||||
|
||||
/// `parent_module` refers to the parent of the re-export, not the original item
|
||||
fn merge_attrs(
|
||||
pub(crate) fn merge_attrs(
|
||||
cx: &mut DocContext<'_>,
|
||||
parent_module: Option<DefId>,
|
||||
old_attrs: Attrs<'_>,
|
||||
|
@ -482,7 +482,7 @@ impl Item {
|
||||
cx: &mut DocContext<'_>,
|
||||
cfg: Option<Arc<Cfg>>,
|
||||
) -> Item {
|
||||
trace!("name={:?}, def_id={:?}", name, def_id);
|
||||
trace!("name={:?}, def_id={:?} cfg={:?}", name, def_id, cfg);
|
||||
|
||||
// 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
|
||||
@ -801,6 +801,31 @@ impl ItemKind {
|
||||
| KeywordItem => [].iter(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this item does not appear inside an impl block.
|
||||
pub(crate) fn is_non_assoc(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
StructItem(_)
|
||||
| UnionItem(_)
|
||||
| EnumItem(_)
|
||||
| TraitItem(_)
|
||||
| ModuleItem(_)
|
||||
| ExternCrateItem { .. }
|
||||
| FunctionItem(_)
|
||||
| TypedefItem(_)
|
||||
| OpaqueTyItem(_)
|
||||
| StaticItem(_)
|
||||
| ConstantItem(_)
|
||||
| TraitAliasItem(_)
|
||||
| ForeignFunctionItem(_)
|
||||
| ForeignStaticItem(_)
|
||||
| ForeignTypeItem
|
||||
| MacroItem(_)
|
||||
| ProcMacroItem(_)
|
||||
| PrimitiveItem(_)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -191,12 +191,6 @@ impl StylePath {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_srclink(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) {
|
||||
if let Some(l) = cx.src_href(item) {
|
||||
write!(buf, "<a class=\"srclink\" href=\"{}\">source</a>", l)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Hash)]
|
||||
struct ItemEntry {
|
||||
url: String,
|
||||
@ -522,7 +516,14 @@ fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<Strin
|
||||
(cfg, _) => cfg.as_deref().cloned(),
|
||||
};
|
||||
|
||||
debug!("Portability {:?} - {:?} = {:?}", item.cfg, parent.and_then(|p| p.cfg.as_ref()), cfg);
|
||||
debug!(
|
||||
"Portability {:?} {:?} (parent: {:?}) - {:?} = {:?}",
|
||||
item.name,
|
||||
item.cfg,
|
||||
parent,
|
||||
parent.and_then(|p| p.cfg.as_ref()),
|
||||
cfg
|
||||
);
|
||||
|
||||
Some(format!("<div class=\"stab portability\">{}</div>", cfg?.render_long_html()))
|
||||
}
|
||||
@ -840,12 +841,13 @@ fn assoc_method(
|
||||
/// Note that it is possible for an unstable function to be const-stable. In that case, the span
|
||||
/// will include the const-stable version, but no stable version will be emitted, as a natural
|
||||
/// consequence of the above rules.
|
||||
fn render_stability_since_raw(
|
||||
fn render_stability_since_raw_with_extra(
|
||||
w: &mut Buffer,
|
||||
ver: Option<Symbol>,
|
||||
const_stability: Option<ConstStability>,
|
||||
containing_ver: Option<Symbol>,
|
||||
containing_const_ver: Option<Symbol>,
|
||||
extra_class: &str,
|
||||
) -> bool {
|
||||
let stable_version = ver.filter(|inner| !inner.is_empty() && Some(*inner) != containing_ver);
|
||||
|
||||
@ -893,12 +895,30 @@ fn render_stability_since_raw(
|
||||
}
|
||||
|
||||
if !stability.is_empty() {
|
||||
write!(w, r#"<span class="since" title="{}">{}</span>"#, title, stability);
|
||||
write!(w, r#"<span class="since{extra_class}" title="{title}">{stability}</span>"#);
|
||||
}
|
||||
|
||||
!stability.is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn render_stability_since_raw(
|
||||
w: &mut Buffer,
|
||||
ver: Option<Symbol>,
|
||||
const_stability: Option<ConstStability>,
|
||||
containing_ver: Option<Symbol>,
|
||||
containing_const_ver: Option<Symbol>,
|
||||
) -> bool {
|
||||
render_stability_since_raw_with_extra(
|
||||
w,
|
||||
ver,
|
||||
const_stability,
|
||||
containing_ver,
|
||||
containing_const_ver,
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
fn render_assoc_item(
|
||||
w: &mut Buffer,
|
||||
item: &clean::Item,
|
||||
@ -1681,23 +1701,29 @@ fn render_rightside(
|
||||
RenderMode::Normal => (item.const_stability(tcx), containing_item.const_stable_since(tcx)),
|
||||
RenderMode::ForDeref { .. } => (None, None),
|
||||
};
|
||||
let src_href = cx.src_href(item);
|
||||
let has_src_ref = src_href.is_some();
|
||||
|
||||
let mut rightside = Buffer::new();
|
||||
let has_stability = render_stability_since_raw(
|
||||
let has_stability = render_stability_since_raw_with_extra(
|
||||
&mut rightside,
|
||||
item.stable_since(tcx),
|
||||
const_stability,
|
||||
containing_item.stable_since(tcx),
|
||||
const_stable_since,
|
||||
if has_src_ref { "" } else { " rightside" },
|
||||
);
|
||||
let mut srclink = Buffer::empty_from(w);
|
||||
write_srclink(cx, item, &mut srclink);
|
||||
if has_stability && !srclink.is_empty() {
|
||||
rightside.write_str(" · ");
|
||||
if let Some(l) = src_href {
|
||||
if has_stability {
|
||||
write!(rightside, " · <a class=\"srclink\" href=\"{}\">source</a>", l)
|
||||
} else {
|
||||
write!(rightside, "<a class=\"srclink rightside\" href=\"{}\">source</a>", l)
|
||||
}
|
||||
}
|
||||
rightside.push_buffer(srclink);
|
||||
if !rightside.is_empty() {
|
||||
if has_stability && has_src_ref {
|
||||
write!(w, "<span class=\"rightside\">{}</span>", rightside.into_inner());
|
||||
} else {
|
||||
w.push_buffer(rightside);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ use std::rc::Rc;
|
||||
use super::{
|
||||
collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_section,
|
||||
notable_traits_decl, render_assoc_item, render_assoc_items, render_attributes_in_code,
|
||||
render_attributes_in_pre, render_impl, render_stability_since_raw, write_srclink,
|
||||
render_attributes_in_pre, render_impl, render_rightside, render_stability_since_raw,
|
||||
AssocItemLink, Context, ImplRenderingParameters,
|
||||
};
|
||||
use crate::clean;
|
||||
@ -477,7 +477,7 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) ->
|
||||
(cfg, _) => cfg.as_deref().cloned(),
|
||||
};
|
||||
|
||||
debug!("Portability {:?} - {:?} = {:?}", item.cfg, parent.cfg, cfg);
|
||||
debug!("Portability name={:?} {:?} - {:?} = {:?}", item.name, item.cfg, parent.cfg, cfg);
|
||||
if let Some(ref cfg) = cfg {
|
||||
tags += &tag_html("portability", &cfg.render_long_plain(), &cfg.render_short_html());
|
||||
}
|
||||
@ -709,14 +709,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
||||
write!(w, "<details class=\"rustdoc-toggle\" open><summary>");
|
||||
}
|
||||
write!(w, "<div id=\"{}\" class=\"method has-srclink\">", id);
|
||||
write!(w, "<div class=\"rightside\">");
|
||||
|
||||
let has_stability = render_stability_since(w, m, t, cx.tcx());
|
||||
if has_stability {
|
||||
w.write_str(" · ");
|
||||
}
|
||||
write_srclink(cx, m, w);
|
||||
write!(w, "</div>");
|
||||
render_rightside(w, cx, m, t, RenderMode::Normal);
|
||||
write!(w, "<h4 class=\"code-header\">");
|
||||
render_assoc_item(
|
||||
w,
|
||||
@ -1260,7 +1253,13 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
|
||||
w.write_str(")");
|
||||
}
|
||||
w.write_str("</code>");
|
||||
render_stability_since(w, variant, it, cx.tcx());
|
||||
render_stability_since_raw(
|
||||
w,
|
||||
variant.stable_since(cx.tcx()),
|
||||
variant.const_stability(cx.tcx()),
|
||||
it.stable_since(cx.tcx()),
|
||||
it.const_stable_since(cx.tcx()),
|
||||
);
|
||||
w.write_str("</h3>");
|
||||
|
||||
use crate::clean::Variant;
|
||||
@ -1591,21 +1590,6 @@ where
|
||||
w.write_str("</code></pre>");
|
||||
}
|
||||
|
||||
fn render_stability_since(
|
||||
w: &mut Buffer,
|
||||
item: &clean::Item,
|
||||
containing_item: &clean::Item,
|
||||
tcx: TyCtxt<'_>,
|
||||
) -> bool {
|
||||
render_stability_since_raw(
|
||||
w,
|
||||
item.stable_since(tcx),
|
||||
item.const_stability(tcx),
|
||||
containing_item.stable_since(tcx),
|
||||
containing_item.const_stable_since(tcx),
|
||||
)
|
||||
}
|
||||
|
||||
fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cx: &Context<'_>) -> Ordering {
|
||||
let lhss = format!("{}", lhs.inner_impl().print(false, cx));
|
||||
let rhss = format!("{}", rhs.inner_impl().print(false, cx));
|
||||
|
@ -1200,14 +1200,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
|
||||
float: right;
|
||||
}
|
||||
|
||||
.variants_table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.variants_table tbody tr td:first-child {
|
||||
width: 1%; /* make the variant name as small as possible */
|
||||
}
|
||||
|
||||
td.summary-column {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ details.rustdoc-toggle > summary::before {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.rightside,
|
||||
.rightside:not(a),
|
||||
.out-of-band {
|
||||
color: grey;
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ details.rustdoc-toggle > summary::before {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.rightside,
|
||||
.rightside:not(a),
|
||||
.out-of-band {
|
||||
color: grey;
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ details.rustdoc-toggle > summary::before {
|
||||
.stab { background: #FFF5D6; border-color: #FFC600; }
|
||||
.stab.portability > code { background: none; }
|
||||
|
||||
.rightside,
|
||||
.rightside:not(a),
|
||||
.out-of-band {
|
||||
color: grey;
|
||||
}
|
||||
|
@ -13,13 +13,13 @@
|
||||
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceCodePro-Regular.ttf.woff2"> {#- -#}
|
||||
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceSerif4-Bold.ttf.woff2"> {#- -#}
|
||||
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceCodePro-Semibold.ttf.woff2"> {#- -#}
|
||||
<link rel="stylesheet" type="text/css" {# -#}
|
||||
<link rel="stylesheet" {# -#}
|
||||
href="{{static_root_path|safe}}normalize{{page.resource_suffix}}.css"> {#- -#}
|
||||
<link rel="stylesheet" type="text/css" {# -#}
|
||||
<link rel="stylesheet" {# -#}
|
||||
href="{{static_root_path|safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
|
||||
id="mainThemeStyle"> {#- -#}
|
||||
{%- for theme in themes -%}
|
||||
<link rel="stylesheet" type="text/css" {# -#}
|
||||
<link rel="stylesheet" {# -#}
|
||||
href="{{static_root_path|safe}}{{theme}}{{page.resource_suffix}}.css" {# -#}
|
||||
{%- if theme == "light" -%}
|
||||
id="themeStyle"
|
||||
@ -51,7 +51,7 @@
|
||||
href="{{static_root_path|safe}}noscript{{page.resource_suffix}}.css"> {#- -#}
|
||||
</noscript> {#- -#}
|
||||
{%- if layout.css_file_extension.is_some() -%}
|
||||
<link rel="stylesheet" type="text/css" {# -#}
|
||||
<link rel="stylesheet" {# -#}
|
||||
href="{{static_root_path|safe}}theme{{page.resource_suffix}}.css"> {#- -#}
|
||||
{%- endif -%}
|
||||
{%- if !layout.favicon.is_empty() -%}
|
||||
|
@ -2,29 +2,53 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::clean::cfg::Cfg;
|
||||
use crate::clean::inline::{load_attrs, merge_attrs};
|
||||
use crate::clean::{Crate, Item};
|
||||
use crate::core::DocContext;
|
||||
use crate::fold::DocFolder;
|
||||
use crate::passes::Pass;
|
||||
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
|
||||
pub(crate) const PROPAGATE_DOC_CFG: Pass = Pass {
|
||||
name: "propagate-doc-cfg",
|
||||
run: propagate_doc_cfg,
|
||||
description: "propagates `#[doc(cfg(...))]` to child items",
|
||||
};
|
||||
|
||||
pub(crate) fn propagate_doc_cfg(cr: Crate, _: &mut DocContext<'_>) -> Crate {
|
||||
CfgPropagator { parent_cfg: None }.fold_crate(cr)
|
||||
pub(crate) fn propagate_doc_cfg(cr: Crate, cx: &mut DocContext<'_>) -> Crate {
|
||||
CfgPropagator { parent_cfg: None, parent: None, cx }.fold_crate(cr)
|
||||
}
|
||||
|
||||
struct CfgPropagator {
|
||||
struct CfgPropagator<'a, 'tcx> {
|
||||
parent_cfg: Option<Arc<Cfg>>,
|
||||
parent: Option<LocalDefId>,
|
||||
cx: &'a mut DocContext<'tcx>,
|
||||
}
|
||||
|
||||
impl DocFolder for CfgPropagator {
|
||||
impl<'a, 'tcx> DocFolder for CfgPropagator<'a, 'tcx> {
|
||||
fn fold_item(&mut self, mut item: Item) -> Option<Item> {
|
||||
let old_parent_cfg = self.parent_cfg.clone();
|
||||
|
||||
if item.kind.is_non_assoc() &&
|
||||
let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) {
|
||||
let hir = self.cx.tcx.hir();
|
||||
let hir_id = hir.local_def_id_to_hir_id(def_id);
|
||||
let expected_parent = hir.get_parent_item(hir_id);
|
||||
|
||||
// If parents are different, it means that `item` is a reexport and we need to compute
|
||||
// the actual `cfg` by iterating through its "real" parents.
|
||||
if self.parent != Some(expected_parent) {
|
||||
let mut attrs = Vec::new();
|
||||
for (parent_hir_id, _) in hir.parent_iter(hir_id) {
|
||||
let def_id = hir.local_def_id(parent_hir_id).to_def_id();
|
||||
attrs.extend_from_slice(load_attrs(self.cx, def_id));
|
||||
}
|
||||
let (_, cfg) =
|
||||
merge_attrs(self.cx, None, item.attrs.other_attrs.as_slice(), Some(&attrs));
|
||||
item.cfg = cfg;
|
||||
}
|
||||
}
|
||||
let new_cfg = match (self.parent_cfg.take(), item.cfg.take()) {
|
||||
(None, None) => None,
|
||||
(Some(rc), None) | (None, Some(rc)) => Some(rc),
|
||||
@ -37,8 +61,15 @@ impl DocFolder for CfgPropagator {
|
||||
self.parent_cfg = new_cfg.clone();
|
||||
item.cfg = new_cfg;
|
||||
|
||||
let old_parent =
|
||||
if let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) {
|
||||
self.parent.replace(def_id)
|
||||
} else {
|
||||
self.parent.take()
|
||||
};
|
||||
let result = self.fold_item_recur(item);
|
||||
self.parent_cfg = old_parent_cfg;
|
||||
self.parent = old_parent;
|
||||
|
||||
Some(result)
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
// This test is to ensure that the anchors (`§`) have the expected color and position.
|
||||
goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
|
||||
show-text: true
|
||||
goto: file://|DOC_PATH|/staged_api/struct.Foo.html
|
||||
|
||||
// This is needed to ensure that the text color is computed.
|
||||
show-text: true
|
||||
@ -13,10 +12,31 @@ reload:
|
||||
assert-css: ("#toggle-all-docs", {"color": "rgb(0, 0, 0)"})
|
||||
assert-css: (".fqn .in-band a:nth-of-type(1)", {"color": "rgb(0, 0, 0)"})
|
||||
assert-css: (".fqn .in-band a:nth-of-type(2)", {"color": "rgb(173, 55, 138)"})
|
||||
assert-css: (".srclink", {"color": "rgb(56, 115, 173)"})
|
||||
assert-css: (
|
||||
".rightside .srclink",
|
||||
{"color": "rgb(56, 115, 173)", "text-decoration": "none solid rgb(56, 115, 173)"},
|
||||
ALL,
|
||||
)
|
||||
compare-elements-css: (".rightside .srclink", ".rightside.srclink", ["color", "text-decoration"])
|
||||
compare-elements-css: (".main-heading .srclink", ".rightside.srclink", ["color", "text-decoration"])
|
||||
|
||||
move-cursor-to: ".main-heading .srclink"
|
||||
assert-css: (".srclink", {"text-decoration": "underline solid rgb(56, 115, 173)"})
|
||||
assert-css: (
|
||||
".main-heading .srclink",
|
||||
{"color": "rgb(56, 115, 173)", "text-decoration": "underline solid rgb(56, 115, 173)"},
|
||||
)
|
||||
move-cursor-to: ".impl-items .rightside .srclink"
|
||||
assert-css: (
|
||||
".impl-items .rightside .srclink",
|
||||
{"color": "rgb(56, 115, 173)", "text-decoration": "none solid rgb(56, 115, 173)"},
|
||||
)
|
||||
move-cursor-to: ".impl-items .rightside.srclink"
|
||||
assert-css: (
|
||||
".impl-items .rightside.srclink",
|
||||
{"color": "rgb(56, 115, 173)", "text-decoration": "none solid rgb(56, 115, 173)"},
|
||||
)
|
||||
|
||||
goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
|
||||
|
||||
assert-css: ("#top-doc-prose-title", {"color": "rgb(0, 0, 0)"})
|
||||
|
||||
@ -32,3 +52,103 @@ move-cursor-to: "#impl-HeavilyDocumentedStruct"
|
||||
assert-css: ("#impl-HeavilyDocumentedStruct a.anchor", {"color": "rgb(0, 0, 0)"})
|
||||
|
||||
assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})
|
||||
|
||||
//
|
||||
// We do the same checks with the dark theme now.
|
||||
//
|
||||
local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
|
||||
goto: file://|DOC_PATH|/staged_api/struct.Foo.html
|
||||
|
||||
assert-css: ("#toggle-all-docs", {"color": "rgb(221, 221, 221)"})
|
||||
assert-css: (".fqn .in-band a:nth-of-type(1)", {"color": "rgb(221, 221, 221)"})
|
||||
assert-css: (".fqn .in-band a:nth-of-type(2)", {"color": "rgb(45, 191, 184)"})
|
||||
assert-css: (
|
||||
".rightside .srclink",
|
||||
{"color": "rgb(210, 153, 29)", "text-decoration": "none solid rgb(210, 153, 29)"},
|
||||
ALL,
|
||||
)
|
||||
compare-elements-css: (".rightside .srclink", ".rightside.srclink", ["color", "text-decoration"])
|
||||
compare-elements-css: (".main-heading .srclink", ".rightside.srclink", ["color", "text-decoration"])
|
||||
|
||||
move-cursor-to: ".main-heading .srclink"
|
||||
assert-css: (
|
||||
".main-heading .srclink",
|
||||
{"color": "rgb(210, 153, 29)", "text-decoration": "underline solid rgb(210, 153, 29)"},
|
||||
)
|
||||
move-cursor-to: ".impl-items .rightside .srclink"
|
||||
assert-css: (
|
||||
".impl-items .rightside .srclink",
|
||||
{"color": "rgb(210, 153, 29)", "text-decoration": "none solid rgb(210, 153, 29)"},
|
||||
)
|
||||
move-cursor-to: ".impl-items .rightside.srclink"
|
||||
assert-css: (
|
||||
".impl-items .rightside.srclink",
|
||||
{"color": "rgb(210, 153, 29)", "text-decoration": "none solid rgb(210, 153, 29)"},
|
||||
)
|
||||
|
||||
goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
|
||||
|
||||
assert-css: ("#top-doc-prose-title", {"color": "rgb(221, 221, 221)"})
|
||||
|
||||
assert-css: (".sidebar a", {"color": "rgb(253, 191, 53)"})
|
||||
assert-css: (".in-band a", {"color": "rgb(221, 221, 221)"})
|
||||
|
||||
// We move the cursor over the "Implementations" title so the anchor is displayed.
|
||||
move-cursor-to: "h2#implementations"
|
||||
assert-css: ("h2#implementations a.anchor", {"color": "rgb(221, 221, 221)"})
|
||||
|
||||
// Same thing with the impl block title.
|
||||
move-cursor-to: "#impl-HeavilyDocumentedStruct"
|
||||
assert-css: ("#impl-HeavilyDocumentedStruct a.anchor", {"color": "rgb(221, 221, 221)"})
|
||||
|
||||
assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})
|
||||
|
||||
//
|
||||
// We do the same checks with the ayu theme now.
|
||||
//
|
||||
local-storage: {"rustdoc-theme": "ayu", "rustdoc-use-system-theme": "false"}
|
||||
goto: file://|DOC_PATH|/staged_api/struct.Foo.html
|
||||
|
||||
assert-css: ("#toggle-all-docs", {"color": "rgb(197, 197, 197)"})
|
||||
assert-css: (".fqn .in-band a:nth-of-type(1)", {"color": "rgb(255, 255, 255)"})
|
||||
assert-css: (".fqn .in-band a:nth-of-type(2)", {"color": "rgb(255, 160, 165)"})
|
||||
assert-css: (
|
||||
".rightside .srclink",
|
||||
{"color": "rgb(57, 175, 215)", "text-decoration": "none solid rgb(57, 175, 215)"},
|
||||
ALL,
|
||||
)
|
||||
compare-elements-css: (".rightside .srclink", ".rightside.srclink", ["color", "text-decoration"])
|
||||
compare-elements-css: (".main-heading .srclink", ".rightside.srclink", ["color", "text-decoration"])
|
||||
|
||||
move-cursor-to: ".main-heading .srclink"
|
||||
assert-css: (
|
||||
".main-heading .srclink",
|
||||
{"color": "rgb(57, 175, 215)", "text-decoration": "underline solid rgb(57, 175, 215)"},
|
||||
)
|
||||
move-cursor-to: ".impl-items .rightside .srclink"
|
||||
assert-css: (
|
||||
".impl-items .rightside .srclink",
|
||||
{"color": "rgb(57, 175, 215)", "text-decoration": "none solid rgb(57, 175, 215)"},
|
||||
)
|
||||
move-cursor-to: ".impl-items .rightside.srclink"
|
||||
assert-css: (
|
||||
".impl-items .rightside.srclink",
|
||||
{"color": "rgb(57, 175, 215)", "text-decoration": "none solid rgb(57, 175, 215)"},
|
||||
)
|
||||
|
||||
goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
|
||||
|
||||
assert-css: ("#top-doc-prose-title", {"color": "rgb(255, 255, 255)"})
|
||||
|
||||
assert-css: (".sidebar a", {"color": "rgb(83, 177, 219)"})
|
||||
assert-css: (".in-band a", {"color": "rgb(255, 255, 255)"})
|
||||
|
||||
// We move the cursor over the "Implementations" title so the anchor is displayed.
|
||||
move-cursor-to: "h2#implementations"
|
||||
assert-css: ("h2#implementations a.anchor", {"color": "rgb(197, 197, 197)"})
|
||||
|
||||
// Same thing with the impl block title.
|
||||
move-cursor-to: "#impl-HeavilyDocumentedStruct"
|
||||
assert-css: ("#impl-HeavilyDocumentedStruct a.anchor", {"color": "rgb(197, 197, 197)"})
|
||||
|
||||
assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})
|
||||
|
@ -247,12 +247,12 @@ assert-css: (
|
||||
|
||||
local-storage: {"rustdoc-theme": "light"}
|
||||
goto: file://|DOC_PATH|/staged_api/struct.Foo.html
|
||||
assert-css: (".since", {"color": "rgb(128, 128, 128)"})
|
||||
assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
|
||||
|
||||
local-storage: {"rustdoc-theme": "dark"}
|
||||
reload:
|
||||
assert-css: (".since", {"color": "rgb(128, 128, 128)"})
|
||||
assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
|
||||
|
||||
local-storage: {"rustdoc-theme": "ayu"}
|
||||
reload:
|
||||
assert-css: (".since", {"color": "rgb(128, 128, 128)"})
|
||||
assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
|
||||
|
@ -7,5 +7,6 @@ edition = "2021"
|
||||
path = "lib.rs"
|
||||
|
||||
[features]
|
||||
default = ["some_feature"]
|
||||
default = ["some_feature", "some_other_feature"]
|
||||
some_feature = []
|
||||
some_other_feature = []
|
||||
|
@ -7,4 +7,6 @@ pub struct Foo {}
|
||||
impl Foo {
|
||||
#[stable(feature = "some_feature", since = "1.3.5")]
|
||||
pub fn bar() {}
|
||||
#[stable(feature = "some_other_feature", since = "1.3.6")]
|
||||
pub fn yo() {}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
<div id="associatedconstant.YOLO" class="method has-srclink"><div class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#16">source</a></div><h4 class="code-header">const <a href="#associatedconstant.YOLO" class="constant">YOLO</a>: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></div>
|
||||
<div id="associatedconstant.YOLO" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#16">source</a><h4 class="code-header">const <a href="#associatedconstant.YOLO" class="constant">YOLO</a>: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></div>
|
@ -1 +1 @@
|
||||
<section id="associatedconstant.X" class="associatedconstant has-srclink"><span class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#42">source</a></span><h4 class="code-header">pub const <a href="#associatedconstant.X" class="constant">X</a>: <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a> = 0i32</h4></section>
|
||||
<section id="associatedconstant.X" class="associatedconstant has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#42">source</a><h4 class="code-header">pub const <a href="#associatedconstant.X" class="constant">X</a>: <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a> = 0i32</h4></section>
|
@ -1 +1 @@
|
||||
<section id="method.new" class="method has-srclink"><span class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#48">source</a></span><h4 class="code-header">pub fn <a href="#method.new" class="fnname">new</a>() -> Self</h4></section>
|
||||
<section id="method.new" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#48">source</a><h4 class="code-header">pub fn <a href="#method.new" class="fnname">new</a>() -> Self</h4></section>
|
@ -1 +1 @@
|
||||
<div id="method.bar" class="method has-srclink"><div class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#23">source</a></div><h4 class="code-header">fn <a href="#method.bar" class="fnname">bar</a>()</h4></div>
|
||||
<div id="method.bar" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#23">source</a><h4 class="code-header">fn <a href="#method.bar" class="fnname">bar</a>()</h4></div>
|
@ -1 +1 @@
|
||||
<div id="tymethod.foo" class="method has-srclink"><div class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#20">source</a></div><h4 class="code-header">fn <a href="#tymethod.foo" class="fnname">foo</a>()</h4></div>
|
||||
<div id="tymethod.foo" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#20">source</a><h4 class="code-header">fn <a href="#tymethod.foo" class="fnname">foo</a>()</h4></div>
|
@ -1 +1 @@
|
||||
<div id="associatedtype.T" class="method has-srclink"><div class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#13">source</a></div><h4 class="code-header">type <a href="#associatedtype.T" class="associatedtype">T</a></h4></div>
|
||||
<div id="associatedtype.T" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#13">source</a><h4 class="code-header">type <a href="#associatedtype.T" class="associatedtype">T</a></h4></div>
|
33
src/test/rustdoc/cfg_doc_reexport.rs
Normal file
33
src/test/rustdoc/cfg_doc_reexport.rs
Normal file
@ -0,0 +1,33 @@
|
||||
#![feature(doc_cfg)]
|
||||
#![feature(no_core)]
|
||||
|
||||
#![crate_name = "foo"]
|
||||
#![no_core]
|
||||
|
||||
// @has 'foo/index.html'
|
||||
// @has - '//*[@class="item-left module-item"]/*[@class="stab portability"]' 'foobar'
|
||||
// @has - '//*[@class="item-left module-item"]/*[@class="stab portability"]' 'bar'
|
||||
|
||||
#[doc(cfg(feature = "foobar"))]
|
||||
mod imp_priv {
|
||||
// @has 'foo/struct.BarPriv.html'
|
||||
// @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
|
||||
// 'Available on crate feature foobar only.'
|
||||
pub struct BarPriv {}
|
||||
impl BarPriv {
|
||||
pub fn test() {}
|
||||
}
|
||||
}
|
||||
#[doc(cfg(feature = "foobar"))]
|
||||
pub use crate::imp_priv::*;
|
||||
|
||||
pub mod bar {
|
||||
// @has 'foo/bar/struct.Bar.html'
|
||||
// @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
|
||||
// 'Available on crate feature bar only.'
|
||||
#[doc(cfg(feature = "bar"))]
|
||||
pub struct Bar;
|
||||
}
|
||||
|
||||
#[doc(cfg(feature = "bar"))]
|
||||
pub use bar::Bar;
|
@ -2,5 +2,5 @@
|
||||
|
||||
// This test ensures that the [src] link is present on traits items.
|
||||
|
||||
// @has foo/trait.Iterator.html '//*[@id="method.zip"]//a[@class="srclink"]' "source"
|
||||
// @has foo/trait.Iterator.html '//*[@id="method.zip"]//a[@class="srclink rightside"]' "source"
|
||||
pub use std::iter::Iterator;
|
||||
|
@ -6,7 +6,7 @@
|
||||
// @has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header in-band"]' 'impl Sync for Unsized'
|
||||
// @!has - '//*[@id="impl-Sync-for-Unsized"]//a[@class="srclink"]' 'source'
|
||||
// @has - '//*[@id="impl-Any-for-Unsized"]/h3[@class="code-header in-band"]' 'impl<T> Any for T'
|
||||
// @has - '//*[@id="impl-Any-for-Unsized"]//a[@class="srclink"]' 'source'
|
||||
// @has - '//*[@id="impl-Any-for-Unsized"]//a[@class="srclink rightside"]' 'source'
|
||||
pub struct Unsized {
|
||||
data: [u8],
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ pub fn foo() {}
|
||||
pub struct Bar;
|
||||
|
||||
impl Bar {
|
||||
// @has - '//*[@id="method.bar"]/*[@class="rightside"]' '2.0'
|
||||
// @has - '//*[@id="method.bar"]/*[@class="since rightside"]' '2.0'
|
||||
// @!has - '//*[@id="method.bar"]/*[@class="rightside"]' '2.0 ·'
|
||||
#[stable(feature = "foobar", since = "2.0")]
|
||||
pub fn bar() {}
|
||||
|
@ -6,9 +6,6 @@ edition = "2021"
|
||||
[dependencies]
|
||||
rustdoc = { path = "../../librustdoc" }
|
||||
|
||||
[build-dependencies]
|
||||
walkdir = "2"
|
||||
|
||||
[[bin]]
|
||||
name = "error_index_generator"
|
||||
path = "main.rs"
|
||||
|
Loading…
x
Reference in New Issue
Block a user