diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
index 5fbaed7283a..37d2679c10d 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/comments.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
@@ -82,8 +82,14 @@ pub(super) fn add_local_place_comments<'tcx>(
return;
}
let TyAndLayout { ty, layout } = place.layout();
- let rustc_target::abi::Layout { size, align, abi: _, variants: _, fields: _, largest_niche: _ } =
- layout;
+ let rustc_target::abi::LayoutS {
+ size,
+ align,
+ abi: _,
+ variants: _,
+ fields: _,
+ largest_niche: _,
+ } = layout.0.0;
let (kind, extra) = match *place.inner() {
CPlaceInner::Var(place_local, var) => {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 4dfb13476c2..6489b96be4b 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -1070,7 +1070,7 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
};
raw_eq, (v lhs_ref, v rhs_ref) {
- let size = fx.layout_of(substs.type_at(0)).layout.size;
+ let size = fx.layout_of(substs.type_at(0)).layout.size();
// FIXME add and use emit_small_memcmp
let is_eq_value =
if size == Size::ZERO {
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 572ac559d09..ef213f56369 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -272,20 +272,20 @@ fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'t
use rustc_target::abi::Abi::*;
let tp_ty = substs.type_at(0);
let layout = self.layout_of(tp_ty).layout;
- let _use_integer_compare = match layout.abi {
+ let _use_integer_compare = match layout.abi() {
Scalar(_) | ScalarPair(_, _) => true,
Uninhabited | Vector { .. } => false,
Aggregate { .. } => {
// For rusty ABIs, small aggregates are actually passed
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
// so we re-use that same threshold here.
- layout.size <= self.data_layout().pointer_size * 2
+ layout.size() <= self.data_layout().pointer_size * 2
}
};
let a = args[0].immediate();
let b = args[1].immediate();
- if layout.size.bytes() == 0 {
+ if layout.size().bytes() == 0 {
self.const_bool(true)
}
/*else if use_integer_compare {
@@ -301,7 +301,7 @@ fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'t
let void_ptr_type = self.context.new_type::<*const ()>();
let a_ptr = self.bitcast(a, void_ptr_type);
let b_ptr = self.bitcast(b, void_ptr_type);
- let n = self.context.new_cast(None, self.const_usize(layout.size.bytes()), self.sizet_type);
+ let n = self.context.new_cast(None, self.const_usize(layout.size().bytes()), self.sizet_type);
let builtin = self.context.get_builtin_function("memcmp");
let cmp = self.context.new_call(None, builtin, &[a_ptr, b_ptr, n]);
self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0))
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index e7c13e793d9..7f804ab5e63 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -300,34 +300,34 @@ fn codegen_intrinsic_call(
use abi::Abi::*;
let tp_ty = substs.type_at(0);
let layout = self.layout_of(tp_ty).layout;
- let use_integer_compare = match layout.abi {
+ let use_integer_compare = match layout.abi() {
Scalar(_) | ScalarPair(_, _) => true,
Uninhabited | Vector { .. } => false,
Aggregate { .. } => {
// For rusty ABIs, small aggregates are actually passed
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
// so we re-use that same threshold here.
- layout.size <= self.data_layout().pointer_size * 2
+ layout.size() <= self.data_layout().pointer_size * 2
}
};
let a = args[0].immediate();
let b = args[1].immediate();
- if layout.size.bytes() == 0 {
+ if layout.size().bytes() == 0 {
self.const_bool(true)
} else if use_integer_compare {
- let integer_ty = self.type_ix(layout.size.bits());
+ let integer_ty = self.type_ix(layout.size().bits());
let ptr_ty = self.type_ptr_to(integer_ty);
let a_ptr = self.bitcast(a, ptr_ty);
- let a_val = self.load(integer_ty, a_ptr, layout.align.abi);
+ let a_val = self.load(integer_ty, a_ptr, layout.align().abi);
let b_ptr = self.bitcast(b, ptr_ty);
- let b_val = self.load(integer_ty, b_ptr, layout.align.abi);
+ let b_val = self.load(integer_ty, b_ptr, layout.align().abi);
self.icmp(IntPredicate::IntEQ, a_val, b_val)
} else {
let i8p_ty = self.type_i8p();
let a_ptr = self.bitcast(a, i8p_ty);
let b_ptr = self.bitcast(b, i8p_ty);
- let n = self.const_usize(layout.size.bytes());
+ let n = self.const_usize(layout.size().bytes());
let cmp = self.call_intrinsic("memcmp", &[a_ptr, b_ptr, n]);
self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0))
}
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 37e84046901..62a297937d4 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -427,7 +427,7 @@ fn msvc_enum_fallback<'tcx>(
// calculate the range of values for the dataful variant
let dataful_discriminant_range =
- dataful_variant_layout.largest_niche.unwrap().scalar.valid_range;
+ dataful_variant_layout.largest_niche().unwrap().scalar.valid_range;
let min = dataful_discriminant_range.start;
let min = tag.value.size(&tcx).truncate(min);
diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs
index f0e3f83e848..7a320b10b60 100644
--- a/compiler/rustc_data_structures/src/intern.rs
+++ b/compiler/rustc_data_structures/src/intern.rs
@@ -1,3 +1,4 @@
+use crate::stable_hasher::{HashStable, StableHasher};
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
@@ -98,5 +99,14 @@ fn hash(&self, s: &mut H) {
}
}
+impl HashStable for Interned<'_, T>
+where
+ T: HashStable,
+{
+ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+ self.0.hash_stable(hcx, hasher);
+ }
+}
+
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 72b8d8bb297..b6b73ba4539 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2861,8 +2861,8 @@ fn structurally_same_type_impl<'tcx>(
let compare_layouts = |a, b| -> Result> {
debug!("compare_layouts({:?}, {:?})", a, b);
- let a_layout = &cx.layout_of(a)?.layout.abi;
- let b_layout = &cx.layout_of(b)?.layout.abi;
+ let a_layout = &cx.layout_of(a)?.layout.abi();
+ let b_layout = &cx.layout_of(b)?.layout.abi();
debug!(
"comparing layouts: {:?} == {:?} = {}",
a_layout,
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index c0bf64387ff..0d5e1e7f551 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1349,7 +1349,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
let (largest, slargest, largest_index) = iter::zip(enum_definition.variants, variants)
.map(|(variant, variant_layout)| {
// Subtract the size of the enum tag.
- let bytes = variant_layout.size.bytes().saturating_sub(tag_size);
+ let bytes = variant_layout.size().bytes().saturating_sub(tag_size);
debug!("- variant `{}` is {} bytes large", variant.ident, bytes);
bytes
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 7cdcb6a4ab3..f4bc28f4da1 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -392,7 +392,7 @@ fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize {
.layout;
// In both stdcall and fastcall, we always round up the argument size to the
// nearest multiple of 4 bytes.
- (layout.size.bytes_usize() + 3) & !3
+ (layout.size().bytes_usize() + 3) & !3
})
.sum()
}
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index c4e6734aa0f..825dc79129d 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -6,7 +6,7 @@
macro_rules! arena_types {
($macro:path) => (
$macro!([
- [] layout: rustc_target::abi::Layout,
+ [] layout: rustc_target::abi::LayoutS<'tcx>,
[] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
// AdtDef are interned and compared by address
[decode] adt_def: rustc_middle::ty::AdtDef,
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index b48b6e3a820..99dd4ab1bf5 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -56,7 +56,7 @@
use rustc_span::source_map::{MultiSpan, SourceMap};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
+use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi;
use rustc_type_ir::TypeFlags;
@@ -114,7 +114,7 @@ pub struct CtxtInterners<'tcx> {
const_: InternedSet<'tcx, ConstS<'tcx>>,
const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List>,
- layout: InternedSet<'tcx, Layout>,
+ layout: InternedSet<'tcx, LayoutS<'tcx>>,
adt_def: InternedSet<'tcx, AdtDef>,
}
@@ -2146,6 +2146,7 @@ pub fn $method(self, v: $ty) -> $ret_ty {
region: mk_region(RegionKind): Region -> Region<'tcx>,
const_: mk_const(ConstS<'tcx>): Const -> Const<'tcx>,
const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
+ layout: intern_layout(LayoutS<'tcx>): Layout -> Layout<'tcx>,
}
macro_rules! direct_interners_old {
@@ -2186,7 +2187,6 @@ pub fn $method(self, v: $ty) -> &'tcx $ty {
// FIXME: eventually these should all be converted to `direct_interners`.
direct_interners_old! {
- layout: intern_layout(Layout),
adt_def: intern_adt_def(AdtDef),
}
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 7495449da4c..23664640aae 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -5,6 +5,7 @@
use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
use rustc_ast as ast;
use rustc_attr as attr;
+use rustc_data_structures::intern::Interned;
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::BitSet;
@@ -302,7 +303,7 @@ fn invert_mapping(map: &[u32]) -> Vec {
}
impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
- fn scalar_pair(&self, a: Scalar, b: Scalar) -> Layout {
+ fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS<'tcx> {
let dl = self.data_layout();
let b_align = b.value.align(dl);
let align = a.value.align(dl).max(b_align).max(dl.aggregate_align);
@@ -316,7 +317,7 @@ fn scalar_pair(&self, a: Scalar, b: Scalar) -> Layout {
.chain(Niche::from_scalar(dl, Size::ZERO, a))
.max_by_key(|niche| niche.available(dl));
- Layout {
+ LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Arbitrary {
offsets: vec![Size::ZERO, b_offset],
@@ -335,7 +336,7 @@ fn univariant_uninterned(
fields: &[TyAndLayout<'_>],
repr: &ReprOptions,
kind: StructKind,
- ) -> Result> {
+ ) -> Result, LayoutError<'tcx>> {
let dl = self.data_layout();
let pack = repr.pack;
if pack.is_some() && repr.align.is_some() {
@@ -503,8 +504,20 @@ fn univariant_uninterned(
// Two non-ZST fields, and they're both scalars.
(
- Some((i, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(a), .. }, .. })),
- Some((j, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(b), .. }, .. })),
+ Some((
+ i,
+ &TyAndLayout {
+ layout: Layout(Interned(&LayoutS { abi: Abi::Scalar(a), .. }, _)),
+ ..
+ },
+ )),
+ Some((
+ j,
+ &TyAndLayout {
+ layout: Layout(Interned(&LayoutS { abi: Abi::Scalar(b), .. }, _)),
+ ..
+ },
+ )),
None,
) => {
// Order by the memory placement, not source order.
@@ -537,7 +550,7 @@ fn univariant_uninterned(
abi = Abi::Uninhabited;
}
- Ok(Layout {
+ Ok(LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Arbitrary { offsets, memory_index },
abi,
@@ -547,7 +560,7 @@ fn univariant_uninterned(
})
}
- fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'tcx>> {
+ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result, LayoutError<'tcx>> {
let tcx = self.tcx;
let param_env = self.param_env;
let dl = self.data_layout();
@@ -556,7 +569,8 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
assert!(size.bits() <= 128);
Scalar { value, valid_range: WrappingRange { start: 0, end: size.unsigned_int_max() } }
};
- let scalar = |value: Primitive| tcx.intern_layout(Layout::scalar(self, scalar_unit(value)));
+ let scalar =
+ |value: Primitive| tcx.intern_layout(LayoutS::scalar(self, scalar_unit(value)));
let univariant = |fields: &[TyAndLayout<'_>], repr: &ReprOptions, kind| {
Ok(tcx.intern_layout(self.univariant_uninterned(ty, fields, repr, kind)?))
@@ -565,11 +579,11 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
Ok(match *ty.kind() {
// Basic scalars.
- ty::Bool => tcx.intern_layout(Layout::scalar(
+ ty::Bool => tcx.intern_layout(LayoutS::scalar(
self,
Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } },
)),
- ty::Char => tcx.intern_layout(Layout::scalar(
+ ty::Char => tcx.intern_layout(LayoutS::scalar(
self,
Scalar {
value: Int(I32, false),
@@ -585,11 +599,11 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
ty::FnPtr(_) => {
let mut ptr = scalar_unit(Pointer);
ptr.valid_range = ptr.valid_range.with_start(1);
- tcx.intern_layout(Layout::scalar(self, ptr))
+ tcx.intern_layout(LayoutS::scalar(self, ptr))
}
// The never type.
- ty::Never => tcx.intern_layout(Layout {
+ ty::Never => tcx.intern_layout(LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Primitive,
abi: Abi::Uninhabited,
@@ -607,13 +621,13 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
let pointee = tcx.normalize_erasing_regions(param_env, pointee);
if pointee.is_sized(tcx.at(DUMMY_SP), param_env) {
- return Ok(tcx.intern_layout(Layout::scalar(self, data_ptr)));
+ return Ok(tcx.intern_layout(LayoutS::scalar(self, data_ptr)));
}
let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
let metadata = match unsized_part.kind() {
ty::Foreign(..) => {
- return Ok(tcx.intern_layout(Layout::scalar(self, data_ptr)));
+ return Ok(tcx.intern_layout(LayoutS::scalar(self, data_ptr)));
}
ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
ty::Dynamic(..) => {
@@ -651,7 +665,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
let largest_niche = if count != 0 { element.largest_niche } else { None };
- tcx.intern_layout(Layout {
+ tcx.intern_layout(LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Array { stride: element.size, count },
abi,
@@ -662,7 +676,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
}
ty::Slice(element) => {
let element = self.layout_of(element)?;
- tcx.intern_layout(Layout {
+ tcx.intern_layout(LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Array { stride: element.size, count: 0 },
abi: Abi::Aggregate { sized: false },
@@ -671,7 +685,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
size: Size::ZERO,
})
}
- ty::Str => tcx.intern_layout(Layout {
+ ty::Str => tcx.intern_layout(LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
abi: Abi::Aggregate { sized: false },
@@ -775,7 +789,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
// Extract the number of elements from the layout of the array field:
let Ok(TyAndLayout {
- layout: Layout { fields: FieldsShape::Array { count, .. }, .. },
+ layout: Layout(Interned(LayoutS { fields: FieldsShape::Array { count, .. }, .. }, _)),
..
}) = self.layout_of(f0_ty) else {
return Err(LayoutError::Unknown(ty));
@@ -825,7 +839,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
FieldsShape::Array { stride: e_ly.size, count: e_len }
};
- tcx.intern_layout(Layout {
+ tcx.intern_layout(LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields,
abi: Abi::Vector { element: e_abi, count: e_len },
@@ -905,7 +919,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
align = align.min(AbiAndPrefAlign::new(pack));
}
- return Ok(tcx.intern_layout(Layout {
+ return Ok(tcx.intern_layout(LayoutS {
variants: Variants::Single { index },
fields: FieldsShape::Union(
NonZeroUsize::new(variants[index].len())
@@ -1100,17 +1114,17 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
align = align.max(st.align);
- Ok(st)
+ Ok(tcx.intern_layout(st))
})
.collect::, _>>()?;
- let offset = st[i].fields.offset(field_index) + niche.offset;
- let size = st[i].size;
+ let offset = st[i].fields().offset(field_index) + niche.offset;
+ let size = st[i].size();
- let abi = if st.iter().all(|v| v.abi.is_uninhabited()) {
+ let abi = if st.iter().all(|v| v.abi().is_uninhabited()) {
Abi::Uninhabited
} else {
- match st[i].abi {
+ match st[i].abi() {
Abi::Scalar(_) => Abi::Scalar(niche_scalar),
Abi::ScalarPair(first, second) => {
// We need to use scalar_unit to reset the
@@ -1130,7 +1144,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
let largest_niche = Niche::from_scalar(dl, offset, niche_scalar);
- niche_filling_layout = Some(Layout {
+ niche_filling_layout = Some(LayoutS {
variants: Variants::Multiple {
tag: niche_scalar,
tag_encoding: TagEncoding::Niche {
@@ -1377,7 +1391,10 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag);
- let tagged_layout = Layout {
+ let layout_variants =
+ layout_variants.into_iter().map(|v| tcx.intern_layout(v)).collect();
+
+ let tagged_layout = LayoutS {
variants: Variants::Multiple {
tag,
tag_encoding: TagEncoding::Direct,
@@ -1563,7 +1580,7 @@ fn generator_layout(
ty: Ty<'tcx>,
def_id: hir::def_id::DefId,
substs: SubstsRef<'tcx>,
- ) -> Result<&'tcx Layout, LayoutError<'tcx>> {
+ ) -> Result, LayoutError<'tcx>> {
use SavedLocalEligibility::*;
let tcx = self.tcx;
let subst_field = |ty: Ty<'tcx>| ty.subst(tcx, substs);
@@ -1586,7 +1603,7 @@ fn generator_layout(
value: Primitive::Int(discr_int, false),
valid_range: WrappingRange { start: 0, end: max_discr },
};
- let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag));
+ let tag_layout = self.tcx.intern_layout(LayoutS::scalar(self, tag));
let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
let promoted_layouts = ineligible_locals
@@ -1722,20 +1739,20 @@ fn generator_layout(
size = size.max(variant.size);
align = align.max(variant.align);
- Ok(variant)
+ Ok(tcx.intern_layout(variant))
})
.collect::, _>>()?;
size = size.align_to(align.abi);
- let abi = if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi.is_uninhabited())
- {
- Abi::Uninhabited
- } else {
- Abi::Aggregate { sized: true }
- };
+ let abi =
+ if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi().is_uninhabited()) {
+ Abi::Uninhabited
+ } else {
+ Abi::Aggregate { sized: true }
+ };
- let layout = tcx.intern_layout(Layout {
+ let layout = tcx.intern_layout(LayoutS {
variants: Variants::Multiple {
tag,
tag_encoding: TagEncoding::Direct,
@@ -2250,7 +2267,7 @@ fn ty_and_layout_for_variant(
ty::Adt(def, _) => def.variants[variant_index].fields.len(),
_ => bug!(),
};
- tcx.intern_layout(Layout {
+ tcx.intern_layout(LayoutS {
variants: Variants::Single { index: variant_index },
fields: match NonZeroUsize::new(fields) {
Some(fields) => FieldsShape::Union(fields),
@@ -2263,10 +2280,10 @@ fn ty_and_layout_for_variant(
})
}
- Variants::Multiple { ref variants, .. } => &variants[variant_index],
+ Variants::Multiple { ref variants, .. } => variants[variant_index],
};
- assert_eq!(layout.variants, Variants::Single { index: variant_index });
+ assert_eq!(*layout.variants(), Variants::Single { index: variant_index });
TyAndLayout { ty: this.ty, layout }
}
@@ -2284,8 +2301,10 @@ fn field_ty_or_layout<'tcx>(
) -> TyMaybeWithLayout<'tcx> {
let tcx = cx.tcx();
let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> {
- let layout = Layout::scalar(cx, tag);
- TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx) }
+ TyAndLayout {
+ layout: tcx.intern_layout(LayoutS::scalar(cx, tag)),
+ ty: tag.value.to_ty(tcx),
+ }
};
match *this.ty.kind() {
diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
index 7133724d07d..bd196f11879 100644
--- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
@@ -65,7 +65,7 @@ fn variant_discriminants<'tcx>(
Variants::Multiple { variants, .. } => variants
.iter_enumerated()
.filter_map(|(idx, layout)| {
- (layout.abi != Abi::Uninhabited)
+ (layout.abi() != Abi::Uninhabited)
.then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
})
.collect(),
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 4ef86371298..fb5e0272cc3 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -10,6 +10,7 @@
use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
use std::str::FromStr;
+use rustc_data_structures::intern::Interned;
use rustc_index::vec::{Idx, IndexVec};
use rustc_macros::HashStable_Generic;
use rustc_serialize::json::{Json, ToJson};
@@ -1024,7 +1025,7 @@ pub struct VariantIdx {
}
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub enum Variants {
+pub enum Variants<'a> {
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
Single { index: VariantIdx },
@@ -1038,7 +1039,7 @@ pub enum Variants {
tag: Scalar,
tag_encoding: TagEncoding,
tag_field: usize,
- variants: IndexVec,
+ variants: IndexVec>,
},
}
@@ -1146,8 +1147,8 @@ pub fn reserve(&self, cx: &C, count: u128) -> Option<(u128, Sc
}
}
-#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub struct Layout {
+#[derive(PartialEq, Eq, Hash, HashStable_Generic)]
+pub struct LayoutS<'a> {
/// Says where the fields are located within the layout.
pub fields: FieldsShape,
@@ -1158,7 +1159,7 @@ pub struct Layout {
///
/// To access all fields of this layout, both `fields` and the fields of the active variant
/// must be taken into account.
- pub variants: Variants,
+ pub variants: Variants<'a>,
/// The `abi` defines how this data is passed between functions, and it defines
/// value restrictions via `valid_range`.
@@ -1177,12 +1178,12 @@ pub struct Layout {
pub size: Size,
}
-impl Layout {
+impl<'a> LayoutS<'a> {
pub fn scalar(cx: &C, scalar: Scalar) -> Self {
let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
let size = scalar.value.size(cx);
let align = scalar.value.align(cx);
- Layout {
+ LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Primitive,
abi: Abi::Scalar(scalar),
@@ -1193,6 +1194,59 @@ pub fn scalar(cx: &C, scalar: Scalar) -> Self {
}
}
+impl<'a> fmt::Debug for LayoutS<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // This is how `Layout` used to print before it become
+ // `Interned`. We print it like this to avoid having to update
+ // expected output in a lot of tests.
+ f.debug_struct("Layout")
+ .field("fields", &self.fields)
+ .field("variants", &self.variants)
+ .field("abi", &self.abi)
+ .field("largest_niche", &self.largest_niche)
+ .field("align", &self.align)
+ .field("size", &self.size)
+ .finish()
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
+#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
+pub struct Layout<'a>(pub Interned<'a, LayoutS<'a>>);
+
+impl<'a> fmt::Debug for Layout<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // See comment on `::fmt` above.
+ self.0.0.fmt(f)
+ }
+}
+
+impl<'a> Layout<'a> {
+ pub fn fields(self) -> &'a FieldsShape {
+ &self.0.0.fields
+ }
+
+ pub fn variants(self) -> &'a Variants<'a> {
+ &self.0.0.variants
+ }
+
+ pub fn abi(self) -> Abi {
+ self.0.0.abi
+ }
+
+ pub fn largest_niche(self) -> Option {
+ self.0.0.largest_niche
+ }
+
+ pub fn align(self) -> AbiAndPrefAlign {
+ self.0.0.align
+ }
+
+ pub fn size(self) -> Size {
+ self.0.0.size
+ }
+}
+
/// The layout of a type, alongside the type itself.
/// Provides various type traversal APIs (e.g., recursing into fields).
///
@@ -1203,13 +1257,13 @@ pub fn scalar(cx: &C, scalar: Scalar) -> Self {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)]
pub struct TyAndLayout<'a, Ty> {
pub ty: Ty,
- pub layout: &'a Layout,
+ pub layout: Layout<'a>,
}
impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
- type Target = &'a Layout;
- fn deref(&self) -> &&'a Layout {
- &self.layout
+ type Target = &'a LayoutS<'a>;
+ fn deref(&self) -> &&'a LayoutS<'a> {
+ &self.layout.0.0
}
}
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index 2919743e499..e9ef71ede51 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -8,13 +8,14 @@
//! LLVM.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(bool_to_option)]
-#![feature(let_else)]
-#![feature(nll)]
-#![feature(never_type)]
#![feature(associated_type_bounds)]
+#![feature(bool_to_option)]
#![feature(exhaustive_patterns)]
+#![feature(let_else)]
#![feature(min_specialization)]
+#![feature(never_type)]
+#![feature(nll)]
+#![feature(rustc_attrs)]
#![feature(step_trait)]
use std::iter::FromIterator;
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index e84dc6c7240..68644a017a4 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1710,11 +1710,11 @@ struct update syntax will not work.",
}
fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
- fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
- if layout.abi.is_unsized() {
+ fn write_size_of_layout(w: &mut Buffer, layout: Layout<'_>, tag_size: u64) {
+ if layout.abi().is_unsized() {
write!(w, "(unsized)");
} else {
- let bytes = layout.size.bytes() - tag_size;
+ let bytes = layout.size().bytes() - tag_size;
write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },);
}
}
@@ -1744,7 +1744,7 @@ fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
write_size_of_layout(w, ty_layout.layout, 0);
writeln!(w, "
");
if let Variants::Multiple { variants, tag, tag_encoding, .. } =
- &ty_layout.layout.variants
+ &ty_layout.layout.variants()
{
if !variants.is_empty() {
w.write_str(
@@ -1767,7 +1767,7 @@ fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
for (index, layout) in variants.iter_enumerated() {
let name = adt.variants[index].name;
write!(w, "{name}
: ", name = name);
- write_size_of_layout(w, layout, tag_size);
+ write_size_of_layout(w, *layout, tag_size);
writeln!(w, "");
}
w.write_str("");
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
index 05eadab3e6c..81076776ed3 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -326,7 +326,7 @@ fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty);
if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty));
then {
- layout.layout.size.bytes() == 0
+ layout.layout.size().bytes() == 0
} else {
false
}