Auto merge of #110666 - JohnTitor:rollup-3pwilte, r=JohnTitor
Rollup of 7 pull requests Successful merges: - #109949 (rustdoc: migrate `document_type_layout` to askama) - #110622 (Stable hash tag (discriminant) of `GenericArg`) - #110635 (More `IS_ZST` in `library`) - #110640 (compiler/rustc_target: Raise m68k-linux-gnu baseline to 68020) - #110657 (nit: consistent naming for SimplifyConstCondition) - #110659 (rustdoc: clean up JS) - #110660 (Print ty placeholders pretty) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
3128fd8ddf
@ -73,34 +73,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'t
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArgKind<'tcx> {
|
||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||
match self {
|
||||
// WARNING: We dedup cache the `HashStable` results for `List`
|
||||
// while ignoring types and freely transmute
|
||||
// between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
|
||||
// See `fn mk_type_list` for more details.
|
||||
//
|
||||
// We therefore hash types without adding a hash for their discriminant.
|
||||
//
|
||||
// In order to make it very unlikely for the sequence of bytes being hashed for
|
||||
// a `GenericArgKind::Type` to be the same as the sequence of bytes being
|
||||
// hashed for one of the other variants, we hash some very high number instead
|
||||
// of their actual discriminant since `TyKind` should never start with anything
|
||||
// that high.
|
||||
ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher),
|
||||
ty::subst::GenericArgKind::Const(ct) => {
|
||||
0xF3u8.hash_stable(hcx, hasher);
|
||||
ct.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::subst::GenericArgKind::Lifetime(lt) => {
|
||||
0xF5u8.hash_stable(hcx, hasher);
|
||||
lt.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AllocIds get resolved to whatever they point to (to be stable)
|
||||
impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
|
||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||
|
@ -738,7 +738,9 @@ pub trait PrettyPrinter<'tcx>:
|
||||
}
|
||||
}
|
||||
ty::Placeholder(placeholder) => match placeholder.bound.kind {
|
||||
ty::BoundTyKind::Anon => p!(write("Placeholder({:?})", placeholder)),
|
||||
ty::BoundTyKind::Anon => {
|
||||
self.pretty_print_placeholder_var(placeholder.universe, placeholder.bound.var)?
|
||||
}
|
||||
ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
|
||||
},
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||
@ -1172,6 +1174,18 @@ pub trait PrettyPrinter<'tcx>:
|
||||
}
|
||||
}
|
||||
|
||||
fn pretty_print_placeholder_var(
|
||||
&mut self,
|
||||
ui: ty::UniverseIndex,
|
||||
var: ty::BoundVar,
|
||||
) -> Result<(), Self::Error> {
|
||||
if ui == ty::UniverseIndex::ROOT {
|
||||
write!(self, "!{}", var.index())
|
||||
} else {
|
||||
write!(self, "!{}_{}", ui.index(), var.index())
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_infer_name(&self, _: ty::TyVid) -> Option<Symbol> {
|
||||
None
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ const TYPE_TAG: usize = 0b00;
|
||||
const REGION_TAG: usize = 0b01;
|
||||
const CONST_TAG: usize = 0b10;
|
||||
|
||||
#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)]
|
||||
pub enum GenericArgKind<'tcx> {
|
||||
Lifetime(ty::Region<'tcx>),
|
||||
Type(Ty<'tcx>),
|
||||
|
@ -507,12 +507,12 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
//
|
||||
// Const-prop runs unconditionally, but doesn't mutate the MIR at mir-opt-level=0.
|
||||
&const_debuginfo::ConstDebugInfo,
|
||||
&o1(simplify_branches::SimplifyConstConditionPassName::AfterConstProp),
|
||||
&o1(simplify_branches::SimplifyConstCondition::AfterConstProp),
|
||||
&early_otherwise_branch::EarlyOtherwiseBranch,
|
||||
&simplify_comparison_integral::SimplifyComparisonIntegral,
|
||||
&dead_store_elimination::DeadStoreElimination,
|
||||
&dest_prop::DestinationPropagation,
|
||||
&o1(simplify_branches::SimplifyConstConditionPassName::Final),
|
||||
&o1(simplify_branches::SimplifyConstCondition::Final),
|
||||
&o1(remove_noop_landing_pads::RemoveNoopLandingPads),
|
||||
&o1(simplify::SimplifyCfg::Final),
|
||||
&nrvo::RenameReturnPlace,
|
||||
|
@ -2,18 +2,16 @@ use crate::MirPass;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
pub enum SimplifyConstConditionPassName {
|
||||
pub enum SimplifyConstCondition {
|
||||
AfterConstProp,
|
||||
Final,
|
||||
}
|
||||
/// A pass that replaces a branch with a goto when its condition is known.
|
||||
impl<'tcx> MirPass<'tcx> for SimplifyConstConditionPassName {
|
||||
impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
|
||||
fn name(&self) -> &'static str {
|
||||
match self {
|
||||
SimplifyConstConditionPassName::AfterConstProp => {
|
||||
"SimplifyConstCondition-after-const-prop"
|
||||
}
|
||||
SimplifyConstConditionPassName::Final => "SimplifyConstCondition-final",
|
||||
SimplifyConstCondition::AfterConstProp => "SimplifyConstCondition-after-const-prop",
|
||||
SimplifyConstCondition::Final => "SimplifyConstCondition-final",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ use crate::spec::{Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::linux_gnu_base::opts();
|
||||
base.cpu = "M68020".into();
|
||||
base.max_atomic_width = Some(32);
|
||||
|
||||
Target {
|
||||
|
@ -203,6 +203,10 @@ pub enum TyKind<I: Interner> {
|
||||
/// `for<'a, T> &'a (): Trait<T>` and then convert the introduced bound variables
|
||||
/// back to inference variables in a new inference context when inside of the query.
|
||||
///
|
||||
/// It is conventional to render anonymous bound types like `^N` or `^D_N`,
|
||||
/// where `N` is the bound variable's anonymous index into the binder, and
|
||||
/// `D` is the debruijn index, or totally omitted if the debruijn index is zero.
|
||||
///
|
||||
/// See the `rustc-dev-guide` for more details about
|
||||
/// [higher-ranked trait bounds][1] and [canonical queries][2].
|
||||
///
|
||||
@ -212,6 +216,12 @@ pub enum TyKind<I: Interner> {
|
||||
|
||||
/// A placeholder type, used during higher ranked subtyping to instantiate
|
||||
/// bound variables.
|
||||
///
|
||||
/// It is conventional to render anonymous placeholer types like `!N` or `!U_N`,
|
||||
/// where `N` is the placeholder variable's anonymous index (which corresponds
|
||||
/// to the bound variable's index from the binder from which it was instantiated),
|
||||
/// and `U` is the universe index in which it is instantiated, or totally omitted
|
||||
/// if the universe index is zero.
|
||||
Placeholder(I::PlaceholderType),
|
||||
|
||||
/// A type variable used during type checking.
|
||||
|
@ -7,7 +7,7 @@ use core::fmt::{self, Debug, Display, Formatter};
|
||||
use core::marker::PhantomData;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::marker::Unsize;
|
||||
use core::mem;
|
||||
use core::mem::{self, SizedTypeProperties};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::ptr::Pointee;
|
||||
use core::ptr::{self, NonNull};
|
||||
@ -202,9 +202,7 @@ impl<H> WithHeader<H> {
|
||||
let ptr = if layout.size() == 0 {
|
||||
// Some paranoia checking, mostly so that the ThinBox tests are
|
||||
// more able to catch issues.
|
||||
debug_assert!(
|
||||
value_offset == 0 && mem::size_of::<T>() == 0 && mem::size_of::<H>() == 0
|
||||
);
|
||||
debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST);
|
||||
layout.dangling()
|
||||
} else {
|
||||
let ptr = alloc::alloc(layout);
|
||||
@ -249,9 +247,7 @@ impl<H> WithHeader<H> {
|
||||
alloc::dealloc(self.ptr.as_ptr().sub(value_offset), layout);
|
||||
} else {
|
||||
debug_assert!(
|
||||
value_offset == 0
|
||||
&& mem::size_of::<H>() == 0
|
||||
&& self.value_layout.size() == 0
|
||||
value_offset == 0 && H::IS_ZST && self.value_layout.size() == 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -112,9 +112,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> {
|
||||
let unyielded_ptr = this.iter.as_slice().as_ptr();
|
||||
|
||||
// ZSTs have no identity, so we don't need to move them around.
|
||||
let needs_move = mem::size_of::<T>() != 0;
|
||||
|
||||
if needs_move {
|
||||
if !T::IS_ZST {
|
||||
let start_ptr = source_vec.as_mut_ptr().add(start);
|
||||
|
||||
// memmove back unyielded elements
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::alloc::{Allocator, Global};
|
||||
use core::mem::{self, ManuallyDrop};
|
||||
use core::mem::{ManuallyDrop, SizedTypeProperties};
|
||||
use core::ptr;
|
||||
use core::slice;
|
||||
|
||||
@ -96,9 +96,7 @@ where
|
||||
|
||||
unsafe {
|
||||
// ZSTs have no identity, so we don't need to move them around.
|
||||
let needs_move = mem::size_of::<T>() != 0;
|
||||
|
||||
if needs_move && this.idx < this.old_len && this.del > 0 {
|
||||
if !T::IS_ZST && this.idx < this.old_len && this.del > 0 {
|
||||
let ptr = this.vec.as_mut_ptr();
|
||||
let src = ptr.add(this.idx);
|
||||
let dst = src.sub(this.del);
|
||||
|
@ -73,7 +73,7 @@ macro_rules! iterator {
|
||||
// Unsafe because the offset must not exceed `self.len()`.
|
||||
#[inline(always)]
|
||||
unsafe fn post_inc_start(&mut self, offset: usize) -> * $raw_mut T {
|
||||
if mem::size_of::<T>() == 0 {
|
||||
if T::IS_ZST {
|
||||
zst_shrink!(self, offset);
|
||||
self.ptr.as_ptr()
|
||||
} else {
|
||||
|
@ -32,6 +32,7 @@ mod context;
|
||||
mod print_item;
|
||||
mod sidebar;
|
||||
mod span_map;
|
||||
mod type_layout;
|
||||
mod write_shared;
|
||||
|
||||
pub(crate) use self::context::*;
|
||||
|
@ -6,16 +6,14 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::CtorKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::layout::LayoutError;
|
||||
use rustc_middle::ty::{self, Adt, TyCtxt};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_target::abi::{LayoutS, Primitive, TagEncoding, Variants};
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::type_layout::document_type_layout;
|
||||
use super::{
|
||||
collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
|
||||
item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
|
||||
@ -1933,118 +1931,6 @@ fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a
|
||||
})
|
||||
}
|
||||
|
||||
fn document_type_layout<'a, 'cx: 'a>(
|
||||
cx: &'a Context<'cx>,
|
||||
ty_def_id: DefId,
|
||||
) -> impl fmt::Display + 'a + Captures<'cx> {
|
||||
fn write_size_of_layout(mut w: impl fmt::Write, layout: &LayoutS, tag_size: u64) {
|
||||
if layout.abi.is_unsized() {
|
||||
write!(w, "(unsized)").unwrap();
|
||||
} else {
|
||||
let size = layout.size.bytes() - tag_size;
|
||||
write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" }).unwrap();
|
||||
if layout.abi.is_uninhabited() {
|
||||
write!(
|
||||
w,
|
||||
" (<a href=\"https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited\">uninhabited</a>)"
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
display_fn(move |mut f| {
|
||||
if !cx.shared.show_type_layout {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
writeln!(
|
||||
f,
|
||||
"<h2 id=\"layout\" class=\"small-section-header\"> \
|
||||
Layout<a href=\"#layout\" class=\"anchor\">§</a></h2>"
|
||||
)?;
|
||||
writeln!(f, "<div class=\"docblock\">")?;
|
||||
|
||||
let tcx = cx.tcx();
|
||||
let param_env = tcx.param_env(ty_def_id);
|
||||
let ty = tcx.type_of(ty_def_id).subst_identity();
|
||||
match tcx.layout_of(param_env.and(ty)) {
|
||||
Ok(ty_layout) => {
|
||||
writeln!(
|
||||
f,
|
||||
"<div class=\"warning\"><p><strong>Note:</strong> Most layout information is \
|
||||
<strong>completely unstable</strong> and may even differ between compilations. \
|
||||
The only exception is types with certain <code>repr(...)</code> attributes. \
|
||||
Please see the Rust Reference’s \
|
||||
<a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \
|
||||
chapter for details on type layout guarantees.</p></div>"
|
||||
)?;
|
||||
f.write_str("<p><strong>Size:</strong> ")?;
|
||||
write_size_of_layout(&mut f, &ty_layout.layout.0, 0);
|
||||
writeln!(f, "</p>")?;
|
||||
if let Variants::Multiple { variants, tag, tag_encoding, .. } =
|
||||
&ty_layout.layout.variants()
|
||||
{
|
||||
if !variants.is_empty() {
|
||||
f.write_str(
|
||||
"<p><strong>Size for each variant:</strong></p>\
|
||||
<ul>",
|
||||
)?;
|
||||
|
||||
let Adt(adt, _) = ty_layout.ty.kind() else {
|
||||
span_bug!(tcx.def_span(ty_def_id), "not an adt")
|
||||
};
|
||||
|
||||
let tag_size = if let TagEncoding::Niche { .. } = tag_encoding {
|
||||
0
|
||||
} else if let Primitive::Int(i, _) = tag.primitive() {
|
||||
i.size().bytes()
|
||||
} else {
|
||||
span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
|
||||
};
|
||||
|
||||
for (index, layout) in variants.iter_enumerated() {
|
||||
let name = adt.variant(index).name;
|
||||
write!(&mut f, "<li><code>{name}</code>: ")?;
|
||||
write_size_of_layout(&mut f, layout, tag_size);
|
||||
writeln!(&mut f, "</li>")?;
|
||||
}
|
||||
f.write_str("</ul>")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
// This kind of layout error can occur with valid code, e.g. if you try to
|
||||
// get the layout of a generic type such as `Vec<T>`.
|
||||
Err(LayoutError::Unknown(_)) => {
|
||||
writeln!(
|
||||
f,
|
||||
"<p><strong>Note:</strong> Unable to compute type layout, \
|
||||
possibly due to this type having generic parameters. \
|
||||
Layout can only be computed for concrete, fully-instantiated types.</p>"
|
||||
)?;
|
||||
}
|
||||
// This kind of error probably can't happen with valid code, but we don't
|
||||
// want to panic and prevent the docs from building, so we just let the
|
||||
// user know that we couldn't compute the layout.
|
||||
Err(LayoutError::SizeOverflow(_)) => {
|
||||
writeln!(
|
||||
f,
|
||||
"<p><strong>Note:</strong> Encountered an error during type layout; \
|
||||
the type was too big.</p>"
|
||||
)?;
|
||||
}
|
||||
Err(LayoutError::NormalizationFailure(_, _)) => {
|
||||
writeln!(
|
||||
f,
|
||||
"<p><strong>Note:</strong> Encountered an error during type layout; \
|
||||
the type failed to be normalized.</p>"
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(f, "</div>")
|
||||
})
|
||||
}
|
||||
|
||||
fn pluralize(count: usize) -> &'static str {
|
||||
if count > 1 { "s" } else { "" }
|
||||
}
|
||||
|
86
src/librustdoc/html/render/type_layout.rs
Normal file
86
src/librustdoc/html/render/type_layout.rs
Normal file
@ -0,0 +1,86 @@
|
||||
use askama::Template;
|
||||
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::layout::LayoutError;
|
||||
use rustc_middle::ty::Adt;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::abi::{Primitive, TagEncoding, Variants};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use crate::html::format::display_fn;
|
||||
use crate::html::render::Context;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "type_layout.html")]
|
||||
struct TypeLayout<'cx> {
|
||||
variants: Vec<(Symbol, TypeLayoutSize)>,
|
||||
type_layout_size: Result<TypeLayoutSize, LayoutError<'cx>>,
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "type_layout_size.html")]
|
||||
struct TypeLayoutSize {
|
||||
is_unsized: bool,
|
||||
is_uninhabited: bool,
|
||||
size: u64,
|
||||
}
|
||||
|
||||
pub(crate) fn document_type_layout<'a, 'cx: 'a>(
|
||||
cx: &'a Context<'cx>,
|
||||
ty_def_id: DefId,
|
||||
) -> impl fmt::Display + 'a + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
if !cx.shared.show_type_layout {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let tcx = cx.tcx();
|
||||
let param_env = tcx.param_env(ty_def_id);
|
||||
let ty = tcx.type_of(ty_def_id).subst_identity();
|
||||
let type_layout = tcx.layout_of(param_env.and(ty));
|
||||
|
||||
let variants =
|
||||
if let Ok(type_layout) = type_layout &&
|
||||
let Variants::Multiple { variants, tag, tag_encoding, .. } =
|
||||
type_layout.layout.variants() &&
|
||||
!variants.is_empty()
|
||||
{
|
||||
let tag_size =
|
||||
if let TagEncoding::Niche { .. } = tag_encoding {
|
||||
0
|
||||
} else if let Primitive::Int(i, _) = tag.primitive() {
|
||||
i.size().bytes()
|
||||
} else {
|
||||
span_bug!(cx.tcx().def_span(ty_def_id), "tag is neither niche nor int")
|
||||
};
|
||||
variants
|
||||
.iter_enumerated()
|
||||
.map(|(variant_idx, variant_layout)| {
|
||||
let Adt(adt, _) = type_layout.ty.kind() else {
|
||||
span_bug!(cx.tcx().def_span(ty_def_id), "not an adt")
|
||||
};
|
||||
let name = adt.variant(variant_idx).name;
|
||||
let is_unsized = variant_layout.abi.is_unsized();
|
||||
let is_uninhabited = variant_layout.abi.is_uninhabited();
|
||||
let size = variant_layout.size.bytes() - tag_size;
|
||||
let type_layout_size = TypeLayoutSize { is_unsized, is_uninhabited, size };
|
||||
(name, type_layout_size)
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| {
|
||||
let is_unsized = layout.abi.is_unsized();
|
||||
let is_uninhabited = layout.abi.is_uninhabited();
|
||||
let size = layout.size.bytes();
|
||||
TypeLayoutSize { is_unsized, is_uninhabited, size }
|
||||
});
|
||||
|
||||
Ok(TypeLayout { variants, type_layout_size }.render_into(f).unwrap())
|
||||
})
|
||||
}
|
@ -375,10 +375,7 @@ function preLoadCss(cssUrl) {
|
||||
|
||||
function handleEscape(ev) {
|
||||
searchState.clearInputTimeout();
|
||||
switchDisplayedElement(null);
|
||||
if (browserSupportsHistoryApi()) {
|
||||
history.replaceState(null, "", getNakedUrl() + window.location.hash);
|
||||
}
|
||||
searchState.hideResults();
|
||||
ev.preventDefault();
|
||||
searchState.defocus();
|
||||
window.hideAllModals(true); // true = reset focus for tooltips
|
||||
@ -533,9 +530,11 @@ function preLoadCss(cssUrl) {
|
||||
// ignored are included in the attribute `data-ignore-extern-crates`.
|
||||
const script = document
|
||||
.querySelector("script[data-ignore-extern-crates]");
|
||||
const ignoreExternCrates = script ? script.getAttribute("data-ignore-extern-crates") : "";
|
||||
const ignoreExternCrates = new Set(
|
||||
(script ? script.getAttribute("data-ignore-extern-crates") : "").split(",")
|
||||
);
|
||||
for (const lib of libs) {
|
||||
if (lib === window.currentCrate || ignoreExternCrates.indexOf(lib) !== -1) {
|
||||
if (lib === window.currentCrate || ignoreExternCrates.has(lib)) {
|
||||
continue;
|
||||
}
|
||||
const structs = imp[lib];
|
||||
|
@ -2412,10 +2412,6 @@ function initSearch(rawSearchIndex) {
|
||||
const searchAfter500ms = () => {
|
||||
searchState.clearInputTimeout();
|
||||
if (searchState.input.value.length === 0) {
|
||||
if (browserSupportsHistoryApi()) {
|
||||
history.replaceState(null, window.currentCrate + " - Rust",
|
||||
getNakedUrl() + window.location.hash);
|
||||
}
|
||||
searchState.hideResults();
|
||||
} else {
|
||||
searchState.timeout = setTimeout(search, 500);
|
||||
|
@ -52,12 +52,12 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) {
|
||||
const files = document.createElement("div");
|
||||
files.className = "files";
|
||||
if (elem[FILES_OFFSET]) {
|
||||
const w = window.location.href.split("#")[0];
|
||||
for (const file_text of elem[FILES_OFFSET]) {
|
||||
const file = document.createElement("a");
|
||||
file.innerText = file_text;
|
||||
file.href = rootPath + "src/" + fullPath + file_text + ".html";
|
||||
file.addEventListener("click", closeSidebarIfMobile);
|
||||
const w = window.location.href.split("#")[0];
|
||||
if (!hasFoundFile && w === file.href) {
|
||||
file.className = "selected";
|
||||
dirEntry.open = true;
|
||||
|
53
src/librustdoc/html/templates/type_layout.html
Normal file
53
src/librustdoc/html/templates/type_layout.html
Normal file
@ -0,0 +1,53 @@
|
||||
<h2 id="layout" class="small-section-header"> {# #}
|
||||
Layout<a href="#layout" class="anchor">§</a> {# #}
|
||||
</h2> {# #}
|
||||
<div class="docblock"> {# #}
|
||||
{% match type_layout_size %}
|
||||
{% when Ok(type_layout_size) %}
|
||||
<div class="warning"> {# #}
|
||||
<p> {# #}
|
||||
<strong>Note:</strong> Most layout information is <strong>completely {#+ #}
|
||||
unstable</strong> and may even differ between compilations. {#+ #}
|
||||
The only exception is types with certain <code>repr(...)</code> {#+ #}
|
||||
attributes. Please see the Rust Reference’s {#+ #}
|
||||
<a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #}
|
||||
chapter for details on type layout guarantees. {# #}
|
||||
</p> {# #}
|
||||
</div> {# #}
|
||||
<p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #}
|
||||
{% if !variants.is_empty() %}
|
||||
<p> {# #}
|
||||
<strong>Size for each variant:</strong> {# #}
|
||||
</p> {# #}
|
||||
<ul> {# #}
|
||||
{% for (name, layout_size) in variants %}
|
||||
<li> {# #}
|
||||
<code>{{ name }}</code>: {#+ #}
|
||||
{{ layout_size|safe }}
|
||||
</li> {# #}
|
||||
{% endfor %}
|
||||
</ul> {# #}
|
||||
{% endif %}
|
||||
{# This kind of layout error can occur with valid code, e.g. if you try to
|
||||
get the layout of a generic type such as `Vec<T>`. #}
|
||||
{% when Err(LayoutError::Unknown(_)) %}
|
||||
<p> {# #}
|
||||
<strong>Note:</strong> Unable to compute type layout, {#+ #}
|
||||
possibly due to this type having generic parameters. {#+ #}
|
||||
Layout can only be computed for concrete, fully-instantiated types. {# #}
|
||||
</p> {# #}
|
||||
{# This kind of error probably can't happen with valid code, but we don't
|
||||
want to panic and prevent the docs from building, so we just let the
|
||||
user know that we couldn't compute the layout. #}
|
||||
{% when Err(LayoutError::SizeOverflow(_)) %}
|
||||
<p> {# #}
|
||||
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
|
||||
the type was too big. {# #}
|
||||
</p> {# #}
|
||||
{% when Err(LayoutError::NormalizationFailure(_, _)) %}
|
||||
<p> {# #}
|
||||
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
|
||||
the type failed to be normalized. {# #}
|
||||
</p> {# #}
|
||||
{% endmatch %}
|
||||
</div> {# #}
|
12
src/librustdoc/html/templates/type_layout_size.html
Normal file
12
src/librustdoc/html/templates/type_layout_size.html
Normal file
@ -0,0 +1,12 @@
|
||||
{% if is_unsized %}
|
||||
(unsized)
|
||||
{% else %}
|
||||
{% if size == 1 %}
|
||||
1 byte
|
||||
{% else %}
|
||||
{{ size +}} bytes
|
||||
{% endif %}
|
||||
{% if is_uninhabited %}
|
||||
{# +#} (<a href="https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited">uninhabited</a>)
|
||||
{% endif %}
|
||||
{% endif %}
|
Loading…
x
Reference in New Issue
Block a user