diff options
Diffstat (limited to 'compiler')
24 files changed, 92 insertions, 73 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index ef72e6efb94..48972321a9f 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -167,6 +167,7 @@ pub(crate) fn codegen_const_value<'tcx>( } match const_val { + ConstValue::ZeroSized => unreachable!(), // we already handles ZST above ConstValue::Scalar(x) => match x { Scalar::Int(int) => { if fx.clif_type(layout.ty).is_some() { diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index d156f874434..fc391f53f18 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -9,7 +9,6 @@ use rustc_codegen_ssa::traits::{ StaticMethods, }; use rustc_middle::mir::Mutability; -use rustc_middle::ty::ScalarInt; use rustc_middle::ty::layout::{TyAndLayout, LayoutOf}; use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar}; use rustc_target::abi::{self, HasDataLayout, Pointer, Size}; @@ -159,13 +158,13 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { None } + fn zst_to_backend(&self, _ty: Type<'gcc>) -> RValue<'gcc> { + self.const_undef(self.type_ix(0)) + } + fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> RValue<'gcc> { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { - Scalar::Int(ScalarInt::ZST) => { - assert_eq!(0, layout.size(self).bytes()); - self.const_undef(self.type_ix(0)) - } Scalar::Int(int) => { let data = int.assert_bits(layout.size(self)); diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index fc20dee4c74..77cbbf4c6ca 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -13,7 +13,6 @@ use rustc_codegen_ssa::traits::*; use rustc_middle::bug; use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar}; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; -use rustc_middle::ty::ScalarInt; use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer, Size}; use libc::{c_char, c_uint}; @@ -223,13 +222,13 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { }) } + fn zst_to_backend(&self, _llty: &'ll Type) -> &'ll Value { + self.const_undef(self.type_ix(0)) + } + fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) -> &'ll Value { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { - Scalar::Int(ScalarInt::ZST) => { - assert_eq!(0, layout.size(self).bytes()); - self.const_undef(self.type_ix(0)) - } Scalar::Int(int) => { let data = int.assert_bits(layout.size(self)); let llval = self.const_uint_big(self.type_ix(bitsize), data); diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 2e655ae94cc..c612634fce2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -84,6 +84,10 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout)); OperandValue::Immediate(llval) } + ConstValue::ZeroSized => { + let llval = bx.zst_to_backend(bx.immediate_backend_type(layout)); + OperandValue::Immediate(llval) + } ConstValue::Slice { data, start, end } => { let Abi::ScalarPair(a_scalar, _) = layout.abi else { bug!("from_const: invalid ScalarPair layout: {:#?}", layout); diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index fdc7a30e841..8a91d4735ba 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -29,6 +29,7 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value; fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: Self::Type) -> Self::Value; + fn zst_to_backend(&self, llty: Self::Type) -> Self::Value; fn from_const_alloc( &self, layout: TyAndLayout<'tcx>, diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index f84dd9521ee..b18976302b4 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -2,7 +2,7 @@ use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr}; use crate::interpret::eval_nullary_intrinsic; use crate::interpret::{ intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId, - Immediate, InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, Scalar, + Immediate, InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, ScalarMaybeUninit, StackPopCleanup, }; @@ -157,7 +157,7 @@ pub(super) fn op_to_const<'tcx>( "this MPlaceTy must come from a validated constant, thus we can assume the \ alignment is correct", ); - ConstValue::Scalar(Scalar::ZST) + ConstValue::ZeroSized } } }; diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index f8b390aaf50..2288a4e7b6c 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -272,7 +272,7 @@ pub fn valtree_to_const_value<'tcx>( match ty.kind() { ty::FnDef(..) => { assert!(valtree.unwrap_branch().is_empty()); - ConstValue::Scalar(Scalar::ZST) + ConstValue::ZeroSized } ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => match valtree { ty::ValTree::Leaf(scalar_int) => ConstValue::Scalar(Scalar::Int(scalar_int)), @@ -344,11 +344,7 @@ fn valtree_into_mplace<'tcx>( match ty.kind() { ty::FnDef(_, _) => { - ecx.write_immediate( - Immediate::Scalar(ScalarMaybeUninit::Scalar(Scalar::ZST)), - &place.into(), - ) - .unwrap(); + ecx.write_immediate(Immediate::Uninit, &place.into()).unwrap(); } ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => { let scalar_int = valtree.unwrap_leaf(); diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 576958a855d..d11ae7b4925 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -297,8 +297,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let Some(alloc) = self.get_place_alloc(mplace)? else { return Ok(Some(ImmTy { - // zero-sized type - imm: Scalar::ZST.into(), + // zero-sized type can be left uninit + imm: Immediate::Uninit, layout: mplace.layout, })); }; @@ -441,8 +441,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // This makes several assumptions about what layouts we will encounter; we match what // codegen does as good as we can (see `extract_field` in `rustc_codegen_ssa/src/mir/operand.rs`). let field_val: Immediate<_> = match (*base, base.layout.abi) { - // the field contains no information - _ if field_layout.is_zst() => Scalar::ZST.into(), + // the field contains no information, can be left uninit + _ if field_layout.is_zst() => Immediate::Uninit, // the field covers the entire type _ if field_layout.size == base.layout.size => { assert!(match (base.layout.abi, field_layout.abi) { @@ -553,8 +553,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { let layout = self.layout_of_local(frame, local, layout)?; let op = if layout.is_zst() { - // Do not read from ZST, they might not be initialized - Operand::Immediate(Scalar::ZST.into()) + // Bypass `access_local` (helps in ConstProp) + Operand::Immediate(Immediate::Uninit) } else { *M::access_local(frame, local)? }; @@ -709,6 +709,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Operand::Indirect(MemPlace::from_ptr(ptr.into())) } ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x)?.into()), + ConstValue::ZeroSized => Operand::Immediate(Immediate::Uninit), ConstValue::Slice { data, start, end } => { // We rely on mutability being set correctly in `data` to prevent writes // where none should happen. diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 46c34247d40..ef06c457bf4 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -59,6 +59,7 @@ #![feature(drain_filter)] #![feature(intra_doc_pointers)] #![feature(yeet_expr)] +#![feature(const_option)] #![recursion_limit = "512"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 8ecbb5ab0b3..22bbe29c105 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -29,11 +29,14 @@ pub struct ConstAlloc<'tcx> { #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] #[derive(HashStable)] pub enum ConstValue<'tcx> { - /// Used only for types with `layout::abi::Scalar` ABI and ZSTs. + /// Used only for types with `layout::abi::Scalar` ABI. /// /// Not using the enum `Value` to encode that this must not be `Uninit`. Scalar(Scalar), + /// Only used for ZSTs. + ZeroSized, + /// Used only for `&[u8]` and `&str` Slice { data: ConstAllocation<'tcx>, start: usize, end: usize }, @@ -55,6 +58,7 @@ impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> { fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ConstValue<'tcx>> { Some(match self { ConstValue::Scalar(s) => ConstValue::Scalar(s), + ConstValue::ZeroSized => ConstValue::ZeroSized, ConstValue::Slice { data, start, end } => { ConstValue::Slice { data: tcx.lift(data)?, start, end } } @@ -69,7 +73,7 @@ impl<'tcx> ConstValue<'tcx> { #[inline] pub fn try_to_scalar(&self) -> Option<Scalar<AllocId>> { match *self { - ConstValue::ByRef { .. } | ConstValue::Slice { .. } => None, + ConstValue::ByRef { .. } | ConstValue::Slice { .. } | ConstValue::ZeroSized => None, ConstValue::Scalar(val) => Some(val), } } @@ -111,10 +115,6 @@ impl<'tcx> ConstValue<'tcx> { pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self { ConstValue::Scalar(Scalar::from_machine_usize(i, cx)) } - - pub fn zst() -> Self { - Self::Scalar(Scalar::ZST) - } } /// A `Scalar` represents an immediate, primitive value existing outside of a @@ -194,8 +194,6 @@ impl<Tag> From<ScalarInt> for Scalar<Tag> { } impl<Tag> Scalar<Tag> { - pub const ZST: Self = Scalar::Int(ScalarInt::ZST); - #[inline(always)] pub fn from_pointer(ptr: Pointer<Tag>, cx: &impl HasDataLayout) -> Self { Scalar::Ptr(ptr, u8::try_from(cx.pointer_size().bytes()).unwrap()) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index f136b8e2368..fc8b3112b87 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1711,7 +1711,7 @@ impl<'tcx> Operand<'tcx> { Operand::Constant(Box::new(Constant { span, user_ty: None, - literal: ConstantKind::Val(ConstValue::zst(), ty), + literal: ConstantKind::Val(ConstValue::ZeroSized, ty), })) } @@ -2196,7 +2196,7 @@ impl<'tcx> ConstantKind<'tcx> { #[inline] pub fn zero_sized(ty: Ty<'tcx>) -> Self { - let cv = ConstValue::Scalar(Scalar::ZST); + let cv = ConstValue::ZeroSized; Self::Val(cv, ty) } @@ -2772,6 +2772,13 @@ fn pretty_print_const_value<'tcx>( fmt.write_str(&cx.into_buffer())?; return Ok(()); } + (ConstValue::ZeroSized, ty::FnDef(d, s)) => { + let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS); + cx.print_alloc_ids = true; + let cx = cx.print_value_path(*d, s)?; + fmt.write_str(&cx.into_buffer())?; + return Ok(()); + } // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading // their fields instead of just dumping the memory. _ => {} diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 24c6cd91d0a..e2fa37ee7be 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -448,7 +448,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { self.push(&format!("+ user_ty: {:?}", user_ty)); } + // FIXME: this is a poor version of `pretty_print_const_value`. let fmt_val = |val: &ConstValue<'tcx>| match val { + ConstValue::ZeroSized => format!("<ZST>"), ConstValue::Scalar(s) => format!("Scalar({:?})", s), ConstValue::Slice { .. } => format!("Slice(..)"), ConstValue::ByRef { .. } => format!("ByRef(..)"), @@ -679,6 +681,7 @@ pub fn write_allocations<'tcx>( ConstValue::Scalar(interpret::Scalar::Int { .. }) => { Either::Left(Either::Right(std::iter::empty())) } + ConstValue::ZeroSized => Either::Left(Either::Right(std::iter::empty())), ConstValue::ByRef { alloc, .. } | ConstValue::Slice { data: alloc, .. } => { Either::Right(alloc_ids_from_alloc(alloc)) } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 03c11c2863f..3fe6394ad7e 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -419,6 +419,10 @@ pub enum ExprKind<'tcx> { lit: ty::ScalarInt, user_ty: Option<Canonical<'tcx, UserType<'tcx>>>, }, + /// A literal of a ZST type. + ZstLiteral { + user_ty: Option<Canonical<'tcx, UserType<'tcx>>>, + }, /// Associated constants and named constants NamedConst { def_id: DefId, @@ -454,12 +458,6 @@ pub enum ExprKind<'tcx> { }, } -impl<'tcx> ExprKind<'tcx> { - pub fn zero_sized_literal(user_ty: Option<Canonical<'tcx, UserType<'tcx>>>) -> Self { - ExprKind::NonHirLiteral { lit: ty::ScalarInt::ZST, user_ty } - } -} - /// Represents the association of a field identifier and an expression. /// /// This is used in struct constructors. diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 8c8ebb0a6b8..c8d09875c28 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -129,6 +129,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {} Literal { lit: _, neg: _ } => {} NonHirLiteral { lit: _, user_ty: _ } => {} + ZstLiteral { user_ty: _ } => {} NamedConst { def_id: _, substs: _, user_ty: _ } => {} ConstParam { param: _, def_id: _ } => {} StaticRef { alloc_id: _, ty: _, def_id: _ } => {} diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index c7c2692281e..7436f0f6f4d 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -4,6 +4,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_target::abi::Size; use std::convert::{TryFrom, TryInto}; use std::fmt; +use std::num::NonZeroU8; use crate::ty::TyCtxt; @@ -123,7 +124,7 @@ pub struct ScalarInt { /// The first `size` bytes of `data` are the value. /// Do not try to read less or more bytes than that. The remaining bytes must be 0. data: u128, - size: u8, + size: NonZeroU8, } // Cannot derive these, as the derives take references to the fields, and we @@ -135,33 +136,31 @@ impl<CTX> crate::ty::HashStable<CTX> for ScalarInt { // Since `Self` is a packed struct, that would create a possibly unaligned reference, // which is UB. { self.data }.hash_stable(hcx, hasher); - self.size.hash_stable(hcx, hasher); + self.size.get().hash_stable(hcx, hasher); } } impl<S: Encoder> Encodable<S> for ScalarInt { fn encode(&self, s: &mut S) { s.emit_u128(self.data); - s.emit_u8(self.size); + s.emit_u8(self.size.get()); } } impl<D: Decoder> Decodable<D> for ScalarInt { fn decode(d: &mut D) -> ScalarInt { - ScalarInt { data: d.read_u128(), size: d.read_u8() } + ScalarInt { data: d.read_u128(), size: NonZeroU8::new(d.read_u8()).unwrap() } } } impl ScalarInt { - pub const TRUE: ScalarInt = ScalarInt { data: 1_u128, size: 1 }; + pub const TRUE: ScalarInt = ScalarInt { data: 1_u128, size: NonZeroU8::new(1).unwrap() }; - pub const FALSE: ScalarInt = ScalarInt { data: 0_u128, size: 1 }; - - pub const ZST: ScalarInt = ScalarInt { data: 0_u128, size: 0 }; + pub const FALSE: ScalarInt = ScalarInt { data: 0_u128, size: NonZeroU8::new(1).unwrap() }; #[inline] pub fn size(self) -> Size { - Size::from_bytes(self.size) + Size::from_bytes(self.size.get()) } /// Make sure the `data` fits in `size`. @@ -185,7 +184,7 @@ impl ScalarInt { #[inline] pub fn null(size: Size) -> Self { - Self { data: 0, size: size.bytes() as u8 } + Self { data: 0, size: NonZeroU8::new(size.bytes() as u8).unwrap() } } #[inline] @@ -197,7 +196,7 @@ impl ScalarInt { pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> { let data = i.into(); if size.truncate(data) == data { - Some(Self { data, size: size.bytes() as u8 }) + Some(Self { data, size: NonZeroU8::new(size.bytes() as u8).unwrap() }) } else { None } @@ -209,7 +208,7 @@ impl ScalarInt { // `into` performed sign extension, we have to truncate let truncated = size.truncate(i as u128); if size.sign_extend(truncated) as i128 == i { - Some(Self { data: truncated, size: size.bytes() as u8 }) + Some(Self { data: truncated, size: NonZeroU8::new(size.bytes() as u8).unwrap() }) } else { None } @@ -225,7 +224,7 @@ impl ScalarInt { #[inline] pub fn to_bits(self, target_size: Size) -> Result<u128, Size> { assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); - if target_size.bytes() == u64::from(self.size) { + if target_size.bytes() == u64::from(self.size.get()) { self.check_data(); Ok(self.data) } else { @@ -339,7 +338,7 @@ macro_rules! from { fn from(u: $ty) -> Self { Self { data: u128::from(u), - size: std::mem::size_of::<$ty>() as u8, + size: NonZeroU8::new(std::mem::size_of::<$ty>() as u8).unwrap(), } } } @@ -382,7 +381,7 @@ impl TryFrom<ScalarInt> for bool { impl From<char> for ScalarInt { #[inline] fn from(c: char) -> Self { - Self { data: c as u128, size: std::mem::size_of::<char>() as u8 } + Self { data: c as u128, size: NonZeroU8::new(std::mem::size_of::<char>() as u8).unwrap() } } } @@ -409,7 +408,7 @@ impl From<Single> for ScalarInt { #[inline] fn from(f: Single) -> Self { // We trust apfloat to give us properly truncated data. - Self { data: f.to_bits(), size: 4 } + Self { data: f.to_bits(), size: NonZeroU8::new((Single::BITS / 8) as u8).unwrap() } } } @@ -425,7 +424,7 @@ impl From<Double> for ScalarInt { #[inline] fn from(f: Double) -> Self { // We trust apfloat to give us properly truncated data. - Self { data: f.to_bits(), size: 8 } + Self { data: f.to_bits(), size: NonZeroU8::new((Double::BITS / 8) as u8).unwrap() } } } @@ -439,13 +438,8 @@ impl TryFrom<ScalarInt> for Double { impl fmt::Debug for ScalarInt { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.size == 0 { - self.check_data(); - write!(f, "<ZST>") - } else { - // Dispatch to LowerHex below. - write!(f, "0x{:x}", self) - } + // Dispatch to LowerHex below. + write!(f, "0x{:x}", self) } } @@ -463,7 +457,7 @@ impl fmt::LowerHex for ScalarInt { // would thus borrow `self.data`. Since `Self` // is a packed struct, that would create a possibly unaligned reference, which // is UB. - write!(f, "{:01$x}", { self.data }, self.size as usize * 2) + write!(f, "{:01$x}", { self.data }, self.size.get() as usize * 2) } } @@ -477,7 +471,7 @@ impl fmt::UpperHex for ScalarInt { // would thus borrow `self.data`. Since `Self` // is a packed struct, that would create a possibly unaligned reference, which // is UB. - write!(f, "{:01$X}", { self.data }, self.size as usize * 2) + write!(f, "{:01$X}", { self.data }, self.size.get() as usize * 2) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 887236c484b..f721a175c98 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1355,10 +1355,6 @@ pub trait PrettyPrinter<'tcx>: " as ", )?; } - // For function type zsts just printing the path is enough - ty::FnDef(d, s) if int == ScalarInt::ZST => { - p!(print_value_path(*d, s)) - } // Nontrivial types with scalar bit representation _ => { let print = |mut this: Self| { diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 3d6e50f0c06..648d10b9e42 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -49,11 +49,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { inferred_ty: ty, }) }); - let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty); Constant { span, user_ty: user_ty, literal } } + ExprKind::ZstLiteral { user_ty } => { + let user_ty = user_ty.map(|user_ty| { + this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { + span, + user_ty, + inferred_ty: ty, + }) + }); + let literal = ConstantKind::Val(ConstValue::ZeroSized, ty); + + Constant { span, user_ty: user_ty, literal } + } ExprKind::NamedConst { def_id, substs, user_ty } => { let user_ty = user_ty.map(|user_ty| { this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index e77f5931dd6..e88f9dc1f08 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -603,6 +603,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Literal { .. } | ExprKind::NamedConst { .. } | ExprKind::NonHirLiteral { .. } + | ExprKind::ZstLiteral { .. } | ExprKind::ConstParam { .. } | ExprKind::ConstBlock { .. } | ExprKind::StaticRef { .. } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index e3a383f86a7..15f2d17c4e0 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -415,6 +415,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Literal { .. } | ExprKind::NamedConst { .. } | ExprKind::NonHirLiteral { .. } + | ExprKind::ZstLiteral { .. } | ExprKind::ConstParam { .. } | ExprKind::ConstBlock { .. } | ExprKind::StaticRef { .. } => { diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs index b1a70643934..a4386319dc1 100644 --- a/compiler/rustc_mir_build/src/build/expr/category.rs +++ b/compiler/rustc_mir_build/src/build/expr/category.rs @@ -72,6 +72,7 @@ impl Category { ExprKind::ConstBlock { .. } | ExprKind::Literal { .. } | ExprKind::NonHirLiteral { .. } + | ExprKind::ZstLiteral { .. } | ExprKind::ConstParam { .. } | ExprKind::StaticRef { .. } | ExprKind::NamedConst { .. } => Some(Category::Constant), diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index cffb67ef013..017d43d10a9 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -559,6 +559,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Literal { .. } | ExprKind::NamedConst { .. } | ExprKind::NonHirLiteral { .. } + | ExprKind::ZstLiteral { .. } | ExprKind::ConstParam { .. } | ExprKind::ThreadLocalRef(_) | ExprKind::StaticRef { .. } => { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 94b2722dca8..8585199faaf 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -307,6 +307,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { | ExprKind::Literal { .. } | ExprKind::NamedConst { .. } | ExprKind::NonHirLiteral { .. } + | ExprKind::ZstLiteral { .. } | ExprKind::ConstParam { .. } | ExprKind::ConstBlock { .. } | ExprKind::Deref { .. } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 4bc3d216a40..4eb3607e9cc 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -799,7 +799,7 @@ impl<'tcx> Cx<'tcx> { } }; let ty = self.tcx().mk_fn_def(def_id, substs); - Expr { temp_lifetime, ty, span, kind: ExprKind::zero_sized_literal(user_ty) } + Expr { temp_lifetime, ty, span, kind: ExprKind::ZstLiteral { user_ty } } } fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId { @@ -828,7 +828,7 @@ impl<'tcx> Cx<'tcx> { | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(_) => { let user_ty = self.user_substs_applied_to_res(expr.hir_id, res); - ExprKind::zero_sized_literal(user_ty) + ExprKind::ZstLiteral { user_ty } } Res::Def(DefKind::ConstParam, def_id) => { diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index f9b4a1583cc..3a152eff485 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -451,6 +451,10 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { let val = ty::ValTree::from_scalar_int(lit); self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty))) } + &ExprKind::ZstLiteral { user_ty: _ } => { + let val = ty::ValTree::zst(); + self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty))) + } &ExprKind::NamedConst { def_id, substs, user_ty: _ } => { let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); |
