Skip to content

Commit a4cc866

Browse files
committed
Add assert_zst intrinsic for use in conjure_zst function
1 parent 8d603ef commit a4cc866

File tree

15 files changed

+84
-20
lines changed

15 files changed

+84
-20
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,10 @@ fn codegen_regular_intrinsic_call<'tcx>(
749749
let res = CValue::by_val(res, arg.layout());
750750
ret.write_cvalue(fx, res);
751751
}
752-
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid => {
752+
sym::assert_inhabited
753+
| sym::assert_zero_valid
754+
| sym::assert_mem_uninitialized_valid
755+
| sym::assert_zst => {
753756
intrinsic_args!(fx, args => (); intrinsic);
754757

755758
let ty = generic_args.type_at(0);
@@ -777,6 +780,11 @@ fn codegen_regular_intrinsic_call<'tcx>(
777780
"attempted to zero-initialize type `{}`, which is invalid",
778781
ty
779782
)
783+
} else if intrinsic == sym::assert_zst {
784+
format!(
785+
"attempted to conjure type `{}` when it is not zero-sized",
786+
ty
787+
)
780788
} else {
781789
format!(
782790
"attempted to leave type `{}` uninitialized, which is invalid",

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
114114
| sym::assert_zero_valid
115115
| sym::assert_mem_uninitialized_valid
116116
| sym::assert_inhabited
117+
| sym::assert_zst
117118
| sym::ub_checks
118119
| sym::contract_checks
119120
| sym::atomic_fence

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,8 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
557557
// We handle these here since Miri does not want to have them.
558558
sym::assert_inhabited
559559
| sym::assert_zero_valid
560-
| sym::assert_mem_uninitialized_valid => {
560+
| sym::assert_mem_uninitialized_valid
561+
| sym::assert_zst => {
561562
let ty = instance.args.type_at(0);
562563
let requirement = ValidityRequirement::from_intrinsic(intrinsic_name).unwrap();
563564

@@ -582,6 +583,9 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
582583
ValidityRequirement::UninitMitigated0x01Fill => format!(
583584
"aborted execution: attempted to leave type `{ty}` uninitialized, which is invalid"
584585
),
586+
ValidityRequirement::Zst => format!(
587+
"aborted execution: attempted to conjure type `{ty}` when it is not zero-sized"
588+
),
585589
ValidityRequirement::Uninit => bug!("assert_uninit_valid doesn't exist"),
586590
};
587591

compiler/rustc_const_eval/src/util/check_validity_requirement.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ pub fn check_validity_requirement<'tcx>(
2828
) -> Result<bool, &'tcx LayoutError<'tcx>> {
2929
let layout = tcx.layout_of(input)?;
3030

31-
// There is nothing strict or lax about inhabitedness.
31+
// There is nothing strict or lax about inhabitedness, or being a ZST.
3232
if kind == ValidityRequirement::Inhabited {
3333
return Ok(!layout.is_uninhabited());
34+
} else if kind == ValidityRequirement::Zst {
35+
return Ok(!layout.is_uninhabited() && layout.is_zst());
3436
}
3537

3638
let layout_cx = LayoutCx::new(tcx, input.typing_env);
@@ -91,6 +93,9 @@ fn check_validity_requirement_lax<'tcx>(
9193
ValidityRequirement::Inhabited => {
9294
bug!("ValidityRequirement::Inhabited should have been handled above")
9395
}
96+
ValidityRequirement::Zst => {
97+
bug!("ValidityRequirement::Zst should have been handled above")
98+
}
9499
ValidityRequirement::Zero => {
95100
// The range must contain 0.
96101
s.valid_range(cx).contains(0)

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
7373
| sym::assert_inhabited
7474
| sym::assert_mem_uninitialized_valid
7575
| sym::assert_zero_valid
76+
| sym::assert_zst
7677
| sym::autodiff
7778
| sym::bitreverse
7879
| sym::black_box
@@ -289,9 +290,10 @@ pub(crate) fn check_intrinsic_type(
289290
}
290291
sym::rustc_peek => (1, 0, vec![param(0)], param(0)),
291292
sym::caller_location => (0, 0, vec![], tcx.caller_location_ty()),
292-
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid => {
293-
(1, 0, vec![], tcx.types.unit)
294-
}
293+
sym::assert_inhabited
294+
| sym::assert_zero_valid
295+
| sym::assert_mem_uninitialized_valid
296+
| sym::assert_zst => (1, 0, vec![], tcx.types.unit),
295297
sym::forget => (1, 0, vec![param(0)], tcx.types.unit),
296298
sym::transmute | sym::transmute_unchecked => (2, 0, vec![param(0)], param(1)),
297299
sym::prefetch_read_data

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ pub enum ValidityRequirement {
194194
UninitMitigated0x01Fill,
195195
/// True uninitialized memory.
196196
Uninit,
197+
Zst,
197198
}
198199

199200
impl ValidityRequirement {
@@ -202,6 +203,7 @@ impl ValidityRequirement {
202203
sym::assert_inhabited => Some(Self::Inhabited),
203204
sym::assert_zero_valid => Some(Self::Zero),
204205
sym::assert_mem_uninitialized_valid => Some(Self::UninitMitigated0x01Fill),
206+
sym::assert_zst => Some(Self::Zst),
205207
_ => None,
206208
}
207209
}
@@ -214,6 +216,7 @@ impl fmt::Display for ValidityRequirement {
214216
Self::Zero => f.write_str("allows being left zeroed"),
215217
Self::UninitMitigated0x01Fill => f.write_str("allows being filled with 0x01"),
216218
Self::Uninit => f.write_str("allows being left uninitialized"),
219+
Self::Zst => f.write_str("is zero-sized"),
217220
}
218221
}
219222
}

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -945,10 +945,11 @@ fn visit_instance_use<'tcx>(
945945
collect_autodiff_fn(tcx, instance, intrinsic, output);
946946

947947
if let Some(_requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) {
948-
// The intrinsics assert_inhabited, assert_zero_valid, and assert_mem_uninitialized_valid will
949-
// be lowered in codegen to nothing or a call to panic_nounwind. So if we encounter any
950-
// of those intrinsics, we need to include a mono item for panic_nounwind, else we may try to
951-
// codegen a call to that function without generating code for the function itself.
948+
// The intrinsics assert_inhabited, assert_zero_valid, assert_mem_uninitialized_valid,
949+
// and assert_zst will be lowered in codegen to nothing or a call to panic_nounwind.
950+
// So if we encounter any of those intrinsics, we need to include a mono item for
951+
// panic_nounwind, else we may try to codegen a call to that function without generating
952+
// code for the function itself.
952953
let def_id = tcx.require_lang_item(LangItem::PanicNounwind, source);
953954
let panic_instance = Instance::mono(tcx, def_id);
954955
if tcx.should_codegen_locally(panic_instance) {

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ symbols! {
488488
assert_ne_macro,
489489
assert_receiver_is_total_eq,
490490
assert_zero_valid,
491+
assert_zst,
491492
asserting,
492493
associated_const_equality,
493494
associated_consts,

library/core/src/intrinsics/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,16 @@ pub const fn assert_zero_valid<T>();
516516
#[rustc_intrinsic]
517517
pub const fn assert_mem_uninitialized_valid<T>();
518518

519+
/// A guard for `std::mem::conjure_zst`. This will statically either panic, or do nothing. It does
520+
/// not *guarantee* to ever panic, and should only be called if an assertion failure will imply
521+
/// language UB in the following code.
522+
///
523+
/// This intrinsic does not have a stable counterpart.
524+
#[rustc_intrinsic_const_stable_indirect]
525+
#[rustc_nounwind]
526+
#[rustc_intrinsic]
527+
pub const fn assert_zst<T>();
528+
519529
/// Gets a reference to a static `Location` indicating where it was called.
520530
///
521531
/// Note that, unlike most intrinsics, this is safe to call;

src/tools/miri/src/intrinsics/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
185185
throw_machine_stop!(TerminationInfo::Abort(format!("trace/breakpoint trap")))
186186
}
187187

188-
"assert_inhabited" | "assert_zero_valid" | "assert_mem_uninitialized_valid" => {
188+
"assert_inhabited" | "assert_zero_valid" | "assert_mem_uninitialized_valid" | "assert_zst" => {
189189
// Make these a NOP, so we get the better Miri-native error messages.
190190
}
191191

0 commit comments

Comments
 (0)