diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 89fd0bfa8bbfa..ffa629ca16c8b 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -21,7 +21,7 @@ pub(crate) fn pointer_ty(tcx: TyCtxt<'_>) -> types::Type { } pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type { - match scalar.value { + match scalar.primitive() { Primitive::Int(int, _sign) => match int { Integer::I8 => types::I8, Integer::I16 => types::I16, diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index 6b2893fdaeb29..357cb4a6d246f 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs @@ -105,7 +105,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>( // Decode the discriminant (specifically if it's niche-encoded). match *tag_encoding { TagEncoding::Direct => { - let signed = match tag_scalar.value { + let signed = match tag_scalar.primitive() { Int(_, signed) => signed, _ => false, }; diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index afe8797a03009..8f80b02ae0d4e 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -50,7 +50,7 @@ fn codegen_field<'tcx>( } fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: Scalar, b_scalar: Scalar) -> Offset32 { - let b_offset = a_scalar.value.size(&tcx).align_to(b_scalar.value.align(&tcx).abi); + let b_offset = a_scalar.size(&tcx).align_to(b_scalar.align(&tcx).abi); Offset32::new(b_offset.bytes().try_into().unwrap()) } diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 21c7d420b204d..41f88f119e2a2 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -694,11 +694,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn scalar_load_metadata<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, load: RValue<'gcc>, scalar: &abi::Scalar) { - let vr = scalar.valid_range.clone(); - match scalar.value { + let vr = scalar.valid_range(bx); + match scalar.primitive() { abi::Int(..) => { if !scalar.is_always_valid(bx) { - bx.range_metadata(load, scalar.valid_range); + bx.range_metadata(load, vr); } } abi::Pointer if vr.start < vr.end && !vr.contains(0) => { @@ -720,7 +720,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { OperandValue::Immediate(self.to_immediate(load, place.layout)) } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi { - let b_offset = a.value.size(self).align_to(b.value.align(self).abi); + let b_offset = a.size(self).align_to(b.align(self).abi); let pair_type = place.layout.gcc_type(self, false); let mut load = |i, scalar: &abi::Scalar, align| { diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 19127c7612d8f..b056b6d473042 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -158,14 +158,14 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> RValue<'gcc> { - let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() }; + let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { Scalar::Int(ScalarInt::ZST) => { - assert_eq!(0, layout.value.size(self).bytes()); + assert_eq!(0, layout.size(self).bytes()); self.const_undef(self.type_ix(0)) } Scalar::Int(int) => { - let data = int.assert_bits(layout.value.size(self)); + let data = int.assert_bits(layout.size(self)); // FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code // the paths for floating-point values. @@ -209,7 +209,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let base_addr = self.const_bitcast(base_addr, self.usize_type); let offset = self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64); let ptr = self.const_bitcast(base_addr + offset, ptr_type); - if layout.value != Pointer { + if layout.primitive() != Pointer { self.const_bitcast(ptr.dereference(None).to_rvalue(), ty) } else { diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index de52f3ea2255e..3dc456f1aa0e9 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -328,7 +328,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl interpret::Pointer::new(alloc_id, Size::from_bytes(ptr_offset)), &cx.tcx, ), - abi::Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } }, + abi::Scalar::Initialized { value: Primitive::Pointer, valid_range: WrappingRange::full(dl.pointer_size) }, cx.type_i8p(), )); next_offset = offset + pointer_size; diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index ed8f0445ca3e2..2c042ba4e3a9e 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -224,7 +224,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { } fn scalar_gcc_type_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, scalar: &abi::Scalar, offset: Size) -> Type<'gcc> { - match scalar.value { + match scalar.primitive() { Int(i, true) => cx.type_from_integer(i), Int(i, false) => cx.type_from_unsigned_integer(i), F32 => cx.type_f32(), @@ -282,7 +282,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { Size::ZERO } else { - a.value.size(cx).align_to(b.value.align(cx).abi) + a.size(cx).align_to(b.align(cx).abi) }; self.scalar_gcc_type_at(cx, scalar, offset) } diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index b14a4f28c756c..b9baa87bac7c7 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -510,9 +510,9 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { // If the value is a boolean, the range is 0..2 and that ultimately // become 0..0 when the type becomes i1, which would be rejected // by the LLVM verifier. - if let Int(..) = scalar.value { + if let Int(..) = scalar.primitive() { if !scalar.is_bool() && !scalar.is_always_valid(bx) { - bx.range_metadata(callsite, scalar.valid_range); + bx.range_metadata(callsite, scalar.valid_range(bx)); } } } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 96c7d884b7b20..03c390b4bd427 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -753,7 +753,7 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' /// Helper function to get the LLVM type for a Scalar. Pointers are returned as /// the equivalent integer type. fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Type { - match scalar.value { + match scalar.primitive() { Primitive::Int(Integer::I8, _) => cx.type_i8(), Primitive::Int(Integer::I16, _) => cx.type_i16(), Primitive::Int(Integer::I32, _) => cx.type_i32(), @@ -774,7 +774,7 @@ fn llvm_fixup_input<'ll, 'tcx>( ) -> &'ll Value { match (reg, layout.abi) { (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => { - if let Primitive::Int(Integer::I8, _) = s.value { + if let Primitive::Int(Integer::I8, _) = s.primitive() { let vec_ty = bx.cx.type_vector(bx.cx.type_i8(), 8); bx.insert_element(bx.const_undef(vec_ty), value, bx.const_i32(0)) } else { @@ -785,7 +785,7 @@ fn llvm_fixup_input<'ll, 'tcx>( let elem_ty = llvm_asm_scalar_type(bx.cx, s); let count = 16 / layout.size.bytes(); let vec_ty = bx.cx.type_vector(elem_ty, count); - if let Primitive::Pointer = s.value { + if let Primitive::Pointer = s.primitive() { value = bx.ptrtoint(value, bx.cx.type_isize()); } bx.insert_element(bx.const_undef(vec_ty), value, bx.const_i32(0)) @@ -800,7 +800,7 @@ fn llvm_fixup_input<'ll, 'tcx>( bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices)) } (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s)) - if s.value == Primitive::F64 => + if s.primitive() == Primitive::F64 => { bx.bitcast(value, bx.cx.type_i64()) } @@ -812,7 +812,7 @@ fn llvm_fixup_input<'ll, 'tcx>( InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I32, _) = s.value { + if let Primitive::Int(Integer::I32, _) = s.primitive() { bx.bitcast(value, bx.cx.type_f32()) } else { value @@ -826,19 +826,21 @@ fn llvm_fixup_input<'ll, 'tcx>( ), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I64, _) = s.value { + if let Primitive::Int(Integer::I64, _) = s.primitive() { bx.bitcast(value, bx.cx.type_f64()) } else { value } } - (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value { - // MIPS only supports register-length arithmetics. - Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()), - Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()), - Primitive::F64 => bx.bitcast(value, bx.cx.type_i64()), - _ => value, - }, + (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => { + match s.primitive() { + // MIPS only supports register-length arithmetics. + Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()), + Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()), + Primitive::F64 => bx.bitcast(value, bx.cx.type_i64()), + _ => value, + } + } _ => value, } } @@ -852,7 +854,7 @@ fn llvm_fixup_output<'ll, 'tcx>( ) -> &'ll Value { match (reg, layout.abi) { (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => { - if let Primitive::Int(Integer::I8, _) = s.value { + if let Primitive::Int(Integer::I8, _) = s.primitive() { bx.extract_element(value, bx.const_i32(0)) } else { value @@ -860,7 +862,7 @@ fn llvm_fixup_output<'ll, 'tcx>( } (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) => { value = bx.extract_element(value, bx.const_i32(0)); - if let Primitive::Pointer = s.value { + if let Primitive::Pointer = s.primitive() { value = bx.inttoptr(value, layout.llvm_type(bx.cx)); } value @@ -875,7 +877,7 @@ fn llvm_fixup_output<'ll, 'tcx>( bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices)) } (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s)) - if s.value == Primitive::F64 => + if s.primitive() == Primitive::F64 => { bx.bitcast(value, bx.cx.type_f64()) } @@ -887,7 +889,7 @@ fn llvm_fixup_output<'ll, 'tcx>( InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I32, _) = s.value { + if let Primitive::Int(Integer::I32, _) = s.primitive() { bx.bitcast(value, bx.cx.type_i32()) } else { value @@ -901,20 +903,22 @@ fn llvm_fixup_output<'ll, 'tcx>( ), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I64, _) = s.value { + if let Primitive::Int(Integer::I64, _) = s.primitive() { bx.bitcast(value, bx.cx.type_i64()) } else { value } } - (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value { - // MIPS only supports register-length arithmetics. - Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()), - Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()), - Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()), - Primitive::F64 => bx.bitcast(value, bx.cx.type_f64()), - _ => value, - }, + (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => { + match s.primitive() { + // MIPS only supports register-length arithmetics. + Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()), + Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()), + Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()), + Primitive::F64 => bx.bitcast(value, bx.cx.type_f64()), + _ => value, + } + } _ => value, } } @@ -927,7 +931,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>( ) -> &'ll Type { match (reg, layout.abi) { (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => { - if let Primitive::Int(Integer::I8, _) = s.value { + if let Primitive::Int(Integer::I8, _) = s.primitive() { cx.type_vector(cx.type_i8(), 8) } else { layout.llvm_type(cx) @@ -946,7 +950,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>( cx.type_vector(elem_ty, count * 2) } (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s)) - if s.value == Primitive::F64 => + if s.primitive() == Primitive::F64 => { cx.type_i64() } @@ -958,7 +962,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>( InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I32, _) = s.value { + if let Primitive::Int(Integer::I32, _) = s.primitive() { cx.type_f32() } else { layout.llvm_type(cx) @@ -972,19 +976,21 @@ fn llvm_fixup_output_type<'ll, 'tcx>( ), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I64, _) = s.value { + if let Primitive::Int(Integer::I64, _) = s.primitive() { cx.type_f64() } else { layout.llvm_type(cx) } } - (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value { - // MIPS only supports register-length arithmetics. - Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(), - Primitive::F32 => cx.type_i32(), - Primitive::F64 => cx.type_i64(), - _ => layout.llvm_type(cx), - }, + (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => { + match s.primitive() { + // MIPS only supports register-length arithmetics. + Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(), + Primitive::F32 => cx.type_i32(), + Primitive::F64 => cx.type_i64(), + _ => layout.llvm_type(cx), + } + } _ => layout.llvm_type(cx), } } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 1bbfc13e05e75..88b87951ecd35 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -484,14 +484,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { bx.noundef_metadata(load); } - match scalar.value { + match scalar.primitive() { abi::Int(..) => { if !scalar.is_always_valid(bx) { - bx.range_metadata(load, scalar.valid_range); + bx.range_metadata(load, scalar.valid_range(bx)); } } abi::Pointer => { - if !scalar.valid_range.contains(0) { + if !scalar.valid_range(bx).contains(0) { bx.nonnull_metadata(load); } @@ -525,7 +525,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { }); OperandValue::Immediate(self.to_immediate(llval, place.layout)) } else if let abi::Abi::ScalarPair(a, b) = place.layout.abi { - let b_offset = a.value.size(self).align_to(b.value.align(self).abi); + let b_offset = a.size(self).align_to(b.align(self).abi); let pair_ty = place.layout.llvm_type(self); let mut load = |i, scalar: abi::Scalar, layout, align, offset| { diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index a85b2e6141b55..b69d7a000ee9a 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -221,16 +221,16 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) -> &'ll Value { - let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() }; + let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { Scalar::Int(ScalarInt::ZST) => { - assert_eq!(0, layout.value.size(self).bytes()); + assert_eq!(0, layout.size(self).bytes()); self.const_undef(self.type_ix(0)) } Scalar::Int(int) => { - let data = int.assert_bits(layout.value.size(self)); + let data = int.assert_bits(layout.size(self)); let llval = self.const_uint_big(self.type_ix(bitsize), data); - if layout.value == Pointer { + if layout.primitive() == Pointer { unsafe { llvm::LLVMConstIntToPtr(llval, llty) } } else { self.const_bitcast(llval, llty) @@ -269,7 +269,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { 1, ) }; - if layout.value != Pointer { + if layout.primitive() != Pointer { unsafe { llvm::LLVMConstPtrToInt(llval, llty) } } else { self.const_bitcast(llval, llty) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 413ef0ba76464..cb4073528e10a 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -109,7 +109,10 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation< Pointer::new(alloc_id, Size::from_bytes(ptr_offset)), &cx.tcx, ), - Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } }, + Scalar::Initialized { + value: Primitive::Pointer, + valid_range: WrappingRange::full(dl.pointer_size), + }, cx.type_i8p_ext(address_space), )); next_offset = offset + pointer_size; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 1eafa9501c47f..73e01d0453b25 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -118,7 +118,7 @@ fn tag_base_type<'ll, 'tcx>( Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } => { // Niche tags are always normalized to unsized integers of the correct size. - match tag.value { + match tag.primitive() { Primitive::Int(t, _) => t, Primitive::F32 => Integer::I32, Primitive::F64 => Integer::I64, @@ -136,7 +136,7 @@ fn tag_base_type<'ll, 'tcx>( Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. } => { // Direct tags preserve the sign. - tag.value.to_ty(cx.tcx) + tag.primitive().to_ty(cx.tcx) } } } @@ -425,7 +425,7 @@ fn compute_discriminant_value<'ll, 'tcx>( let value = (variant_index.as_u32() as u128) .wrapping_sub(niche_variants.start().as_u32() as u128) .wrapping_add(niche_start); - let value = tag.value.size(cx).truncate(value); + let value = tag.size(cx).truncate(value); // NOTE(eddyb) do *NOT* remove this assert, until // we pass the full 128-bit value to LLVM, otherwise // truncation will be silent and remain undetected. diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index f4dc33452d153..48840c76cac8b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -134,7 +134,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { sym::va_arg => { match fn_abi.ret.layout.abi { abi::Abi::Scalar(scalar) => { - match scalar.value { + match scalar.primitive() { Primitive::Int(..) => { if self.cx().size_of(ret_ty).bytes() < 4 { // `va_arg` should not be called on an integer type diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 757aa9a101167..862805236311d 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -309,7 +309,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { scalar: Scalar, offset: Size, ) -> &'a Type { - match scalar.value { + match scalar.primitive() { Int(i, _) => cx.type_from_integer(i), F32 => cx.type_f32(), F64 => cx.type_f64(), @@ -362,8 +362,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { return cx.type_i1(); } - let offset = - if index == 0 { Size::ZERO } else { a.value.size(cx).align_to(b.value.align(cx).abi) }; + let offset = if index == 0 { Size::ZERO } else { a.size(cx).align_to(b.align(cx).abi) }; self.scalar_llvm_type_at(cx, scalar, offset) } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index ffc8f55bc0cb3..369ca950e87be 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -464,13 +464,13 @@ fn push_debuginfo_type_name<'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().valid_range; let min = dataful_discriminant_range.start; - let min = tag.value.size(&tcx).truncate(min); + let min = tag.size(&tcx).truncate(min); let max = dataful_discriminant_range.end; - let max = tag.value.size(&tcx).truncate(max); + let max = tag.size(&tcx).truncate(max); let dataful_variant_name = variant_name(*dataful_variant); write!(output, ", {}, {}, {}", min, max, dataful_variant_name).unwrap(); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index a87daa8d6b80b..b7d760bfbabe1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1572,7 +1572,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match (src.layout.abi, dst.layout.abi) { (abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => { // HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers. - if (src_scalar.value == abi::Pointer) == (dst_scalar.value == abi::Pointer) { + if (src_scalar.primitive() == abi::Pointer) + == (dst_scalar.primitive() == abi::Pointer) + { assert_eq!(src.layout.size, dst.layout.size); // NOTE(eddyb) the `from_immediate` and `to_immediate_scalar` diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 858f71ebc3933..08be4c0a7b622 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -207,11 +207,11 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { // Extract a scalar component from a pair. (OperandValue::Pair(a_llval, b_llval), Abi::ScalarPair(a, b)) => { if offset.bytes() == 0 { - assert_eq!(field.size, a.value.size(bx.cx())); + assert_eq!(field.size, a.size(bx.cx())); OperandValue::Immediate(a_llval) } else { - assert_eq!(offset, a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi)); - assert_eq!(field.size, b.value.size(bx.cx())); + assert_eq!(offset, a.size(bx.cx()).align_to(b.align(bx.cx()).abi)); + assert_eq!(field.size, b.size(bx.cx())); OperandValue::Immediate(b_llval) } } @@ -316,7 +316,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout); }; let ty = bx.backend_type(dest.layout); - let b_offset = a_scalar.value.size(bx).align_to(b_scalar.value.align(bx).abi); + let b_offset = a_scalar.size(bx).align_to(b_scalar.align(bx).abi); let llptr = bx.struct_gep(ty, dest.llval, 0); let val = bx.from_immediate(a); diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 17cfb6c5dfb54..cf69c8fd8fda9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { self.llval } Abi::ScalarPair(a, b) - if offset == a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi) => + if offset == a.size(bx.cx()).align_to(b.align(bx.cx()).abi) => { // Offset matches second field. let ty = bx.backend_type(self.layout); @@ -234,7 +234,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // Decode the discriminant (specifically if it's niche-encoded). match *tag_encoding { TagEncoding::Direct => { - let signed = match tag_scalar.value { + let signed = match tag_scalar.primitive() { // We use `i1` for bytes that are always `0` or `1`, // e.g., `#[repr(i8)] enum E { A, B }`, but we can't // let LLVM interpret the `i1` as signed, because diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 68decce82ab52..fd29c9e281b92 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -299,7 +299,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let mut signed = false; if let Abi::Scalar(scalar) = operand.layout.abi { - if let Int(_, s) = scalar.value { + if let Int(_, s) = scalar.primitive() { // We use `i1` for bytes that are always `0` or `1`, // e.g., `#[repr(i8)] enum E { A, B }`, but we can't // let LLVM interpret the `i1` as signed, because @@ -307,15 +307,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { signed = !scalar.is_bool() && s; if !scalar.is_always_valid(bx.cx()) - && scalar.valid_range.end >= scalar.valid_range.start + && scalar.valid_range(bx.cx()).end + >= scalar.valid_range(bx.cx()).start { // We want `table[e as usize ± k]` to not // have bound checks, and this is the most // convenient place to put the `assume`s. - if scalar.valid_range.start > 0 { - let enum_value_lower_bound = bx - .cx() - .const_uint_big(ll_t_in, scalar.valid_range.start); + if scalar.valid_range(bx.cx()).start > 0 { + let enum_value_lower_bound = bx.cx().const_uint_big( + ll_t_in, + scalar.valid_range(bx.cx()).start, + ); let cmp_start = bx.icmp( IntPredicate::IntUGE, llval, @@ -324,8 +326,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.assume(cmp_start); } - let enum_value_upper_bound = - bx.cx().const_uint_big(ll_t_in, scalar.valid_range.end); + let enum_value_upper_bound = bx + .cx() + .const_uint_big(ll_t_in, scalar.valid_range(bx.cx()).end); let cmp_end = bx.icmp( IntPredicate::IntULE, llval, 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 b81a4bfe149dc..b856d1708abc9 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, subst::Subst, TyCtxt}; use rustc_span::source_map::Span; -use rustc_target::abi::Abi; +use rustc_target::abi::{self, Abi}; use std::borrow::Cow; use std::convert::TryInto; @@ -118,7 +118,7 @@ pub(super) fn op_to_const<'tcx>( // the usual cases of extracting e.g. a `usize`, without there being a real use case for the // `Undef` situation. let try_as_immediate = match op.layout.abi { - Abi::Scalar(..) => true, + Abi::Scalar(abi::Scalar::Initialized { .. }) => true, Abi::ScalarPair(..) => match op.layout.ty.kind() { ty::Ref(_, inner, _) => match *inner.kind() { ty::Slice(elem) => elem == ecx.tcx.types.u8, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index a956a478cef9e..3cc237faf695c 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -188,7 +188,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = self.read_scalar(&args[0])?.check_init()?; let bits = val.to_bits(layout_of.size)?; let kind = match layout_of.abi { - Abi::Scalar(scalar) => scalar.value, + Abi::Scalar(scalar) => scalar.primitive(), _ => span_bug!( self.cur_span(), "{} called on invalid type {:?}", diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 3012f763b80c0..ee1ba60829316 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer}; use rustc_middle::ty::{ConstInt, DelaySpanBugEmitted, Ty}; use rustc_middle::{mir, ty}; -use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding}; +use rustc_target::abi::{self, Abi, HasDataLayout, Size, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; use super::{ @@ -265,16 +265,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { })); }; + // It may seem like all types with `Scalar` or `ScalarPair` ABI are fair game at this point. + // However, `MaybeUninit` is considered a `Scalar` as far as its layout is concerned -- + // and yet cannot be represented by an interpreter `Scalar`, since we have to handle the + // case where some of the bytes are initialized and others are not. So, we need an extra + // check that walks over the type of `mplace` to make sure it is truly correct to treat this + // like a `Scalar` (or `ScalarPair`). match mplace.layout.abi { - Abi::Scalar(..) => { + Abi::Scalar(abi::Scalar::Initialized { .. }) => { let scalar = alloc.read_scalar(alloc_range(Size::ZERO, mplace.layout.size))?; Ok(Some(ImmTy { imm: scalar.into(), layout: mplace.layout })) } - Abi::ScalarPair(a, b) => { + Abi::ScalarPair( + abi::Scalar::Initialized { value: a, .. }, + abi::Scalar::Initialized { value: b, .. }, + ) => { // We checked `ptr_align` above, so all fields will have the alignment they need. // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`, // which `ptr.offset(b_offset)` cannot possibly fail to satisfy. - let (a, b) = (a.value, b.value); let (a_size, b_size) = (a.size(self), b.size(self)); let b_offset = a_size.align_to(b.align(self).abi); assert!(b_offset.bytes() > 0); // we later use the offset to tell apart the fields @@ -676,7 +684,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // may be a pointer. This is `tag_val.layout`; we just use it for sanity checks. // Get layout for tag. - let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(*self.tcx))?; + let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?; // Read tag and sanity-check `tag_layout`. let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index c37973bd1663c..5f7f52ef9e9f4 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -772,13 +772,11 @@ where // We checked `ptr_align` above, so all fields will have the alignment they need. // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`, // which `ptr.offset(b_offset)` cannot possibly fail to satisfy. - let (a, b) = match dest.layout.abi { - Abi::ScalarPair(a, b) => (a.value, b.value), - _ => span_bug!( + let Abi::ScalarPair(a, b) = dest.layout.abi else { span_bug!( self.cur_span(), "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}", dest.layout - ), + ) }; let (a_size, b_size) = (a.size(&tcx), b.size(&tcx)); let b_offset = a_size.align_to(b.align(&tcx).abi); @@ -1046,7 +1044,7 @@ where // raw discriminants for enums are isize or bigger during // their computation, but the in-memory tag is the smallest possible // representation - let size = tag_layout.value.size(self); + let size = tag_layout.size(self); let tag_val = size.truncate(discr_val); let tag_dest = self.place_field(dest, tag_field)?; @@ -1070,7 +1068,7 @@ where .expect("overflow computing relative variant idx"); // We need to use machine arithmetic when taking into account `niche_start`: // tag_val = variant_index_relative + niche_start_val - let tag_layout = self.layout_of(tag_layout.value.to_int_ty(*self.tcx))?; + let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?; let niche_start_val = ImmTy::from_uint(niche_start, tag_layout); let variant_index_relative_val = ImmTy::from_uint(variant_index_relative, tag_layout); diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index a7587652114bf..c2a38c6978bfb 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -189,12 +189,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // that will take care to make it UB to leave the range, just // like for transmute). (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => { - caller.value == callee.value + caller.primitive() == callee.primitive() } ( abi::Abi::ScalarPair(caller1, caller2), abi::Abi::ScalarPair(callee1, callee2), - ) => caller1.value == callee1.value && caller2.value == callee2.value, + ) => { + caller1.primitive() == callee1.primitive() + && caller2.primitive() == callee2.primitive() + } // Be conservative _ => false, } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 42ff7b1945918..e5fd182f8b3a9 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -629,12 +629,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' op: &OpTy<'tcx, M::PointerTag>, scalar_layout: ScalarAbi, ) -> InterpResult<'tcx> { - if scalar_layout.valid_range.is_full_for(op.layout.size) { + if scalar_layout.valid_range(self.ecx).is_full_for(op.layout.size) { // Nothing to check return Ok(()); } // At least one value is excluded. - let valid_range = scalar_layout.valid_range; + let valid_range = scalar_layout.valid_range(self.ecx); let WrappingRange { start, end } = valid_range; let max_value = op.layout.size.unsigned_int_max(); assert!(end <= max_value); diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 14ac30987b35c..437104d1aaf5d 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeFoldable}; use rustc_span::source_map; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol, DUMMY_SP}; -use rustc_target::abi::Abi; +use rustc_target::abi::{Abi, WrappingRange}; use rustc_target::abi::{Integer, TagEncoding, Variants}; use rustc_target::spec::abi::Abi as SpecAbi; @@ -796,14 +796,18 @@ crate fn repr_nullable_ptr<'tcx>( // Return the nullable type this Option-like enum can be safely represented with. let field_ty_abi = &cx.layout_of(field_ty).unwrap().abi; if let Abi::Scalar(field_ty_scalar) = field_ty_abi { - match (field_ty_scalar.valid_range.start, field_ty_scalar.valid_range.end) { - (0, x) if x == field_ty_scalar.value.size(&cx.tcx).unsigned_int_max() - 1 => { + match field_ty_scalar.valid_range(cx) { + WrappingRange { start: 0, end } + if end == field_ty_scalar.size(&cx.tcx).unsigned_int_max() - 1 => + { return Some(get_nullable_type(cx, field_ty).unwrap()); } - (1, _) => { + WrappingRange { start: 1, .. } => { return Some(get_nullable_type(cx, field_ty).unwrap()); } - (start, end) => unreachable!("Unhandled start and end range: ({}, {})", start, end), + WrappingRange { start, end } => { + unreachable!("Unhandled start and end range: ({}, {})", start, end) + } }; } } @@ -1342,7 +1346,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { return }; - let tag_size = tag.value.size(&cx.tcx).bytes(); + let tag_size = tag.size(&cx.tcx).bytes(); debug!( "enum `{}` is {} bytes large with layout:\n{:#?}", diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0c1ab67cc4ac7..e278efa3d8b1e 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -305,10 +305,10 @@ fn invert_mapping(map: &[u32]) -> Vec { impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { 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); - let b_offset = a.value.size(dl).align_to(b_align.abi); - let size = (b_offset + b.value.size(dl)).align_to(align.abi); + let b_align = b.align(dl); + let align = a.align(dl).max(b_align).max(dl.aggregate_align); + let b_offset = a.size(dl).align_to(b_align.abi); + let size = (b_offset + b.size(dl)).align_to(align.abi); // HACK(nox): We iter on `b` and then `a` because `max_by_key` // returns the last maximum. @@ -567,7 +567,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let scalar_unit = |value: Primitive| { let size = value.size(dl); assert!(size.bits() <= 128); - Scalar { value, valid_range: WrappingRange { start: 0, end: size.unsigned_int_max() } } + Scalar::Initialized { value, valid_range: WrappingRange::full(size) } }; let scalar = |value: Primitive| tcx.intern_layout(LayoutS::scalar(self, scalar_unit(value))); @@ -581,11 +581,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Basic scalars. ty::Bool => tcx.intern_layout(LayoutS::scalar( self, - Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } }, + Scalar::Initialized { + value: Int(I8, false), + valid_range: WrappingRange { start: 0, end: 1 }, + }, )), ty::Char => tcx.intern_layout(LayoutS::scalar( self, - Scalar { + Scalar::Initialized { value: Int(I32, false), valid_range: WrappingRange { start: 0, end: 0x10FFFF }, }, @@ -598,7 +601,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }), ty::FnPtr(_) => { let mut ptr = scalar_unit(Pointer); - ptr.valid_range = ptr.valid_range.with_start(1); + ptr.valid_range_mut().start = 1; tcx.intern_layout(LayoutS::scalar(self, ptr)) } @@ -616,7 +619,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { let mut data_ptr = scalar_unit(Pointer); if !ty.is_unsafe_ptr() { - data_ptr.valid_range = data_ptr.valid_range.with_start(1); + data_ptr.valid_range_mut().start = 1; } let pointee = tcx.normalize_erasing_regions(param_env, pointee); @@ -632,7 +635,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), ty::Dynamic(..) => { let mut vtable = scalar_unit(Pointer); - vtable.valid_range = vtable.valid_range.with_start(1); + vtable.valid_range_mut().start = 1; vtable } _ => return Err(LayoutError::Unknown(unsized_part)), @@ -889,14 +892,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // If all non-ZST fields have the same ABI, forward this ABI if optimize && !field.is_zst() { - // Normalize scalar_unit to the maximal valid range + // Discard valid range information and allow undef let field_abi = match field.abi { - Abi::Scalar(x) => Abi::Scalar(scalar_unit(x.value)), + Abi::Scalar(x) => Abi::Scalar(x.to_union()), Abi::ScalarPair(x, y) => { - Abi::ScalarPair(scalar_unit(x.value), scalar_unit(y.value)) + Abi::ScalarPair(x.to_union(), y.to_union()) } Abi::Vector { element: x, count } => { - Abi::Vector { element: scalar_unit(x.value), count } + Abi::Vector { element: x.to_union(), count } } Abi::Uninhabited | Abi::Aggregate { .. } => { Abi::Aggregate { sized: true } @@ -1000,14 +1003,16 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { if let Bound::Included(start) = start { // FIXME(eddyb) this might be incorrect - it doesn't // account for wrap-around (end < start) ranges. - assert!(scalar.valid_range.start <= start); - scalar.valid_range.start = start; + let valid_range = scalar.valid_range_mut(); + assert!(valid_range.start <= start); + valid_range.start = start; } if let Bound::Included(end) = end { // FIXME(eddyb) this might be incorrect - it doesn't // account for wrap-around (end < start) ranges. - assert!(scalar.valid_range.end >= end); - scalar.valid_range.end = end; + let valid_range = scalar.valid_range_mut(); + assert!(valid_range.end >= end); + valid_range.end = end; } // Update `largest_niche` if we have introduced a larger niche. @@ -1133,9 +1138,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // guaranteed to be initialised, not the // other primitive. if offset.bytes() == 0 { - Abi::ScalarPair(niche_scalar, scalar_unit(second.value)) + Abi::ScalarPair( + niche_scalar, + scalar_unit(second.primitive()), + ) } else { - Abi::ScalarPair(scalar_unit(first.value), niche_scalar) + Abi::ScalarPair( + scalar_unit(first.primitive()), + niche_scalar, + ) } } _ => Abi::Aggregate { sized: true }, @@ -1314,7 +1325,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } let tag_mask = ity.size().unsigned_int_max(); - let tag = Scalar { + let tag = Scalar::Initialized { value: Int(ity, signed), valid_range: WrappingRange { start: (min as u128 & tag_mask), @@ -1325,7 +1336,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Without latter check aligned enums with custom discriminant values // Would result in ICE see the issue #92464 for more info - if tag.value.size(dl) == size || variants.iter().all(|layout| layout.is_empty()) { + if tag.size(dl) == size || variants.iter().all(|layout| layout.is_empty()) { abi = Abi::Scalar(tag); } else { // Try to use a ScalarPair for all tagged enums. @@ -1345,7 +1356,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } }; let prim = match field.abi { - Abi::Scalar(scalar) => scalar.value, + Abi::Scalar(scalar) => scalar.primitive(), _ => { common_prim = None; break; @@ -1599,7 +1610,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let max_discr = (info.variant_fields.len() - 1) as u128; let discr_int = Integer::fit_unsigned(max_discr); let discr_int_ty = discr_int.to_ty(tcx, false); - let tag = Scalar { + let tag = Scalar::Initialized { value: Primitive::Int(discr_int, false), valid_range: WrappingRange { start: 0, end: max_discr }, }; @@ -1898,7 +1909,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { adt_kind.into(), adt_packed, match tag_encoding { - TagEncoding::Direct => Some(tag.value.size(self)), + TagEncoding::Direct => Some(tag.size(self)), _ => None, }, variant_infos, @@ -2304,7 +2315,7 @@ where let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> { TyAndLayout { layout: tcx.intern_layout(LayoutS::scalar(cx, tag)), - ty: tag.value.to_ty(tcx), + ty: tag.primitive().to_ty(tcx), } }; @@ -3079,11 +3090,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } // Only pointer types handled below. - if scalar.value != Pointer { - return; - } + let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return }; - if !scalar.valid_range.contains(0) { + if !valid_range.contains(0) { attrs.set(ArgAttribute::NonNull); } diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs index 1ac454be5e9ad..cd54167aa7f82 100644 --- a/compiler/rustc_target/src/abi/call/mips64.rs +++ b/compiler/rustc_target/src/abi/call/mips64.rs @@ -6,7 +6,7 @@ use crate::abi::{self, HasDataLayout, Size, TyAbiInterface}; fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { // Always sign extend u32 values on 64-bit mips if let abi::Abi::Scalar(scalar) = arg.layout.abi { - if let abi::Int(i, signed) = scalar.value { + if let abi::Int(i, signed) = scalar.primitive() { if !signed && i.size().bits() == 32 { if let PassMode::Direct(ref mut attrs) = arg.mode { attrs.ext(ArgExtension::Sext); @@ -25,7 +25,7 @@ where C: HasDataLayout, { match ret.layout.field(cx, i).abi { - abi::Abi::Scalar(scalar) => match scalar.value { + abi::Abi::Scalar(scalar) => match scalar.primitive() { abi::F32 => Some(Reg::f32()), abi::F64 => Some(Reg::f64()), _ => None, @@ -110,7 +110,7 @@ where // We only care about aligned doubles if let abi::Abi::Scalar(scalar) = field.abi { - if let abi::F64 = scalar.value { + if let abi::F64 = scalar.primitive() { if offset.is_aligned(dl.f64_align.abi) { // Insert enough integers to cover [last_offset, offset) assert!(last_offset.is_aligned(dl.f64_align.abi)); diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 34324a582977d..ce564d1455bfc 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -348,7 +348,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { // The primitive for this algorithm. Abi::Scalar(scalar) => { - let kind = match scalar.value { + let kind = match scalar.primitive() { abi::Int(..) | abi::Pointer => RegKind::Integer, abi::F32 | abi::F64 => RegKind::Float, }; @@ -482,7 +482,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { Abi::Scalar(scalar) => PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)), Abi::ScalarPair(a, b) => PassMode::Pair( scalar_attrs(&layout, a, Size::ZERO), - scalar_attrs(&layout, b, a.value.size(cx).align_to(b.value.align(cx).abi)), + scalar_attrs(&layout, b, a.size(cx).align_to(b.align(cx).abi)), ), Abi::Vector { .. } => PassMode::Direct(ArgAttributes::new()), Abi::Aggregate { .. } => PassMode::Direct(ArgAttributes::new()), @@ -534,7 +534,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { pub fn extend_integer_width_to(&mut self, bits: u64) { // Only integers have signedness if let Abi::Scalar(scalar) = self.layout.abi { - if let abi::Int(i, signed) = scalar.value { + if let abi::Int(i, signed) = scalar.primitive() { if i.size().bits() < bits { if let PassMode::Direct(ref mut attrs) = self.mode { if signed { diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs index bbefc73a076d7..752b44f6434cf 100644 --- a/compiler/rustc_target/src/abi/call/riscv.rs +++ b/compiler/rustc_target/src/abi/call/riscv.rs @@ -44,7 +44,7 @@ where Ty: TyAbiInterface<'a, C> + Copy, { match arg_layout.abi { - Abi::Scalar(scalar) => match scalar.value { + Abi::Scalar(scalar) => match scalar.primitive() { abi::Int(..) | abi::Pointer => { if arg_layout.size.bits() > xlen { return Err(CannotUseFpConv); @@ -298,7 +298,7 @@ fn classify_arg<'a, Ty, C>( fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) { if let Abi::Scalar(scalar) = arg.layout.abi { - if let abi::Int(i, _) = scalar.value { + if let abi::Int(i, _) = scalar.primitive() { // 32-bit integers are always sign-extended if i.size().bits() == 32 && xlen > 32 { if let PassMode::Direct(ref mut attrs) = arg.mode { diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index 72709d31021b2..5a92ebdd9e843 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -20,7 +20,7 @@ where { let dl = cx.data_layout(); - if scalar.value != abi::F32 && scalar.value != abi::F64 { + if !scalar.primitive().is_float() { return data; } @@ -56,7 +56,7 @@ where return data; } - if scalar.value == abi::F32 { + if scalar.primitive() == abi::F32 { data.arg_attribute = ArgAttribute::InReg; data.prefix[data.prefix_index] = Some(Reg::f32()); data.last_offset = offset + Reg::f32().size; @@ -79,17 +79,15 @@ where C: HasDataLayout, { data = arg_scalar(cx, &scalar1, offset, data); - if scalar1.value == abi::F32 { - offset += Reg::f32().size; - } else if scalar2.value == abi::F64 { - offset += Reg::f64().size; - } else if let abi::Int(i, _signed) = scalar1.value { - offset += i.size(); - } else if scalar1.value == abi::Pointer { - offset = offset + Reg::i64().size; + match (scalar1.primitive(), scalar2.primitive()) { + (abi::F32, _) => offset += Reg::f32().size, + (_, abi::F64) => offset += Reg::f64().size, + (abi::Int(i, _signed), _) => offset += i.size(), + (abi::Pointer, _) => offset += Reg::i64().size, + _ => {} } - if (offset.raw % 4) != 0 && (scalar2.value == abi::F32 || scalar2.value == abi::F64) { + if (offset.raw % 4) != 0 && scalar2.primitive().is_float() { offset.raw += 4 - (offset.raw % 4); } data = arg_scalar(cx, &scalar2, offset, data); diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs index fae3c3af61bf0..a52e01a495a57 100644 --- a/compiler/rustc_target/src/abi/call/x86_64.rs +++ b/compiler/rustc_target/src/abi/call/x86_64.rs @@ -49,7 +49,7 @@ where let mut c = match layout.abi { Abi::Uninhabited => return Ok(()), - Abi::Scalar(scalar) => match scalar.value { + Abi::Scalar(scalar) => match scalar.primitive() { abi::Int(..) | abi::Pointer => Class::Int, abi::F32 | abi::F64 => Class::Sse, }, diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 52fce7c055309..c46726b767bf2 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -752,6 +752,10 @@ pub struct WrappingRange { } impl WrappingRange { + pub fn full(size: Size) -> Self { + Self { start: 0, end: size.unsigned_int_max() } + } + /// Returns `true` if `v` is contained in the range. #[inline(always)] pub fn contains(&self, v: u128) -> bool { @@ -799,13 +803,23 @@ impl fmt::Debug for WrappingRange { /// Information about one scalar component of a Rust type. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] #[derive(HashStable_Generic)] -pub struct Scalar { - pub value: Primitive, - - // FIXME(eddyb) always use the shortest range, e.g., by finding - // the largest space between two consecutive valid values and - // taking everything else as the (shortest) valid range. - pub valid_range: WrappingRange, +pub enum Scalar { + Initialized { + value: Primitive, + + // FIXME(eddyb) always use the shortest range, e.g., by finding + // the largest space between two consecutive valid values and + // taking everything else as the (shortest) valid range. + valid_range: WrappingRange, + }, + Union { + /// Even for unions, we need to use the correct registers for the kind of + /// values inside the union, so we keep the `Primitive` type around. We + /// also use it to compute the size of the scalar. + /// However, unions never have niches and even allow undef, + /// so there is no `valid_range`. + value: Primitive, + }, } impl Scalar { @@ -813,14 +827,58 @@ impl Scalar { pub fn is_bool(&self) -> bool { matches!( self, - Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } } + Scalar::Initialized { + value: Int(I8, false), + valid_range: WrappingRange { start: 0, end: 1 } + } ) } + /// Get the primitive representation of this type, ignoring the valid range and whether the + /// value is allowed to be undefined (due to being a union). + pub fn primitive(&self) -> Primitive { + match *self { + Scalar::Initialized { value, .. } | Scalar::Union { value } => value, + } + } + + pub fn align(self, cx: &impl HasDataLayout) -> AbiAndPrefAlign { + self.primitive().align(cx) + } + + pub fn size(self, cx: &impl HasDataLayout) -> Size { + self.primitive().size(cx) + } + + #[inline] + pub fn to_union(&self) -> Self { + Self::Union { value: self.primitive() } + } + + #[inline] + pub fn valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange { + match *self { + Scalar::Initialized { valid_range, .. } => valid_range, + Scalar::Union { value } => WrappingRange::full(value.size(cx)), + } + } + + #[inline] + /// Allows the caller to mutate the valid range. This operation will panic if attempted on a union. + pub fn valid_range_mut(&mut self) -> &mut WrappingRange { + match self { + Scalar::Initialized { valid_range, .. } => valid_range, + Scalar::Union { .. } => panic!("cannot change the valid range of a union"), + } + } + /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout #[inline] pub fn is_always_valid(&self, cx: &C) -> bool { - self.valid_range.is_full_for(self.value.size(cx)) + match *self { + Scalar::Initialized { valid_range, .. } => valid_range.is_full_for(self.size(cx)), + Scalar::Union { .. } => true, + } } } @@ -988,7 +1046,7 @@ impl Abi { #[inline] pub fn is_signed(&self) -> bool { match self { - Abi::Scalar(scal) => match scal.value { + Abi::Scalar(scal) => match scal.primitive() { Primitive::Int(_, signed) => signed, _ => false, }, @@ -1060,17 +1118,19 @@ pub enum TagEncoding { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct Niche { pub offset: Size, - pub scalar: Scalar, + pub value: Primitive, + pub valid_range: WrappingRange, } impl Niche { pub fn from_scalar(cx: &C, offset: Size, scalar: Scalar) -> Option { - let niche = Niche { offset, scalar }; + let Scalar::Initialized { value, valid_range } = scalar else { return None }; + let niche = Niche { offset, value, valid_range }; if niche.available(cx) > 0 { Some(niche) } else { None } } pub fn available(&self, cx: &C) -> u128 { - let Scalar { value, valid_range: v } = self.scalar; + let Self { value, valid_range: v, .. } = *self; let size = value.size(cx); assert!(size.bits() <= 128); let max_value = size.unsigned_int_max(); @@ -1083,7 +1143,7 @@ impl Niche { pub fn reserve(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> { assert!(count > 0); - let Scalar { value, valid_range: v } = self.scalar; + let Self { value, valid_range: v, .. } = *self; let size = value.size(cx); assert!(size.bits() <= 128); let max_value = size.unsigned_int_max(); @@ -1107,12 +1167,12 @@ impl Niche { // If niche zero is already reserved, the selection of bounds are of little interest. let move_start = |v: WrappingRange| { let start = v.start.wrapping_sub(count) & max_value; - Some((start, Scalar { value, valid_range: v.with_start(start) })) + Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) })) }; let move_end = |v: WrappingRange| { let start = v.end.wrapping_add(1) & max_value; let end = v.end.wrapping_add(count) & max_value; - Some((start, Scalar { value, valid_range: v.with_end(end) })) + Some((start, Scalar::Initialized { value, valid_range: v.with_end(end) })) }; let distance_end_zero = max_value - v.end; if v.start > v.end { @@ -1172,8 +1232,8 @@ pub struct LayoutS<'a> { 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); + let size = scalar.size(cx); + let align = scalar.align(cx); LayoutS { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Primitive, @@ -1325,7 +1385,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { C: HasDataLayout, { match self.abi { - Abi::Scalar(scalar) => scalar.value.is_float(), + Abi::Scalar(scalar) => scalar.primitive().is_float(), Abi::Aggregate { .. } => { if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 { self.field(cx, 0).is_single_fp_element(cx) @@ -1371,7 +1431,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { let scalar_allows_raw_init = move |s: Scalar| -> bool { if zero { // The range must contain 0. - s.valid_range.contains(0) + s.valid_range(cx).contains(0) } else { // The range must include all values. s.is_always_valid(cx) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 3ad376b8a2ca5..99d7475da3396 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1769,7 +1769,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { let tag_size = if let TagEncoding::Niche { .. } = tag_encoding { 0 - } else if let Primitive::Int(i, _) = tag.value { + } 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") diff --git a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff index f2a1b9d69e1ad..cf6d8a52a7668 100644 --- a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff @@ -3,56 +3,70 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:15:11: 15:11 - let _1: main::InvalidChar; // in scope 0 at $DIR/invalid_constant.rs:21:9: 21:22 - let mut _3: main::InvalidTag; // in scope 0 at $DIR/invalid_constant.rs:28:25: 28:46 - let mut _5: main::NoVariants; // in scope 0 at $DIR/invalid_constant.rs:35:35: 35:56 + let _1: char; // in scope 0 at $DIR/invalid_constant.rs:21:9: 21:22 + let mut _2: main::InvalidChar; // in scope 0 at $DIR/invalid_constant.rs:21:34: 21:63 + let mut _4: E; // in scope 0 at $DIR/invalid_constant.rs:28:25: 28:59 + let mut _5: main::InvalidTag; // in scope 0 at $DIR/invalid_constant.rs:28:34: 28:55 + let mut _7: Empty; // in scope 0 at $DIR/invalid_constant.rs:35:35: 35:73 + let mut _8: main::NoVariants; // in scope 0 at $DIR/invalid_constant.rs:35:44: 35:65 scope 1 { debug _invalid_char => _1; // in scope 1 at $DIR/invalid_constant.rs:21:9: 21:22 - let _2: [main::InvalidTag; 1]; // in scope 1 at $DIR/invalid_constant.rs:28:9: 28:21 - scope 2 { - debug _invalid_tag => _2; // in scope 2 at $DIR/invalid_constant.rs:28:9: 28:21 - let _4: [main::NoVariants; 1]; // in scope 2 at $DIR/invalid_constant.rs:35:9: 35:31 - scope 3 { - debug _enum_without_variants => _4; // in scope 3 at $DIR/invalid_constant.rs:35:9: 35:31 - let _6: main::Str<"���">; // in scope 3 at $DIR/invalid_constant.rs:39:9: 39:22 - scope 4 { - debug _non_utf8_str => _6; // in scope 4 at $DIR/invalid_constant.rs:39:9: 39:22 + let _3: [E; 1]; // in scope 1 at $DIR/invalid_constant.rs:28:9: 28:21 + scope 3 { + debug _invalid_tag => _3; // in scope 3 at $DIR/invalid_constant.rs:28:9: 28:21 + let _6: [Empty; 1]; // in scope 3 at $DIR/invalid_constant.rs:35:9: 35:31 + scope 5 { + debug _enum_without_variants => _6; // in scope 5 at $DIR/invalid_constant.rs:35:9: 35:31 + let _9: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:39:9: 39:22 + scope 7 { + debug _non_utf8_str => _9; // in scope 7 at $DIR/invalid_constant.rs:39:9: 39:22 } } + scope 6 { + } + } + scope 4 { } } + scope 2 { + } bb0: { StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:21:9: 21:22 -- _1 = const { InvalidChar { int: 0x110001 } }; // scope 0 at $DIR/invalid_constant.rs:21:25: 21:64 -+ _1 = const InvalidChar { int: 1114113_u32, chr: {transmute(0x00110001): char} }; // scope 0 at $DIR/invalid_constant.rs:21:25: 21:64 - // mir::Constant - // + span: $DIR/invalid_constant.rs:21:25: 21:64 -- // + literal: Const { ty: InvalidChar, val: Unevaluated(main::{constant#0}, [main::InvalidChar], None) } -+ // + literal: Const { ty: InvalidChar, val: Value(Scalar(0x00110001)) } - StorageLive(_2); // scope 1 at $DIR/invalid_constant.rs:28:9: 28:21 - StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:28:25: 28:46 - (_3.0: u32) = const 4_u32; // scope 1 at $DIR/invalid_constant.rs:28:25: 28:46 -- _2 = [move _3]; // scope 1 at $DIR/invalid_constant.rs:28:24: 28:47 -+ _2 = [const InvalidTag { int: 4_u32, e: Scalar(0x00000004): E }]; // scope 1 at $DIR/invalid_constant.rs:28:24: 28:47 + StorageLive(_2); // scope 2 at $DIR/invalid_constant.rs:21:34: 21:63 + (_2.0: u32) = const 1114113_u32; // scope 2 at $DIR/invalid_constant.rs:21:34: 21:63 +- _1 = (_2.1: char); // scope 2 at $DIR/invalid_constant.rs:21:34: 21:67 ++ _1 = const {transmute(0x00110001): char}; // scope 2 at $DIR/invalid_constant.rs:21:34: 21:67 + StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:21:69: 21:70 + StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:28:9: 28:21 + StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:28:25: 28:59 + StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:28:34: 28:55 + (_5.0: u32) = const 4_u32; // scope 4 at $DIR/invalid_constant.rs:28:34: 28:55 +- _4 = (_5.1: E); // scope 4 at $DIR/invalid_constant.rs:28:34: 28:57 +- _3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:28:24: 28:60 ++ _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:28:34: 28:57 + // mir::Constant -+ // + span: $DIR/invalid_constant.rs:28:24: 28:47 -+ // + literal: Const { ty: InvalidTag, val: Value(Scalar(0x00000004)) } - StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:28:46: 28:47 - StorageLive(_4); // scope 2 at $DIR/invalid_constant.rs:35:9: 35:31 - StorageLive(_5); // scope 2 at $DIR/invalid_constant.rs:35:35: 35:56 - (_5.0: u32) = const 0_u32; // scope 2 at $DIR/invalid_constant.rs:35:35: 35:56 -- _4 = [move _5]; // scope 2 at $DIR/invalid_constant.rs:35:34: 35:57 -+ _4 = [const NoVariants { int: 0_u32, empty: Scalar(): Empty }]; // scope 2 at $DIR/invalid_constant.rs:35:34: 35:57 ++ // + span: $DIR/invalid_constant.rs:28:34: 28:57 ++ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } ++ _3 = [const Scalar(0x00000004): E]; // scope 1 at $DIR/invalid_constant.rs:28:24: 28:60 + // mir::Constant -+ // + span: $DIR/invalid_constant.rs:35:34: 35:57 -+ // + literal: Const { ty: NoVariants, val: Value(Scalar(0x00000000)) } - StorageDead(_5); // scope 2 at $DIR/invalid_constant.rs:35:56: 35:57 - StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:39:9: 39:22 ++ // + span: $DIR/invalid_constant.rs:28:24: 28:60 ++ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } + StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:28:59: 28:60 + StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:28:60: 28:61 + StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:35:9: 35:31 + StorageLive(_7); // scope 3 at $DIR/invalid_constant.rs:35:35: 35:73 + StorageLive(_8); // scope 6 at $DIR/invalid_constant.rs:35:44: 35:65 + (_8.0: u32) = const 0_u32; // scope 6 at $DIR/invalid_constant.rs:35:44: 35:65 + nop; // scope 6 at $DIR/invalid_constant.rs:35:44: 35:71 + nop; // scope 3 at $DIR/invalid_constant.rs:35:34: 35:74 + StorageDead(_7); // scope 3 at $DIR/invalid_constant.rs:35:73: 35:74 + StorageDead(_8); // scope 3 at $DIR/invalid_constant.rs:35:74: 35:75 + StorageLive(_9); // scope 5 at $DIR/invalid_constant.rs:39:9: 39:22 nop; // scope 0 at $DIR/invalid_constant.rs:15:11: 42:2 + StorageDead(_9); // scope 5 at $DIR/invalid_constant.rs:42:1: 42:2 StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:42:1: 42:2 - StorageDead(_4); // scope 2 at $DIR/invalid_constant.rs:42:1: 42:2 - StorageDead(_2); // scope 1 at $DIR/invalid_constant.rs:42:1: 42:2 + StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:42:1: 42:2 StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:42:1: 42:2 return; // scope 0 at $DIR/invalid_constant.rs:42:2: 42:2 } diff --git a/src/test/mir-opt/const_prop/invalid_constant.rs b/src/test/mir-opt/const_prop/invalid_constant.rs index 492ef404916d4..0337a7ca85118 100644 --- a/src/test/mir-opt/const_prop/invalid_constant.rs +++ b/src/test/mir-opt/const_prop/invalid_constant.rs @@ -18,21 +18,21 @@ fn main() { int: u32, chr: char, } - let _invalid_char = const { InvalidChar { int: 0x110001 } }; + let _invalid_char = unsafe { InvalidChar { int: 0x110001 }.chr }; // An enum with an invalid tag. Regression test for #93688. union InvalidTag { int: u32, e: E, } - let _invalid_tag = [InvalidTag { int: 4 }]; + let _invalid_tag = [unsafe { InvalidTag { int: 4 }.e }]; // An enum without variants. Regression test for #94073. union NoVariants { int: u32, empty: Empty, } - let _enum_without_variants = [NoVariants { int: 0 }]; + let _enum_without_variants = [unsafe { NoVariants { int: 0 }.empty }]; // A non-UTF-8 string slice. Regression test for #75763 and #78520. struct Str; diff --git a/src/test/ui/consts/issue-69488.rs b/src/test/ui/consts/issue-69488.rs new file mode 100644 index 0000000000000..46546eada7aac --- /dev/null +++ b/src/test/ui/consts/issue-69488.rs @@ -0,0 +1,34 @@ +// run-pass + +#![feature(const_ptr_write)] +#![feature(const_mut_refs)] + +// Or, equivalently: `MaybeUninit`. +pub union BagOfBits { + uninit: (), + _storage: T, +} + +pub const fn make_1u8_bag() -> BagOfBits { + assert!(core::mem::size_of::() >= 1); + let mut bag = BagOfBits { uninit: () }; + unsafe { (&mut bag as *mut _ as *mut u8).write(1); }; + bag +} + +pub fn check_bag(bag: &BagOfBits) { + let val = unsafe { (bag as *const _ as *const u8).read() }; + assert_eq!(val, 1); +} + +fn main() { + check_bag(&make_1u8_bag::<[usize; 1]>()); // Fine + check_bag(&make_1u8_bag::()); // Fine + + const CONST_ARRAY_BAG: BagOfBits<[usize; 1]> = make_1u8_bag(); + check_bag(&CONST_ARRAY_BAG); // Fine. + const CONST_USIZE_BAG: BagOfBits = make_1u8_bag(); + + // Used to panic since CTFE would make the entire `BagOfBits` uninit + check_bag(&CONST_USIZE_BAG); +} diff --git a/src/test/ui/consts/issue-94371.rs b/src/test/ui/consts/issue-94371.rs new file mode 100644 index 0000000000000..de9ff730b66f3 --- /dev/null +++ b/src/test/ui/consts/issue-94371.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(const_swap)] +#![feature(const_mut_refs)] + +#[repr(C)] +struct Demo(u64, bool, u64, u32, u64, u64, u64); + +const C: (Demo, Demo) = { + let mut x = Demo(1, true, 3, 4, 5, 6, 7); + let mut y = Demo(10, false, 12, 13, 14, 15, 16); + std::mem::swap(&mut x, &mut y); + (x, y) +}; + +fn main() {} diff --git a/src/test/ui/layout/debug.stderr b/src/test/ui/layout/debug.stderr index 418f780d62c97..25f7febfef9df 100644 --- a/src/test/ui/layout/debug.stderr +++ b/src/test/ui/layout/debug.stderr @@ -10,7 +10,7 @@ error: layout_of(E) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, false, @@ -86,13 +86,11 @@ error: layout_of(E) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 0..=0, - }, + value: Int( + I32, + false, + ), + valid_range: 0..=0, }, ), align: AbiAndPrefAlign { @@ -133,14 +131,14 @@ error: layout_of(S) = Layout { index: 0, }, abi: ScalarPair( - Scalar { + Initialized { value: Int( I32, true, ), valid_range: 0..=4294967295, }, - Scalar { + Initialized { value: Int( I32, true, @@ -202,7 +200,7 @@ error: layout_of(std::result::Result) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, false, @@ -271,14 +269,14 @@ error: layout_of(std::result::Result) = Layout { ], }, abi: ScalarPair( - Scalar { + Initialized { value: Int( I32, false, ), valid_range: 0..=1, }, - Scalar { + Initialized { value: Int( I32, true, @@ -291,13 +289,11 @@ error: layout_of(std::result::Result) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 0..=1, - }, + value: Int( + I32, + false, + ), + valid_range: 0..=1, }, ), align: AbiAndPrefAlign { @@ -321,7 +317,7 @@ error: layout_of(i32) = Layout { index: 0, }, abi: Scalar( - Scalar { + Initialized { value: Int( I32, true, diff --git a/src/test/ui/layout/hexagon-enum.stderr b/src/test/ui/layout/hexagon-enum.stderr index 39b23cb4b572e..4db8162b16bb2 100644 --- a/src/test/ui/layout/hexagon-enum.stderr +++ b/src/test/ui/layout/hexagon-enum.stderr @@ -10,7 +10,7 @@ error: layout_of(A) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I8, false, @@ -47,7 +47,7 @@ error: layout_of(A) = Layout { ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I8, false, @@ -60,13 +60,11 @@ error: layout_of(A) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 0..=0, - }, + value: Int( + I8, + false, + ), + valid_range: 0..=0, }, ), align: AbiAndPrefAlign { @@ -98,7 +96,7 @@ error: layout_of(B) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I8, false, @@ -135,7 +133,7 @@ error: layout_of(B) = Layout { ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I8, false, @@ -148,13 +146,11 @@ error: layout_of(B) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, + value: Int( + I8, + false, + ), + valid_range: 255..=255, }, ), align: AbiAndPrefAlign { @@ -186,7 +182,7 @@ error: layout_of(C) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I16, false, @@ -223,7 +219,7 @@ error: layout_of(C) = Layout { ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I16, false, @@ -236,13 +232,11 @@ error: layout_of(C) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, + value: Int( + I16, + false, + ), + valid_range: 256..=256, }, ), align: AbiAndPrefAlign { @@ -274,7 +268,7 @@ error: layout_of(P) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, false, @@ -311,7 +305,7 @@ error: layout_of(P) = Layout { ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I32, false, @@ -324,13 +318,11 @@ error: layout_of(P) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, }, ), align: AbiAndPrefAlign { @@ -362,7 +354,7 @@ error: layout_of(T) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, true, @@ -399,7 +391,7 @@ error: layout_of(T) = Layout { ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I32, true, @@ -412,13 +404,11 @@ error: layout_of(T) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, }, ), align: AbiAndPrefAlign { diff --git a/src/test/ui/layout/thumb-enum.stderr b/src/test/ui/layout/thumb-enum.stderr index 144ab02792e50..9d1f234f31ad5 100644 --- a/src/test/ui/layout/thumb-enum.stderr +++ b/src/test/ui/layout/thumb-enum.stderr @@ -10,7 +10,7 @@ error: layout_of(A) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I8, false, @@ -47,7 +47,7 @@ error: layout_of(A) = Layout { ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I8, false, @@ -60,13 +60,11 @@ error: layout_of(A) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 0..=0, - }, + value: Int( + I8, + false, + ), + valid_range: 0..=0, }, ), align: AbiAndPrefAlign { @@ -98,7 +96,7 @@ error: layout_of(B) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I8, false, @@ -135,7 +133,7 @@ error: layout_of(B) = Layout { ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I8, false, @@ -148,13 +146,11 @@ error: layout_of(B) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, + value: Int( + I8, + false, + ), + valid_range: 255..=255, }, ), align: AbiAndPrefAlign { @@ -186,7 +182,7 @@ error: layout_of(C) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I16, false, @@ -223,7 +219,7 @@ error: layout_of(C) = Layout { ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I16, false, @@ -236,13 +232,11 @@ error: layout_of(C) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, + value: Int( + I16, + false, + ), + valid_range: 256..=256, }, ), align: AbiAndPrefAlign { @@ -274,7 +268,7 @@ error: layout_of(P) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, false, @@ -311,7 +305,7 @@ error: layout_of(P) = Layout { ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I32, false, @@ -324,13 +318,11 @@ error: layout_of(P) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, }, ), align: AbiAndPrefAlign { @@ -362,7 +354,7 @@ error: layout_of(T) = Layout { ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, true, @@ -399,7 +391,7 @@ error: layout_of(T) = Layout { ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I32, true, @@ -412,13 +404,11 @@ error: layout_of(T) = Layout { offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, }, ), align: AbiAndPrefAlign {