Skip to content

Commit

Permalink
Add range information to slice metadata for types that are known to n…
Browse files Browse the repository at this point in the history
…ot be ZST

# Conflicts:
#	compiler/rustc_hir/src/hir.rs
#	compiler/rustc_ty_utils/src/layout.rs
#	tests/ui/stats/hir-stats.stderr
  • Loading branch information
the8472 committed May 11, 2024
1 parent 3349155 commit c0e2e89
Show file tree
Hide file tree
Showing 16 changed files with 308 additions and 65 deletions.
14 changes: 13 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3855,14 +3855,26 @@ impl<'hir> Node<'hir> {
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
static_assert_size!(Block<'_>, 48);
static_assert_size!(Body<'_>, 24);
#[cfg(bootstrap)]
static_assert_size!(Expr<'_>, 64);
#[cfg(not(bootstrap))]
static_assert_size!(Expr<'_>, 56);
#[cfg(bootstrap)]
static_assert_size!(ExprKind<'_>, 48);
#[cfg(not(bootstrap))]
static_assert_size!(ExprKind<'_>, 40);
static_assert_size!(FnDecl<'_>, 40);
#[cfg(bootstrap)]
static_assert_size!(ForeignItem<'_>, 72);
#[cfg(not(bootstrap))]
static_assert_size!(ForeignItem<'_>, 64);
#[cfg(bootstrap)]
static_assert_size!(ForeignItemKind<'_>, 40);
#[cfg(not(bootstrap))]
static_assert_size!(ForeignItemKind<'_>, 32);
// tidy-alphabetical-start
static_assert_size!(GenericArg<'_>, 24);
static_assert_size!(GenericBound<'_>, 48);
static_assert_size!(Generics<'_>, 56);
Expand Down
27 changes: 16 additions & 11 deletions compiler/rustc_hir_typeck/src/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_hir as hir;
use rustc_index::Idx;
use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_target::abi::{Pointer, VariantIdx};
use rustc_target::abi::{Pointer, Size, VariantIdx};

use super::FnCtxt;

Expand Down Expand Up @@ -84,19 +84,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

fn size_to_bits(size: Size) -> u128 {
let Some(bits) = u128::from(size.bytes()).checked_mul(8) else {
// `u128` should definitely be able to hold the size of different architectures
// larger sizes should be reported as error `are too big for the current architecture`
// otherwise we have a bug somewhere
bug!("{:?} overflow for u128", size)
};

bits
}

// Try to display a sensible error with as much information as possible.
let skeleton_string = |ty: Ty<'tcx>, sk: Result<_, &_>| match sk {
Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
Ok(SizeSkeleton::Known(size)) => {
if let Some(v) = u128::from(size.bytes()).checked_mul(8) {
format!("{v} bits")
} else {
// `u128` should definitely be able to hold the size of different architectures
// larger sizes should be reported as error `are too big for the current architecture`
// otherwise we have a bug somewhere
bug!("{:?} overflow for u128", size)
}
Ok(SizeSkeleton::Pointer { tail, known_size: Some(size), .. }) => {
format!("{} bits, pointer to `{tail}`", size_to_bits(size))
}
Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
Ok(SizeSkeleton::Known(size)) => format!("{} bits", size_to_bits(size)),
Ok(SizeSkeleton::Generic(size)) => {
if let Some(size) = size.try_eval_target_usize(tcx, self.param_env) {
format!("{size} bytes")
Expand Down
35 changes: 29 additions & 6 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::query::TyCtxtAt;
use crate::ty::normalize_erasing_regions::NormalizationError;
use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use hir::Mutability;
use rustc_error_messages::DiagMessage;
use rustc_errors::{
Diag, DiagArgValue, DiagCtxt, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
Expand Down Expand Up @@ -319,6 +320,8 @@ pub enum SizeSkeleton<'tcx> {
Pointer {
/// If true, this pointer is never null.
non_zero: bool,
/// Available if the width of the pointer is known, i.e. whether it's 1 or 2 usizes
known_size: Option<Size>,
/// The type which determines the unsized metadata, if any,
/// of this pointer. Either a type parameter or a projection
/// depending on one, with regions erased.
Expand Down Expand Up @@ -372,7 +375,23 @@ impl<'tcx> SizeSkeleton<'tcx> {
match tail.kind() {
ty::Param(_) | ty::Alias(ty::Projection | ty::Inherent, _) => {
debug_assert!(tail.has_non_region_param());
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
Ok(SizeSkeleton::Pointer {
non_zero,
known_size: None,
tail: tcx.erase_regions(tail),
})
}
ty::Slice(_) => {
debug_assert!(tail.has_non_region_param());
// Assumption: all slice pointers have the same size. At most they differ in niches or or ptr/len ordering
let simple_slice =
Ty::new_ptr(tcx, Ty::new_slice(tcx, tcx.types.unit), Mutability::Not);
let size = tcx.layout_of(param_env.and(simple_slice)).unwrap().size;
Ok(SizeSkeleton::Pointer {
non_zero,
known_size: Some(size),
tail: tcx.erase_regions(tail),
})
}
ty::Error(guar) => {
// Fixes ICE #124031
Expand Down Expand Up @@ -449,7 +468,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
let v0 = zero_or_ptr_variant(0)?;
// Newtype.
if def.variants().len() == 1 {
if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
if let Some(SizeSkeleton::Pointer { non_zero, known_size, tail }) = v0 {
return Ok(SizeSkeleton::Pointer {
non_zero: non_zero
|| match tcx.layout_scalar_valid_range(def.did()) {
Expand All @@ -459,6 +478,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
}
_ => false,
},
known_size,
tail,
});
} else {
Expand All @@ -469,9 +489,9 @@ impl<'tcx> SizeSkeleton<'tcx> {
let v1 = zero_or_ptr_variant(1)?;
// Nullable pointer enum optimization.
match (v0, v1) {
(Some(SizeSkeleton::Pointer { non_zero: true, tail }), None)
| (None, Some(SizeSkeleton::Pointer { non_zero: true, tail })) => {
Ok(SizeSkeleton::Pointer { non_zero: false, tail })
(Some(SizeSkeleton::Pointer { non_zero: true, known_size, tail }), None)
| (None, Some(SizeSkeleton::Pointer { non_zero: true, known_size, tail })) => {
Ok(SizeSkeleton::Pointer { non_zero: false, known_size, tail })
}
_ => Err(err),
}
Expand All @@ -492,7 +512,10 @@ impl<'tcx> SizeSkeleton<'tcx> {

pub fn same_size(self, other: SizeSkeleton<'tcx>) -> bool {
match (self, other) {
(SizeSkeleton::Known(a), SizeSkeleton::Known(b)) => a == b,
(
SizeSkeleton::Known(a) | SizeSkeleton::Pointer { known_size: Some(a), .. },
SizeSkeleton::Known(b) | SizeSkeleton::Pointer { known_size: Some(b), .. },
) => a == b,
(SizeSkeleton::Pointer { tail: a, .. }, SizeSkeleton::Pointer { tail: b, .. }) => {
a == b
}
Expand Down
Loading

0 comments on commit c0e2e89

Please sign in to comment.