diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 467eceea221c8..b37fb213d945a 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -421,6 +421,17 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { source_info.span, ) } + AssertKind::NullReferenceConstructed => { + let location = fx.get_caller_location(source_info).load_scalar(fx); + + codegen_panic_inner( + fx, + rustc_hir::LangItem::PanicNullReferenceConstructed, + &[location], + *unwind, + source_info.span, + ) + } AssertKind::InvalidEnumConstruction(source) => { let source = codegen_operand(fx, source).load_scalar(fx); let location = fx.get_caller_location(source_info).load_scalar(fx); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 0173b84a4d9a1..fad93de43b272 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -789,6 +789,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // `#[track_caller]` adds an implicit argument. (LangItem::PanicNullPointerDereference, vec![location]) } + AssertKind::NullReferenceConstructed => { + // It's `fn panic_null_reference_constructed()`, + // `#[track_caller]` adds an implicit argument. + (LangItem::PanicNullReferenceConstructed, vec![location]) + } AssertKind::InvalidEnumConstruction(source) => { let source = self.codegen_operand(bx, source).immediate(); // It's `fn panic_invalid_enum_construction(source: u128)`, diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index b4a97c0b137c9..e7e1dd2ec0fb0 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -772,6 +772,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { found: eval_to_int(found)?, }, NullPointerDereference => NullPointerDereference, + NullReferenceConstructed => NullReferenceConstructed, InvalidEnumConstruction(source) => InvalidEnumConstruction(eval_to_int(source)?), }; Err(ConstEvalErrKind::AssertFailure(err)).into() diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 9c3f7789f9ed9..f0b6d0fb8dcc9 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -309,6 +309,7 @@ language_item_table! { PanicAsyncGenFnResumedPanic, sym::panic_const_async_gen_fn_resumed_panic, panic_const_async_gen_fn_resumed_panic, Target::Fn, GenericRequirement::None; PanicGenFnNonePanic, sym::panic_const_gen_fn_none_panic, panic_const_gen_fn_none_panic, Target::Fn, GenericRequirement::None; PanicNullPointerDereference, sym::panic_null_pointer_dereference, panic_null_pointer_dereference, Target::Fn, GenericRequirement::None; + PanicNullReferenceConstructed, sym::panic_null_reference_constructed, panic_null_reference_constructed, Target::Fn, GenericRequirement::None; PanicInvalidEnumConstruction, sym::panic_invalid_enum_construction, panic_invalid_enum_construction, Target::Fn, GenericRequirement::None; PanicCoroutineResumedDrop, sym::panic_const_coroutine_resumed_drop, panic_const_coroutine_resumed_drop, Target::Fn, GenericRequirement::None; PanicAsyncFnResumedDrop, sym::panic_const_async_fn_resumed_drop, panic_const_async_fn_resumed_drop, Target::Fn, GenericRequirement::None; diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 91ff3f52390e1..5a3d34cb77078 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1061,6 +1061,7 @@ pub enum AssertKind { ResumedAfterDrop(CoroutineKind), MisalignedPointerDereference { required: O, found: O }, NullPointerDereference, + NullReferenceConstructed, InvalidEnumConstruction(O), } diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 3f66fe34af622..aaa0c257925dd 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -210,6 +210,7 @@ impl AssertKind { LangItem::PanicGenFnNonePanic } NullPointerDereference => LangItem::PanicNullPointerDereference, + NullReferenceConstructed => LangItem::PanicNullReferenceConstructed, InvalidEnumConstruction(_) => LangItem::PanicInvalidEnumConstruction, ResumedAfterDrop(CoroutineKind::Coroutine(_)) => LangItem::PanicCoroutineResumedDrop, ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { @@ -287,6 +288,7 @@ impl AssertKind { ) } NullPointerDereference => write!(f, "\"null pointer dereference occurred\""), + NullReferenceConstructed => write!(f, "\"null reference produced\""), InvalidEnumConstruction(source) => { write!(f, "\"trying to construct an enum from an invalid value {{}}\", {source:?}") } @@ -387,6 +389,7 @@ impl fmt::Display for AssertKind { write!(f, "coroutine resumed after panicking") } NullPointerDereference => write!(f, "null pointer dereference occurred"), + NullReferenceConstructed => write!(f, "null reference produced"), InvalidEnumConstruction(source) => { write!(f, "trying to construct an enum from an invalid value `{source:#?}`") } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 921c54b2828c2..22f2d5c1afcac 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -668,7 +668,7 @@ macro_rules! make_mir_visitor { OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) | InvalidEnumConstruction(op) => { self.visit_operand(op, location); } - ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | ResumedAfterDrop(_) => { + ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | NullReferenceConstructed | ResumedAfterDrop(_) => { // Nothing to visit } MisalignedPointerDereference { required, found } => { diff --git a/compiler/rustc_mir_transform/src/check_null.rs b/compiler/rustc_mir_transform/src/check_null.rs index b589e2fff1569..beb26a20cd3f8 100644 --- a/compiler/rustc_mir_transform/src/check_null.rs +++ b/compiler/rustc_mir_transform/src/check_null.rs @@ -55,16 +55,19 @@ fn insert_null_check<'tcx>( const_: Const::Val(ConstValue::from_target_usize(0, &tcx), tcx.types.usize), })); - let pointee_should_be_checked = match context { + let (pointee_should_be_checked, assert_kind) = match context { // Borrows pointing to "null" are UB even if the pointee is a ZST. PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { // Pointer should be checked unconditionally. - Operand::Constant(Box::new(ConstOperand { - span: source_info.span, - user_ty: None, - const_: Const::from_bool(tcx, true), - })) + ( + Operand::Constant(Box::new(ConstOperand { + span: source_info.span, + user_ty: None, + const_: Const::from_bool(tcx, true), + })), + AssertKind::NullReferenceConstructed, + ) } // Other usages of null pointers only are UB if the pointee is not a ZST. _ => { @@ -79,7 +82,7 @@ fn insert_null_check<'tcx>( source_info, StatementKind::Assign(Box::new((pointee_should_be_checked, rvalue))), )); - Operand::Copy(pointee_should_be_checked) + (Operand::Copy(pointee_should_be_checked), AssertKind::NullPointerDereference) } }; @@ -119,9 +122,6 @@ fn insert_null_check<'tcx>( )); // Emit a PointerCheck that asserts on the condition and otherwise triggers - // a AssertKind::NullPointerDereference. - PointerCheck { - cond: Operand::Copy(is_ok), - assert_kind: Box::new(AssertKind::NullPointerDereference), - } + // the chosen AssertKind. + PointerCheck { cond: Operand::Copy(is_ok), assert_kind: Box::new(assert_kind) } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index ceb044c102f69..bb2548749ea67 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -899,6 +899,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { mir::AssertKind::NullPointerDereference => { push_mono_lang_item(self, LangItem::PanicNullPointerDereference); } + mir::AssertKind::NullReferenceConstructed => { + push_mono_lang_item(self, LangItem::PanicNullReferenceConstructed); + } mir::AssertKind::InvalidEnumConstruction(_) => { push_mono_lang_item(self, LangItem::PanicInvalidEnumConstruction); } diff --git a/compiler/rustc_public/src/mir/body.rs b/compiler/rustc_public/src/mir/body.rs index f9b5f9af951e5..b480ec74bae34 100644 --- a/compiler/rustc_public/src/mir/body.rs +++ b/compiler/rustc_public/src/mir/body.rs @@ -269,6 +269,7 @@ pub enum AssertMessage { ResumedAfterDrop(CoroutineKind), MisalignedPointerDereference { required: Operand, found: Operand }, NullPointerDereference, + NullReferenceConstructed, InvalidEnumConstruction(Operand), } @@ -342,6 +343,7 @@ impl AssertMessage { Ok("misaligned pointer dereference") } AssertMessage::NullPointerDereference => Ok("null pointer dereference occurred"), + AssertMessage::NullReferenceConstructed => Ok("null reference produced"), AssertMessage::InvalidEnumConstruction(_) => { Ok("trying to construct an enum from an invalid value") } diff --git a/compiler/rustc_public/src/mir/pretty.rs b/compiler/rustc_public/src/mir/pretty.rs index dec4044fd260b..3bef4d5cb38df 100644 --- a/compiler/rustc_public/src/mir/pretty.rs +++ b/compiler/rustc_public/src/mir/pretty.rs @@ -310,6 +310,9 @@ fn pretty_assert_message(writer: &mut W, msg: &AssertMessage) -> io::R AssertMessage::NullPointerDereference => { write!(writer, "\"null pointer dereference occurred\"") } + AssertMessage::NullReferenceConstructed => { + write!(writer, "\"null reference produced\"") + } AssertMessage::InvalidEnumConstruction(op) => { let pretty_op = pretty_operand(op); write!(writer, "\"trying to construct an enum from an invalid value {{}}\",{pretty_op}") diff --git a/compiler/rustc_public/src/mir/visit.rs b/compiler/rustc_public/src/mir/visit.rs index 5a3afc9937351..1997a7b957897 100644 --- a/compiler/rustc_public/src/mir/visit.rs +++ b/compiler/rustc_public/src/mir/visit.rs @@ -369,6 +369,7 @@ macro_rules! make_mir_visitor { AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) | AssertMessage::NullPointerDereference + | AssertMessage::NullReferenceConstructed | AssertMessage::ResumedAfterDrop(_) => { //nothing to visit } diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs index d126304af8cde..a19dadcb20b94 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs @@ -559,6 +559,9 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> { } } AssertKind::NullPointerDereference => crate::mir::AssertMessage::NullPointerDereference, + AssertKind::NullReferenceConstructed => { + crate::mir::AssertMessage::NullReferenceConstructed + } AssertKind::InvalidEnumConstruction(source) => { crate::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables, cx)) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 71eae246ebaff..055b3739c2818 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1535,6 +1535,7 @@ symbols! { panic_misaligned_pointer_dereference, panic_nounwind, panic_null_pointer_dereference, + panic_null_reference_constructed, panic_runtime, panic_str_2015, panic_unwind, diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 3609dd1fe2e02..46790b620127b 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -305,6 +305,19 @@ fn panic_null_pointer_dereference() -> ! { ) } +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] +#[track_caller] +#[lang = "panic_null_reference_constructed"] // needed by codegen for panic on null reference formation +#[rustc_nounwind] // `CheckNull` MIR pass requires this function to never unwind +fn panic_null_reference_constructed() -> ! { + if cfg!(panic = "immediate-abort") { + super::intrinsics::abort() + } + + panic_nounwind_fmt(format_args!("null reference produced"), /* force_no_backtrace */ false) +} + #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] #[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] diff --git a/tests/ui/mir/null/borrowed_mut_null.rs b/tests/ui/mir/null/borrowed_mut_null.rs index a4660f4bf5734..1f3adede80465 100644 --- a/tests/ui/mir/null/borrowed_mut_null.rs +++ b/tests/ui/mir/null/borrowed_mut_null.rs @@ -1,6 +1,6 @@ //@ run-crash //@ compile-flags: -C debug-assertions -//@ error-pattern: null pointer dereference occurred +//@ error-pattern: null reference produced fn main() { let ptr: *mut u32 = std::ptr::null_mut(); diff --git a/tests/ui/mir/null/borrowed_null.rs b/tests/ui/mir/null/borrowed_null.rs index 2a50058a48202..6857d2e64c660 100644 --- a/tests/ui/mir/null/borrowed_null.rs +++ b/tests/ui/mir/null/borrowed_null.rs @@ -1,6 +1,6 @@ //@ run-crash //@ compile-flags: -C debug-assertions -//@ error-pattern: null pointer dereference occurred +//@ error-pattern: null reference produced fn main() { let ptr: *const u32 = std::ptr::null(); diff --git a/tests/ui/mir/null/borrowed_null_zst.rs b/tests/ui/mir/null/borrowed_null_zst.rs index 106fa00b1db5a..9a31f4c94f96a 100644 --- a/tests/ui/mir/null/borrowed_null_zst.rs +++ b/tests/ui/mir/null/borrowed_null_zst.rs @@ -1,6 +1,6 @@ //@ run-crash //@ compile-flags: -C debug-assertions -//@ error-pattern: null pointer dereference occurred +//@ error-pattern: null reference produced fn main() { let ptr: *const () = std::ptr::null();