From a422b421597202554a76bee32d07b54a15631681 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 3 Jul 2022 11:17:23 -0400 Subject: [PATCH] don't allow ZST in ScalarInt There are several indications that we should not ZST as a ScalarInt: - We had two ways to have ZST valtrees, either an empty `Branch` or a `Leaf` with a ZST in it. `ValTree::zst()` used the former, but the latter could possibly arise as well. - Likewise, the interpreter had `Immediate::Uninit` and `Immediate::Scalar(Scalar::ZST)`. - LLVM codegen already had to special-case ZST ScalarInt. So instead add new ZST variants to those types that did not have other variants which could be used for this purpose. --- compiler/rustc_codegen_llvm/src/common.rs | 9 ++-- compiler/rustc_codegen_ssa/src/mir/operand.rs | 4 ++ .../rustc_codegen_ssa/src/traits/consts.rs | 1 + .../src/const_eval/eval_queries.rs | 4 +- .../src/const_eval/valtrees.rs | 8 +--- .../rustc_const_eval/src/interpret/operand.rs | 13 +++--- compiler/rustc_middle/src/lib.rs | 1 + .../rustc_middle/src/mir/interpret/value.rs | 14 +++--- compiler/rustc_middle/src/mir/mod.rs | 4 +- compiler/rustc_middle/src/mir/pretty.rs | 2 + compiler/rustc_middle/src/thir.rs | 6 ++- compiler/rustc_middle/src/thir/visit.rs | 1 + compiler/rustc_middle/src/ty/consts/int.rs | 46 ++++++++----------- compiler/rustc_middle/src/ty/print/pretty.rs | 4 -- .../src/build/expr/as_constant.rs | 13 +++++- .../src/build/expr/as_place.rs | 1 + .../src/build/expr/as_rvalue.rs | 1 + .../src/build/expr/category.rs | 1 + .../rustc_mir_build/src/build/expr/into.rs | 1 + .../rustc_mir_build/src/check_unsafety.rs | 1 + .../src/traits/const_evaluatable.rs | 4 ++ 21 files changed, 78 insertions(+), 61 deletions(-) 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_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 @@ fn const_to_opt_u128(&self, v: &'ll Value, sign_ext: bool) -> Option { }) } + 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..72d0d3e5482 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -84,6 +84,10 @@ pub fn from_const>( let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout)); OperandValue::Immediate(llval) } + ConstValue::ZST => { + 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..251be589649 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 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::ZST } } }; diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index f8b390aaf50..0ef55c63085 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::ZST } 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..c95ae4f6e7a 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -297,8 +297,8 @@ fn read_immediate_from_mplace_raw( 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 @@ pub fn operand_field( // 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 @@ pub fn local_to_op( ) -> 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 @@ pub(crate) fn const_val_to_op( Operand::Indirect(MemPlace::from_ptr(ptr.into())) } ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x)?.into()), + ConstValue::ZST => 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..59242b785c6 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. + ZST, + /// 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> { Some(match self { ConstValue::Scalar(s) => ConstValue::Scalar(s), + ConstValue::ZST => ConstValue::ZST, 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> { match *self { - ConstValue::ByRef { .. } | ConstValue::Slice { .. } => None, + ConstValue::ByRef { .. } | ConstValue::Slice { .. } | ConstValue::ZST => None, ConstValue::Scalar(val) => Some(val), } } @@ -111,10 +115,6 @@ pub fn from_u64(i: u64) -> Self { 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 @@ fn from(ptr: ScalarInt) -> Self { } impl Scalar { - pub const ZST: Self = Scalar::Int(ScalarInt::ZST); - #[inline(always)] pub fn from_pointer(ptr: Pointer, 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..532b7f2bf0c 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1711,7 +1711,7 @@ pub fn function_handle( Operand::Constant(Box::new(Constant { span, user_ty: None, - literal: ConstantKind::Val(ConstValue::zst(), ty), + literal: ConstantKind::Val(ConstValue::ZST, ty), })) } @@ -2196,7 +2196,7 @@ pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self { #[inline] pub fn zero_sized(ty: Ty<'tcx>) -> Self { - let cv = ConstValue::Scalar(Scalar::ZST); + let cv = ConstValue::ZST; Self::Val(cv, ty) } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 24c6cd91d0a..453e33efdd2 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -449,6 +449,7 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, _location: Location) { } let fmt_val = |val: &ConstValue<'tcx>| match val { + ConstValue::ZST => format!("ZST"), ConstValue::Scalar(s) => format!("Scalar({:?})", s), ConstValue::Slice { .. } => format!("Slice(..)"), ConstValue::ByRef { .. } => format!("ByRef(..)"), @@ -679,6 +680,7 @@ fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator { Either::Left(Either::Right(std::iter::empty())) } + ConstValue::ZST => 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..1938c56768d 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>>, }, + /// A literal of a ZST type. + ZstLiteral { + user_ty: Option>>, + }, /// Associated constants and named constants NamedConst { def_id: DefId, @@ -456,7 +460,7 @@ pub enum ExprKind<'tcx> { impl<'tcx> ExprKind<'tcx> { pub fn zero_sized_literal(user_ty: Option>>) -> Self { - ExprKind::NonHirLiteral { lit: ty::ScalarInt::ZST, user_ty } + ExprKind::ZstLiteral { user_ty } } } 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_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 @@ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut crate::ty::StableHasher) { // 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 Encodable 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 Decodable 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 @@ fn check_data(self) { #[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 @@ pub fn is_null(self) -> bool { pub fn try_from_uint(i: impl Into, size: Size) -> Option { 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 @@ pub fn try_from_int(i: impl Into, size: Size) -> Option { // `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 @@ pub fn assert_bits(self, target_size: Size) -> u128 { #[inline] pub fn to_bits(self, target_size: Size) -> Result { 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 @@ impl From<$ty> for ScalarInt { 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 @@ fn try_from(int: ScalarInt) -> Result { impl From for ScalarInt { #[inline] fn from(c: char) -> Self { - Self { data: c as u128, size: std::mem::size_of::() as u8 } + Self { data: c as u128, size: NonZeroU8::new(std::mem::size_of::() as u8).unwrap() } } } @@ -409,7 +408,7 @@ impl From 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 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 @@ fn try_from(int: ScalarInt) -> Result { impl fmt::Debug for ScalarInt { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.size == 0 { - self.check_data(); - write!(f, "") - } else { - // Dispatch to LowerHex below. - write!(f, "0x{:x}", self) - } + // Dispatch to LowerHex below. + write!(f, "0x{:x}", self) } } @@ -463,7 +457,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // 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 @@ fn pretty_print_const_scalar_int( " 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..c3af9f2d2b7 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 @@ pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'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::ZST, 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 @@ fn expr_as_place( | 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 @@ pub(crate) fn as_rvalue( 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 @@ pub(crate) fn of(ek: &ExprKind<'_>) -> Option { 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 @@ pub(crate) fn expr_into_dest( | 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 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) { | ExprKind::Literal { .. } | ExprKind::NamedConst { .. } | ExprKind::NonHirLiteral { .. } + | ExprKind::ZstLiteral { .. } | ExprKind::ConstParam { .. } | ExprKind::ConstBlock { .. } | ExprKind::Deref { .. } 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 @@ fn recurse_build(&mut self, node: thir::ExprId) -> Result { + 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); -- GitLab