mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 22:41:50 +00:00
Rollup merge of #107553 - edward-shen:edward-shen/suggest-null-ptr, r=WaffleLapkin
Suggest std::ptr::null if literal 0 is given to a raw pointer function argument Implementation feels a little sus (we're parsing the span for a `0`) but it seems to fall in line the string-expected-found-char condition right above this check, so I think it's fine. Feedback appreciated on help text? I think it's consistent but it does sound a little awkward maybe? Fixes #107517
This commit is contained in:
commit
496adf81de
@ -60,6 +60,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
|
||||
|| self.suggest_into(err, expr, expr_ty, expected)
|
||||
|| self.suggest_floating_point_literal(err, expr, expected)
|
||||
|| self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
|
||||
|| self.note_result_coercion(err, expr, expected, expr_ty);
|
||||
if !suggested {
|
||||
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected, expr.span);
|
||||
|
@ -13,6 +13,7 @@ use rustc_hir::{
|
||||
use rustc_hir_analysis::astconv::AstConv;
|
||||
use rustc_infer::traits::{self, StatementAsExpression};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{
|
||||
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
|
||||
TypeVisitable,
|
||||
@ -1244,6 +1245,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Suggest providing `std::ptr::null()` or `std::ptr::null_mut()` if they
|
||||
/// pass in a literal 0 to an raw pointer.
|
||||
#[instrument(skip(self, err))]
|
||||
pub(crate) fn suggest_null_ptr_for_literal_zero_given_to_ptr_arg(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
expected_ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
// Expected type needs to be a raw pointer.
|
||||
let ty::RawPtr(ty::TypeAndMut { mutbl, .. }) = expected_ty.kind() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Provided expression needs to be a literal `0`.
|
||||
let ExprKind::Lit(Spanned {
|
||||
node: rustc_ast::LitKind::Int(0, _),
|
||||
span,
|
||||
}) = expr.kind else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// We need to find a null pointer symbol to suggest
|
||||
let null_sym = match mutbl {
|
||||
hir::Mutability::Not => sym::ptr_null,
|
||||
hir::Mutability::Mut => sym::ptr_null_mut,
|
||||
};
|
||||
let Some(null_did) = self.tcx.get_diagnostic_item(null_sym) else {
|
||||
return false;
|
||||
};
|
||||
let null_path_str = with_no_trimmed_paths!(self.tcx.def_path_str(null_did));
|
||||
|
||||
// We have satisfied all requirements to provide a suggestion. Emit it.
|
||||
err.span_suggestion(
|
||||
span,
|
||||
format!("if you meant to create a null pointer, use `{null_path_str}()`"),
|
||||
null_path_str + "()",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub(crate) fn suggest_associated_const(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
|
31
tests/ui/suggest-null-ptr.fixed
Normal file
31
tests/ui/suggest-null-ptr.fixed
Normal file
@ -0,0 +1,31 @@
|
||||
// run-rustfix
|
||||
|
||||
// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw
|
||||
// pointer if a literal 0 was provided by the user.
|
||||
|
||||
extern "C" {
|
||||
fn foo(ptr: *const u8);
|
||||
|
||||
fn foo_mut(ptr: *mut u8);
|
||||
|
||||
fn usize(ptr: *const usize);
|
||||
|
||||
fn usize_mut(ptr: *mut usize);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
foo(std::ptr::null());
|
||||
//~^ mismatched types [E0308]
|
||||
//~| if you meant to create a null pointer, use `std::ptr::null()`
|
||||
foo_mut(std::ptr::null_mut());
|
||||
//~^ mismatched types [E0308]
|
||||
//~| if you meant to create a null pointer, use `std::ptr::null_mut()`
|
||||
usize(std::ptr::null());
|
||||
//~^ mismatched types [E0308]
|
||||
//~| if you meant to create a null pointer, use `std::ptr::null()`
|
||||
usize_mut(std::ptr::null_mut());
|
||||
//~^ mismatched types [E0308]
|
||||
//~| if you meant to create a null pointer, use `std::ptr::null_mut()`
|
||||
}
|
||||
}
|
31
tests/ui/suggest-null-ptr.rs
Normal file
31
tests/ui/suggest-null-ptr.rs
Normal file
@ -0,0 +1,31 @@
|
||||
// run-rustfix
|
||||
|
||||
// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw
|
||||
// pointer if a literal 0 was provided by the user.
|
||||
|
||||
extern "C" {
|
||||
fn foo(ptr: *const u8);
|
||||
|
||||
fn foo_mut(ptr: *mut u8);
|
||||
|
||||
fn usize(ptr: *const usize);
|
||||
|
||||
fn usize_mut(ptr: *mut usize);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
foo(0);
|
||||
//~^ mismatched types [E0308]
|
||||
//~| if you meant to create a null pointer, use `std::ptr::null()`
|
||||
foo_mut(0);
|
||||
//~^ mismatched types [E0308]
|
||||
//~| if you meant to create a null pointer, use `std::ptr::null_mut()`
|
||||
usize(0);
|
||||
//~^ mismatched types [E0308]
|
||||
//~| if you meant to create a null pointer, use `std::ptr::null()`
|
||||
usize_mut(0);
|
||||
//~^ mismatched types [E0308]
|
||||
//~| if you meant to create a null pointer, use `std::ptr::null_mut()`
|
||||
}
|
||||
}
|
83
tests/ui/suggest-null-ptr.stderr
Normal file
83
tests/ui/suggest-null-ptr.stderr
Normal file
@ -0,0 +1,83 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-null-ptr.rs:18:13
|
||||
|
|
||||
LL | foo(0);
|
||||
| --- ^ expected `*const u8`, found `usize`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected raw pointer `*const u8`
|
||||
found type `usize`
|
||||
note: function defined here
|
||||
--> $DIR/suggest-null-ptr.rs:7:8
|
||||
|
|
||||
LL | fn foo(ptr: *const u8);
|
||||
| ^^^
|
||||
help: if you meant to create a null pointer, use `std::ptr::null()`
|
||||
|
|
||||
LL | foo(std::ptr::null());
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-null-ptr.rs:21:17
|
||||
|
|
||||
LL | foo_mut(0);
|
||||
| ------- ^ expected `*mut u8`, found `usize`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected raw pointer `*mut u8`
|
||||
found type `usize`
|
||||
note: function defined here
|
||||
--> $DIR/suggest-null-ptr.rs:9:8
|
||||
|
|
||||
LL | fn foo_mut(ptr: *mut u8);
|
||||
| ^^^^^^^
|
||||
help: if you meant to create a null pointer, use `std::ptr::null_mut()`
|
||||
|
|
||||
LL | foo_mut(std::ptr::null_mut());
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-null-ptr.rs:24:15
|
||||
|
|
||||
LL | usize(0);
|
||||
| ----- ^ expected `*const usize`, found `usize`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected raw pointer `*const usize`
|
||||
found type `usize`
|
||||
note: function defined here
|
||||
--> $DIR/suggest-null-ptr.rs:11:8
|
||||
|
|
||||
LL | fn usize(ptr: *const usize);
|
||||
| ^^^^^
|
||||
help: if you meant to create a null pointer, use `std::ptr::null()`
|
||||
|
|
||||
LL | usize(std::ptr::null());
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-null-ptr.rs:27:19
|
||||
|
|
||||
LL | usize_mut(0);
|
||||
| --------- ^ expected `*mut usize`, found `usize`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected raw pointer `*mut usize`
|
||||
found type `usize`
|
||||
note: function defined here
|
||||
--> $DIR/suggest-null-ptr.rs:13:8
|
||||
|
|
||||
LL | fn usize_mut(ptr: *mut usize);
|
||||
| ^^^^^^^^^
|
||||
help: if you meant to create a null pointer, use `std::ptr::null_mut()`
|
||||
|
|
||||
LL | usize_mut(std::ptr::null_mut());
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user