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:
bors 2023-04-22 05:35:08 +00:00
commit 3128fd8ddf
19 changed files with 200 additions and 180 deletions

View File

@ -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) {

View File

@ -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
}

View File

@ -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>),

View File

@ -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,

View File

@ -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",
}
}

View File

@ -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 {

View File

@ -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.

View File

@ -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
);
}
}

View File

@ -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

View File

@ -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);

View File

@ -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 {

View File

@ -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::*;

View File

@ -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 References \
<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 { "" }
}

View 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())
})
}

View File

@ -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];

View File

@ -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);

View File

@ -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;

View 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 References {#+ #}
<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> {# #}

View 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 %}