Skip to content

Commit dd800e1

Browse files
committed
We only use Immediate::Uninit for zsts and uninit locals
1 parent aa5c496 commit dd800e1

File tree

6 files changed

+17
-12
lines changed

6 files changed

+17
-12
lines changed

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ pub(super) fn op_to_const<'tcx>(
240240
let meta = b.to_target_usize(ecx).expect(msg);
241241
ConstValue::Slice { data, meta }
242242
}
243-
Immediate::Uninit => bug!("`Uninit` is not a valid value for {}", op.layout.ty),
243+
Immediate::Uninit => bug!("`Zst` is not a valid value for {}", op.layout.ty),
244244
},
245245
}
246246
}

compiler/rustc_const_eval/src/interpret/operand.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ impl<Prov: Provenance> Immediate<Prov> {
152152
}
153153
}
154154
(Immediate::Uninit, _) => {
155-
assert!(abi.is_sized(), "{msg}: unsized immediates are not a thing");
155+
assert_matches!(
156+
abi,
157+
BackendRepr::Memory { sized: true },
158+
"{msg}: unsized zsts are not a thing"
159+
);
156160
}
157161
_ => {
158162
bug!("{msg}: value {self:?} does not match ABI {abi:?})",)
@@ -267,7 +271,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
267271
match (imm, layout.backend_repr) {
268272
(Immediate::Scalar(..), BackendRepr::Scalar(..)) => true,
269273
(Immediate::ScalarPair(..), BackendRepr::ScalarPair(..)) => true,
270-
(Immediate::Uninit, _) if layout.is_sized() => true,
274+
(Immediate::Uninit, _) if layout.is_sized() && layout.is_zst() => true,
271275
_ => false,
272276
},
273277
"immediate {imm:?} does not fit to layout {layout:?}",
@@ -276,8 +280,9 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
276280
}
277281

278282
#[inline]
279-
pub fn uninit(layout: TyAndLayout<'tcx>) -> Self {
283+
pub fn zst(layout: TyAndLayout<'tcx>) -> Self {
280284
debug_assert!(layout.is_sized(), "immediates must be sized");
285+
debug_assert!(layout.is_zst());
281286
ImmTy { imm: Immediate::Uninit, layout }
282287
}
283288

@@ -382,15 +387,16 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
382387
// This makes several assumptions about what layouts we will encounter; we match what
383388
// codegen does as good as we can (see `extract_field` in `rustc_codegen_ssa/src/mir/operand.rs`).
384389
let inner_val: Immediate<_> = match (**self, self.layout.backend_repr) {
385-
// If the entire value is uninit, then so is the field (can happen in ConstProp).
386-
(Immediate::Uninit, _) => Immediate::Uninit,
387390
// If the field is uninhabited, we can forget the data (can happen in ConstProp).
388391
// `enum S { A(!), B, C }` is an example of an enum with Scalar layout that
389392
// has an uninhabited variant, which means this case is possible.
390393
_ if layout.is_uninhabited() => Immediate::Uninit,
391394
// the field contains no information, can be left uninit
392395
// (Scalar/ScalarPair can contain even aligned ZST, not just 1-ZST)
393396
_ if layout.is_zst() => Immediate::Uninit,
397+
// If the value is a zst, then so is the field (can happen in ConstProp).
398+
// This is handled by the zst field read above.
399+
(Immediate::Uninit, _) => unreachable!(),
394400
// some fieldless enum variants can have non-zero size but still `Aggregate` ABI... try
395401
// to detect those here and also give them no data
396402
_ if matches!(layout.backend_repr, BackendRepr::Memory { .. })
@@ -572,8 +578,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
572578
}
573579

574580
let Some(alloc) = self.get_place_alloc(mplace)? else {
575-
// zero-sized type can be left uninit
576-
return interp_ok(Some(ImmTy::uninit(mplace.layout)));
581+
return interp_ok(Some(ImmTy::zst(mplace.layout)));
577582
};
578583

579584
// It may seem like all types with `Scalar` or `ScalarPair` ABI are fair game at this point.

compiler/rustc_const_eval/src/interpret/operator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
496496
}
497497
MemPlaceMeta::None => {
498498
let unit_layout = self.layout_of(self.tcx.types.unit)?;
499-
ImmTy::uninit(unit_layout)
499+
ImmTy::zst(unit_layout)
500500
}
501501
})
502502
}

compiler/rustc_const_eval/src/interpret/place.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ where
722722
// We don't have to reset padding here, `write_immediate` will anyway do a validation run.
723723
interp_ok(())
724724
}
725-
Immediate::Uninit => alloc.write_uninit_full(),
725+
Immediate::Uninit => unreachable!("zst have been skipped in the alloc load above"),
726726
}
727727
}
728728

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
407407
let variant = if ty.is_enum() { Some(variant) } else { None };
408408
let ty = self.ecx.layout_of(ty).ok()?;
409409
if ty.is_zst() {
410-
ImmTy::uninit(ty).into()
410+
ImmTy::zst(ty).into()
411411
} else if matches!(kind, AggregateTy::RawPtr { .. }) {
412412
// Pointers don't have fields, so don't `project_field` them.
413413
let data = self.ecx.read_pointer(fields[0]).discard_err()?;

src/tools/miri/src/shims/native_lib/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
9393
// have the output_type `Tuple([])`.
9494
ty::Tuple(t_list) if (*t_list).deref().is_empty() => {
9595
unsafe { ffi::call::<()>(ptr, libffi_args.as_slice()) };
96-
break 'res interp_ok(ImmTy::uninit(dest.layout));
96+
break 'res interp_ok(ImmTy::zst(dest.layout));
9797
}
9898
ty::RawPtr(..) => {
9999
let x = unsafe { ffi::call::<*const ()>(ptr, libffi_args.as_slice()) };

0 commit comments

Comments
 (0)