From 8cfa4fe6b2268385480dc4a88ce3e6fdb06a3596 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 5 Aug 2023 04:54:23 +0200 Subject: [PATCH 1/4] Add #[rustc_never_returns_null_ptr] And look for it in the useless_ptr_null_checks lint --- compiler/rustc_feature/src/builtin_attrs.rs | 4 ++++ compiler/rustc_lint/src/ptr_nulls.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 3 +++ compiler/rustc_span/src/symbol.rs | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index a183cfd8776a3..6596e47f6156a 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -698,6 +698,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_pass_by_value, Normal, template!(Word), ErrorFollowing, "#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference." ), + rustc_attr!( + rustc_never_returns_null_ptr, Normal, template!(Word), ErrorFollowing, + "#[rustc_never_returns_null_ptr] is used to mark functions returning non-null pointers." + ), rustc_attr!( rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, @only_local: true, "#![rustc_coherence_is_core] allows inherent methods on builtin types, only intended to be used in `core`." diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index 02aff91032fd9..52d8099091abf 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -49,7 +49,7 @@ fn ptr_cast_chain<'a>(cx: &'a LateContext<'_>, mut e: &'a Expr<'a>) -> Option<&' } else if let ExprKind::Call(path, [arg]) = e.kind && let ExprKind::Path(ref qpath) = path.kind && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_from_ref | sym::ptr_from_mut)) { + && cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr) { had_at_least_one_cast = true; arg } else if had_at_least_one_cast { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index cbb030958c693..bec12ca185e70 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -139,6 +139,9 @@ impl CheckAttrVisitor<'_> { self.check_rustc_std_internal_symbol(&attr, span, target) } sym::naked => self.check_naked(hir_id, attr, span, target), + sym::rustc_never_returns_null_ptr => { + self.check_applied_to_fn_or_method(hir_id, attr, span, target) + } sym::rustc_legacy_const_generics => { self.check_rustc_legacy_const_generics(hir_id, &attr, span, target, item) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 44820ae6f727c..07d48170add4e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1311,6 +1311,7 @@ symbols! { rustc_main, rustc_mir, rustc_must_implement_one_of, + rustc_never_returns_null_ptr, rustc_nonnull_optimization_guaranteed, rustc_nounwind, rustc_object_lifetime_default, From 33970db8c6a50a4a8c0fbb3d7d94893de24b98b5 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 5 Aug 2023 14:01:56 +0200 Subject: [PATCH 2/4] Add #[rustc_never_returns_null_ptr] to std functions Add the attribute to standard library functions that are guaranteed to never return null pointers, as their originating data wouldn't allow it. --- library/alloc/src/rc.rs | 2 ++ library/alloc/src/sync.rs | 2 ++ library/alloc/src/vec/mod.rs | 2 ++ library/core/src/cell.rs | 4 ++++ library/core/src/ffi/c_str.rs | 1 + library/core/src/ptr/mod.rs | 2 ++ library/core/src/ptr/non_null.rs | 2 ++ library/core/src/slice/mod.rs | 2 ++ library/core/src/str/mod.rs | 2 ++ library/core/src/sync/atomic.rs | 3 +++ 10 files changed, 22 insertions(+) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 60b07485c3a8e..c6693626e0aa6 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1304,6 +1304,7 @@ impl Rc { /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub fn into_raw(this: Self) -> *const T { let ptr = Self::as_ptr(&this); mem::forget(this); @@ -1327,6 +1328,7 @@ impl Rc { /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` #[stable(feature = "weak_into_raw", since = "1.45.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub fn as_ptr(this: &Self) -> *const T { let ptr: *mut RcBox = NonNull::as_ptr(this.ptr); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 6c701225a848f..d085466d8470a 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1455,6 +1455,7 @@ impl Arc { /// ``` #[must_use = "losing the pointer will leak memory"] #[stable(feature = "rc_raw", since = "1.17.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub fn into_raw(this: Self) -> *const T { let ptr = Self::as_ptr(&this); mem::forget(this); @@ -1479,6 +1480,7 @@ impl Arc { /// ``` #[must_use] #[stable(feature = "rc_as_ptr", since = "1.45.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub fn as_ptr(this: &Self) -> *const T { let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index e45ddc7896beb..a7bd8fdd42457 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1233,6 +1233,7 @@ impl Vec { /// /// [`as_mut_ptr`]: Vec::as_mut_ptr #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] #[inline] pub fn as_ptr(&self) -> *const T { // We shadow the slice method of the same name to avoid going through @@ -1266,6 +1267,7 @@ impl Vec { /// assert_eq!(&*x, &[0, 1, 2, 3]); /// ``` #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] #[inline] pub fn as_mut_ptr(&mut self) -> *mut T { // We shadow the slice method of the same name to avoid going through diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index bf4c682d33e5a..82e24644414d6 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -543,6 +543,7 @@ impl Cell { #[inline] #[stable(feature = "cell_as_ptr", since = "1.12.0")] #[rustc_const_stable(feature = "const_cell_as_ptr", since = "1.32.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub const fn as_ptr(&self) -> *mut T { self.value.get() } @@ -1076,6 +1077,7 @@ impl RefCell { /// ``` #[inline] #[stable(feature = "cell_as_ptr", since = "1.12.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub fn as_ptr(&self) -> *mut T { self.value.get() } @@ -2071,6 +2073,7 @@ impl UnsafeCell { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub const fn get(&self) -> *mut T { // We can just cast the pointer from `UnsafeCell` to `T` because of // #[repr(transparent)]. This exploits std's special status, there is @@ -2213,6 +2216,7 @@ impl SyncUnsafeCell { /// when casting to `&mut T`, and ensure that there are no mutations /// or mutable aliases going on when casting to `&T` #[inline] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub const fn get(&self) -> *mut T { self.value.get() } diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index b59ec12790d24..388a545d3d985 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -509,6 +509,7 @@ impl CStr { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub const fn as_ptr(&self) -> *const c_char { self.inner.as_ptr() } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 5f094ac4e7e64..84cc2e474a135 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -698,6 +698,7 @@ where #[inline(always)] #[must_use] #[unstable(feature = "ptr_from_ref", issue = "106116")] +#[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] #[rustc_diagnostic_item = "ptr_from_ref"] pub const fn from_ref(r: &T) -> *const T { r @@ -710,6 +711,7 @@ pub const fn from_ref(r: &T) -> *const T { #[inline(always)] #[must_use] #[unstable(feature = "ptr_from_ref", issue = "106116")] +#[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] #[rustc_diagnostic_item = "ptr_from_mut"] pub const fn from_mut(r: &mut T) -> *mut T { r diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 9582ca9e0beff..77a2e0775a3b5 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -320,6 +320,7 @@ impl NonNull { /// ``` #[stable(feature = "nonnull", since = "1.25.0")] #[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] #[must_use] #[inline(always)] pub const fn as_ptr(self) -> *mut T { @@ -579,6 +580,7 @@ impl NonNull<[T]> { #[must_use] #[unstable(feature = "slice_ptr_get", issue = "74265")] #[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub const fn as_mut_ptr(self) -> *mut T { self.as_non_null_ptr().as_ptr() } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d95662afddd46..0d635aced85bf 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -730,6 +730,7 @@ impl [T] { /// [`as_mut_ptr`]: slice::as_mut_ptr #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] #[inline(always)] #[must_use] pub const fn as_ptr(&self) -> *const T { @@ -760,6 +761,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[rustc_allow_const_fn_unstable(const_mut_refs)] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] #[inline(always)] #[must_use] pub const fn as_mut_ptr(&mut self) -> *mut T { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 71c03f7bfc579..569707a40f31a 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -387,6 +387,7 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] #[must_use] #[inline(always)] pub const fn as_ptr(&self) -> *const u8 { @@ -402,6 +403,7 @@ impl str { /// It is your responsibility to make sure that the string slice only gets /// modified in a way that it remains valid UTF-8. #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] #[must_use] #[inline(always)] pub fn as_mut_ptr(&mut self) -> *mut u8 { diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 22a1c09782ce8..cf1fbe2d389d7 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1018,6 +1018,7 @@ impl AtomicBool { #[inline] #[stable(feature = "atomic_as_ptr", since = "1.70.0")] #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub const fn as_ptr(&self) -> *mut bool { self.v.get().cast() } @@ -1953,6 +1954,7 @@ impl AtomicPtr { #[inline] #[stable(feature = "atomic_as_ptr", since = "1.70.0")] #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub const fn as_ptr(&self) -> *mut *mut T { self.p.get() } @@ -2891,6 +2893,7 @@ macro_rules! atomic_int { #[inline] #[stable(feature = "atomic_as_ptr", since = "1.70.0")] #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] pub const fn as_ptr(&self) -> *mut $int_type { self.v.get() } From 8faac74e54e8a76cd4ff860c1b6da3836e4a1b1e Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 5 Aug 2023 05:14:32 +0200 Subject: [PATCH 3/4] Remove ptr_from_mut diagnostic item It was added by #113657 for its purposes. Now it is not used any more, remove it, as we use the attr now. --- compiler/rustc_span/src/symbol.rs | 1 - library/core/src/ptr/mod.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 07d48170add4e..46f3487475b2c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1159,7 +1159,6 @@ symbols! { ptr_cast, ptr_cast_mut, ptr_const_is_null, - ptr_from_mut, ptr_from_ref, ptr_guaranteed_cmp, ptr_is_null, diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 84cc2e474a135..8d1a4de9de606 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -712,7 +712,6 @@ pub const fn from_ref(r: &T) -> *const T { #[must_use] #[unstable(feature = "ptr_from_ref", issue = "106116")] #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] -#[rustc_diagnostic_item = "ptr_from_mut"] pub const fn from_mut(r: &mut T) -> *mut T { r } From 4b1bc2701067d7b340d102d40227091c00447f48 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 6 Aug 2023 01:25:24 +0200 Subject: [PATCH 4/4] Improve diagnostics and add tests for function calls --- compiler/rustc_lint/messages.ftl | 2 ++ compiler/rustc_lint/src/lints.rs | 2 ++ compiler/rustc_lint/src/ptr_nulls.rs | 52 ++++++++++++++++------------ tests/ui/lint/ptr_null_checks.rs | 14 +++++--- tests/ui/lint/ptr_null_checks.stderr | 38 +++++++++++--------- 5 files changed, 64 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index c4a7f717840ce..61f68db2cc0cf 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -457,6 +457,8 @@ lint_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking th .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value .label = expression has type `{$orig_ty}` +lint_ptr_null_checks_fn_ret = returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false + lint_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false .label = expression has type `{$orig_ty}` diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 70311a5c57653..049a7c3f7fa54 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -634,6 +634,8 @@ pub enum PtrNullChecksDiag<'a> { #[label] label: Span, }, + #[diag(lint_ptr_null_checks_fn_ret)] + FnRet { fn_name: Ident }, } // for_loops_over_fallibles.rs diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index 52d8099091abf..0de72d8d3dbc0 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -31,12 +31,30 @@ declare_lint! { declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS]); -/// This function detects and returns the original expression from a series of consecutive casts, -/// ie. `(my_fn as *const _ as *mut _).cast_mut()` would return the expression for `my_fn`. -fn ptr_cast_chain<'a>(cx: &'a LateContext<'_>, mut e: &'a Expr<'a>) -> Option<&'a Expr<'a>> { +/// This function checks if the expression is from a series of consecutive casts, +/// ie. `(my_fn as *const _ as *mut _).cast_mut()` and whether the original expression is either +/// a fn ptr, a reference, or a function call whose definition is +/// annotated with `#![rustc_never_returns_null_ptr]`. +/// If this situation is present, the function returns the appropriate diagnostic. +fn incorrect_check<'a, 'tcx: 'a>( + cx: &'a LateContext<'tcx>, + mut e: &'a Expr<'a>, +) -> Option> { let mut had_at_least_one_cast = false; loop { e = e.peel_blocks(); + if let ExprKind::MethodCall(_, _expr, [], _) = e.kind + && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) + && cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr) + && let Some(fn_name) = cx.tcx.opt_item_ident(def_id) { + return Some(PtrNullChecksDiag::FnRet { fn_name }); + } else if let ExprKind::Call(path, _args) = e.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr) + && let Some(fn_name) = cx.tcx.opt_item_ident(def_id) { + return Some(PtrNullChecksDiag::FnRet { fn_name }); + } e = if let ExprKind::Cast(expr, t) = e.kind && let TyKind::Ptr(_) = t.kind { had_at_least_one_cast = true; @@ -46,33 +64,21 @@ fn ptr_cast_chain<'a>(cx: &'a LateContext<'_>, mut e: &'a Expr<'a>) -> Option<&' && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_cast | sym::ptr_cast_mut)) { had_at_least_one_cast = true; expr - } else if let ExprKind::Call(path, [arg]) = e.kind - && let ExprKind::Path(ref qpath) = path.kind - && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr) { - had_at_least_one_cast = true; - arg } else if had_at_least_one_cast { - return Some(e); + let orig_ty = cx.typeck_results().expr_ty(e); + return if orig_ty.is_fn() { + Some(PtrNullChecksDiag::FnPtr { orig_ty, label: e.span }) + } else if orig_ty.is_ref() { + Some(PtrNullChecksDiag::Ref { orig_ty, label: e.span }) + } else { + None + }; } else { return None; }; } } -fn incorrect_check<'a>(cx: &LateContext<'a>, expr: &Expr<'_>) -> Option> { - let expr = ptr_cast_chain(cx, expr)?; - - let orig_ty = cx.typeck_results().expr_ty(expr); - if orig_ty.is_fn() { - Some(PtrNullChecksDiag::FnPtr { orig_ty, label: expr.span }) - } else if orig_ty.is_ref() { - Some(PtrNullChecksDiag::Ref { orig_ty, label: expr.span }) - } else { - None - } -} - impl<'tcx> LateLintPass<'tcx> for PtrNullChecks { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { match expr.kind { diff --git a/tests/ui/lint/ptr_null_checks.rs b/tests/ui/lint/ptr_null_checks.rs index e677ea3094d5e..3028084e96226 100644 --- a/tests/ui/lint/ptr_null_checks.rs +++ b/tests/ui/lint/ptr_null_checks.rs @@ -38,15 +38,15 @@ fn main() { if (&mut 8 as *mut i32).is_null() {} //~^ WARN references are not nullable if ptr::from_mut(&mut 8).is_null() {} - //~^ WARN references are not nullable + //~^ WARN call is never null if (&8 as *const i32).is_null() {} //~^ WARN references are not nullable if ptr::from_ref(&8).is_null() {} - //~^ WARN references are not nullable + //~^ WARN call is never null if ptr::from_ref(&8).cast_mut().is_null() {} - //~^ WARN references are not nullable + //~^ WARN call is never null if (ptr::from_ref(&8).cast_mut() as *mut i32).is_null() {} - //~^ WARN references are not nullable + //~^ WARN call is never null if (&8 as *const i32) == std::ptr::null() {} //~^ WARN references are not nullable let ref_num = &8; @@ -65,6 +65,12 @@ fn main() { if (&*{ static_i32() } as *const i32).is_null() {} //~^ WARN references are not nullable + // ---------------- Functions ------------------- + if ptr::NonNull::new(&mut 8).unwrap().as_ptr().is_null() {} + //~^ WARN call is never null + if ptr::NonNull::::dangling().as_ptr().is_null() {} + //~^ WARN call is never null + // ---------------------------------------------- const ZPTR: *const () = 0 as *const _; const NOT_ZPTR: *const () = 1 as *const _; diff --git a/tests/ui/lint/ptr_null_checks.stderr b/tests/ui/lint/ptr_null_checks.stderr index 3cee1804b62ae..0edc1b865361e 100644 --- a/tests/ui/lint/ptr_null_checks.stderr +++ b/tests/ui/lint/ptr_null_checks.stderr @@ -117,13 +117,11 @@ LL | if (&mut 8 as *mut i32).is_null() {} | | | expression has type `&mut i32` -warning: references are not nullable, so checking them for null will always return false +warning: returned pointer of `from_mut` call is never null, so checking it for null will always return false --> $DIR/ptr_null_checks.rs:40:8 | LL | if ptr::from_mut(&mut 8).is_null() {} - | ^^^^^^^^^^^^^^------^^^^^^^^^^^ - | | - | expression has type `&mut i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: references are not nullable, so checking them for null will always return false --> $DIR/ptr_null_checks.rs:42:8 @@ -133,29 +131,23 @@ LL | if (&8 as *const i32).is_null() {} | | | expression has type `&i32` -warning: references are not nullable, so checking them for null will always return false +warning: returned pointer of `from_ref` call is never null, so checking it for null will always return false --> $DIR/ptr_null_checks.rs:44:8 | LL | if ptr::from_ref(&8).is_null() {} - | ^^^^^^^^^^^^^^--^^^^^^^^^^^ - | | - | expression has type `&i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: references are not nullable, so checking them for null will always return false +warning: returned pointer of `from_ref` call is never null, so checking it for null will always return false --> $DIR/ptr_null_checks.rs:46:8 | LL | if ptr::from_ref(&8).cast_mut().is_null() {} - | ^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^ - | | - | expression has type `&i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: references are not nullable, so checking them for null will always return false +warning: returned pointer of `from_ref` call is never null, so checking it for null will always return false --> $DIR/ptr_null_checks.rs:48:8 | LL | if (ptr::from_ref(&8).cast_mut() as *mut i32).is_null() {} - | ^^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | expression has type `&i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: references are not nullable, so checking them for null will always return false --> $DIR/ptr_null_checks.rs:50:8 @@ -221,5 +213,17 @@ LL | if (&*{ static_i32() } as *const i32).is_null() {} | | | expression has type `&i32` -warning: 25 warnings emitted +warning: returned pointer of `as_ptr` call is never null, so checking it for null will always return false + --> $DIR/ptr_null_checks.rs:69:8 + | +LL | if ptr::NonNull::new(&mut 8).unwrap().as_ptr().is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: returned pointer of `as_ptr` call is never null, so checking it for null will always return false + --> $DIR/ptr_null_checks.rs:71:8 + | +LL | if ptr::NonNull::::dangling().as_ptr().is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 27 warnings emitted