about summary refs log tree commit diff
diff options
context:
space:
mode:
author许杰友 Jieyou Xu (Joe) <jieyouxu@outlook.com>2023-06-05 15:17:49 +0800
committer许杰友 Jieyou Xu (Joe) <jieyouxu@outlook.com>2023-06-09 20:05:46 +0800
commit432ce39c8bb5520cdaea7a633c86eb11036a5985 (patch)
tree35a14a0319c6c6100ff0b15bd4806d232794ad88
parent8b35c0bb0f833c0077dc57006eb317edde2a2d1e (diff)
downloadrust-432ce39c8bb5520cdaea7a633c86eb11036a5985.tar.gz
rust-432ce39c8bb5520cdaea7a633c86eb11036a5985.zip
Suggest using `ptr::null_mut` when user supplied `ptr::null` to a function expecting `ptr::null_mut`
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl2
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs30
-rw-r--r--tests/ui/typeck/ptr-null-mutability-suggestions.fixed11
-rw-r--r--tests/ui/typeck/ptr-null-mutability-suggestions.rs11
-rw-r--r--tests/ui/typeck/ptr-null-mutability-suggestions.stderr21
6 files changed, 86 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index aab432eee57..13ad524a32f 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -87,6 +87,8 @@ hir_typeck_suggest_boxing_note = for more on the distinction between the stack a
 
 hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new`
 
+hir_typeck_suggest_ptr_null_mut = consider using `core::ptr::null_mut` instead
+
 hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
 
 hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 4222205c841..92fed230a08 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -298,6 +298,17 @@ pub enum SuggestBoxing {
     },
 }
 
+#[derive(Subdiagnostic)]
+#[suggestion(
+    hir_typeck_suggest_ptr_null_mut,
+    applicability = "maybe-incorrect",
+    code = "core::ptr::null_mut()"
+)]
+pub struct SuggestPtrNullMut {
+    #[primary_span]
+    pub span: Span,
+}
+
 #[derive(Diagnostic)]
 #[diag(hir_typeck_no_associated_item, code = "E0599")]
 pub struct NoAssociatedItem {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 30a543aab50..b7ddfcf006d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1,4 +1,5 @@
 use crate::coercion::CoerceMany;
+use crate::errors::SuggestPtrNullMut;
 use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
 use crate::gather_locals::Declaration;
 use crate::method::MethodCallee;
@@ -814,6 +815,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             }
 
+            self.suggest_ptr_null_mut(
+                expected_ty,
+                provided_ty,
+                provided_args[*provided_idx],
+                &mut err,
+            );
+
             // Call out where the function is defined
             self.label_fn_like(
                 &mut err,
@@ -1271,6 +1279,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.emit();
     }
 
+    fn suggest_ptr_null_mut(
+        &self,
+        expected_ty: Ty<'tcx>,
+        provided_ty: Ty<'tcx>,
+        arg: &hir::Expr<'tcx>,
+        err: &mut rustc_errors::DiagnosticBuilder<'tcx, ErrorGuaranteed>,
+    ) {
+        if let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Mut, .. }) = expected_ty.kind()
+            && let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Not, .. }) = provided_ty.kind()
+            && let hir::ExprKind::Call(callee, _) = arg.kind
+            && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind
+            && let Res::Def(_, def_id) = path.res
+            && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id)
+        {
+            // The user provided `ptr::null()`, but the function expects
+            // `ptr::null_mut()`.
+            err.subdiagnostic(SuggestPtrNullMut {
+                span: arg.span
+            });
+        }
+    }
+
     // AST fragment checking
     pub(in super::super) fn check_lit(
         &self,
diff --git a/tests/ui/typeck/ptr-null-mutability-suggestions.fixed b/tests/ui/typeck/ptr-null-mutability-suggestions.fixed
new file mode 100644
index 00000000000..d00536b29cf
--- /dev/null
+++ b/tests/ui/typeck/ptr-null-mutability-suggestions.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#[allow(unused_imports)]
+use std::ptr;
+
+fn expecting_null_mut(_: *mut u8) {}
+
+fn main() {
+    expecting_null_mut(core::ptr::null_mut());
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/typeck/ptr-null-mutability-suggestions.rs b/tests/ui/typeck/ptr-null-mutability-suggestions.rs
new file mode 100644
index 00000000000..ea3066d2289
--- /dev/null
+++ b/tests/ui/typeck/ptr-null-mutability-suggestions.rs
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#[allow(unused_imports)]
+use std::ptr;
+
+fn expecting_null_mut(_: *mut u8) {}
+
+fn main() {
+    expecting_null_mut(ptr::null());
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/typeck/ptr-null-mutability-suggestions.stderr b/tests/ui/typeck/ptr-null-mutability-suggestions.stderr
new file mode 100644
index 00000000000..705b029bdea
--- /dev/null
+++ b/tests/ui/typeck/ptr-null-mutability-suggestions.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/ptr-null-mutability-suggestions.rs:9:24
+   |
+LL |     expecting_null_mut(ptr::null());
+   |     ------------------ ^^^^^^^^^^^
+   |     |                  |
+   |     |                  types differ in mutability
+   |     |                  help: consider using `core::ptr::null_mut` instead: `core::ptr::null_mut()`
+   |     arguments to this function are incorrect
+   |
+   = note: expected raw pointer `*mut u8`
+              found raw pointer `*const _`
+note: function defined here
+  --> $DIR/ptr-null-mutability-suggestions.rs:6:4
+   |
+LL | fn expecting_null_mut(_: *mut u8) {}
+   |    ^^^^^^^^^^^^^^^^^^ ----------
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.