Skip to content

Commit 496adf8

Browse files
authored
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
2 parents e7813fe + 3296729 commit 496adf8

File tree

5 files changed

+190
-0
lines changed

5 files changed

+190
-0
lines changed

Diff for: compiler/rustc_hir_typeck/src/demand.rs

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6060
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
6161
|| self.suggest_into(err, expr, expr_ty, expected)
6262
|| self.suggest_floating_point_literal(err, expr, expected)
63+
|| self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
6364
|| self.note_result_coercion(err, expr, expected, expr_ty);
6465
if !suggested {
6566
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected, expr.span);

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+44
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_hir::{
1313
use rustc_hir_analysis::astconv::AstConv;
1414
use rustc_infer::traits::{self, StatementAsExpression};
1515
use rustc_middle::lint::in_external_macro;
16+
use rustc_middle::ty::print::with_no_trimmed_paths;
1617
use rustc_middle::ty::{
1718
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
1819
TypeVisitable,
@@ -1244,6 +1245,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12441245
}
12451246
}
12461247

1248+
/// Suggest providing `std::ptr::null()` or `std::ptr::null_mut()` if they
1249+
/// pass in a literal 0 to an raw pointer.
1250+
#[instrument(skip(self, err))]
1251+
pub(crate) fn suggest_null_ptr_for_literal_zero_given_to_ptr_arg(
1252+
&self,
1253+
err: &mut Diagnostic,
1254+
expr: &hir::Expr<'_>,
1255+
expected_ty: Ty<'tcx>,
1256+
) -> bool {
1257+
// Expected type needs to be a raw pointer.
1258+
let ty::RawPtr(ty::TypeAndMut { mutbl, .. }) = expected_ty.kind() else {
1259+
return false;
1260+
};
1261+
1262+
// Provided expression needs to be a literal `0`.
1263+
let ExprKind::Lit(Spanned {
1264+
node: rustc_ast::LitKind::Int(0, _),
1265+
span,
1266+
}) = expr.kind else {
1267+
return false;
1268+
};
1269+
1270+
// We need to find a null pointer symbol to suggest
1271+
let null_sym = match mutbl {
1272+
hir::Mutability::Not => sym::ptr_null,
1273+
hir::Mutability::Mut => sym::ptr_null_mut,
1274+
};
1275+
let Some(null_did) = self.tcx.get_diagnostic_item(null_sym) else {
1276+
return false;
1277+
};
1278+
let null_path_str = with_no_trimmed_paths!(self.tcx.def_path_str(null_did));
1279+
1280+
// We have satisfied all requirements to provide a suggestion. Emit it.
1281+
err.span_suggestion(
1282+
span,
1283+
format!("if you meant to create a null pointer, use `{null_path_str}()`"),
1284+
null_path_str + "()",
1285+
Applicability::MachineApplicable,
1286+
);
1287+
1288+
true
1289+
}
1290+
12471291
pub(crate) fn suggest_associated_const(
12481292
&self,
12491293
err: &mut Diagnostic,

Diff for: tests/ui/suggest-null-ptr.fixed

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// run-rustfix
2+
3+
// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw
4+
// pointer if a literal 0 was provided by the user.
5+
6+
extern "C" {
7+
fn foo(ptr: *const u8);
8+
9+
fn foo_mut(ptr: *mut u8);
10+
11+
fn usize(ptr: *const usize);
12+
13+
fn usize_mut(ptr: *mut usize);
14+
}
15+
16+
fn main() {
17+
unsafe {
18+
foo(std::ptr::null());
19+
//~^ mismatched types [E0308]
20+
//~| if you meant to create a null pointer, use `std::ptr::null()`
21+
foo_mut(std::ptr::null_mut());
22+
//~^ mismatched types [E0308]
23+
//~| if you meant to create a null pointer, use `std::ptr::null_mut()`
24+
usize(std::ptr::null());
25+
//~^ mismatched types [E0308]
26+
//~| if you meant to create a null pointer, use `std::ptr::null()`
27+
usize_mut(std::ptr::null_mut());
28+
//~^ mismatched types [E0308]
29+
//~| if you meant to create a null pointer, use `std::ptr::null_mut()`
30+
}
31+
}

Diff for: tests/ui/suggest-null-ptr.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// run-rustfix
2+
3+
// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw
4+
// pointer if a literal 0 was provided by the user.
5+
6+
extern "C" {
7+
fn foo(ptr: *const u8);
8+
9+
fn foo_mut(ptr: *mut u8);
10+
11+
fn usize(ptr: *const usize);
12+
13+
fn usize_mut(ptr: *mut usize);
14+
}
15+
16+
fn main() {
17+
unsafe {
18+
foo(0);
19+
//~^ mismatched types [E0308]
20+
//~| if you meant to create a null pointer, use `std::ptr::null()`
21+
foo_mut(0);
22+
//~^ mismatched types [E0308]
23+
//~| if you meant to create a null pointer, use `std::ptr::null_mut()`
24+
usize(0);
25+
//~^ mismatched types [E0308]
26+
//~| if you meant to create a null pointer, use `std::ptr::null()`
27+
usize_mut(0);
28+
//~^ mismatched types [E0308]
29+
//~| if you meant to create a null pointer, use `std::ptr::null_mut()`
30+
}
31+
}

Diff for: tests/ui/suggest-null-ptr.stderr

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/suggest-null-ptr.rs:18:13
3+
|
4+
LL | foo(0);
5+
| --- ^ expected `*const u8`, found `usize`
6+
| |
7+
| arguments to this function are incorrect
8+
|
9+
= note: expected raw pointer `*const u8`
10+
found type `usize`
11+
note: function defined here
12+
--> $DIR/suggest-null-ptr.rs:7:8
13+
|
14+
LL | fn foo(ptr: *const u8);
15+
| ^^^
16+
help: if you meant to create a null pointer, use `std::ptr::null()`
17+
|
18+
LL | foo(std::ptr::null());
19+
| ~~~~~~~~~~~~~~~~
20+
21+
error[E0308]: mismatched types
22+
--> $DIR/suggest-null-ptr.rs:21:17
23+
|
24+
LL | foo_mut(0);
25+
| ------- ^ expected `*mut u8`, found `usize`
26+
| |
27+
| arguments to this function are incorrect
28+
|
29+
= note: expected raw pointer `*mut u8`
30+
found type `usize`
31+
note: function defined here
32+
--> $DIR/suggest-null-ptr.rs:9:8
33+
|
34+
LL | fn foo_mut(ptr: *mut u8);
35+
| ^^^^^^^
36+
help: if you meant to create a null pointer, use `std::ptr::null_mut()`
37+
|
38+
LL | foo_mut(std::ptr::null_mut());
39+
| ~~~~~~~~~~~~~~~~~~~~
40+
41+
error[E0308]: mismatched types
42+
--> $DIR/suggest-null-ptr.rs:24:15
43+
|
44+
LL | usize(0);
45+
| ----- ^ expected `*const usize`, found `usize`
46+
| |
47+
| arguments to this function are incorrect
48+
|
49+
= note: expected raw pointer `*const usize`
50+
found type `usize`
51+
note: function defined here
52+
--> $DIR/suggest-null-ptr.rs:11:8
53+
|
54+
LL | fn usize(ptr: *const usize);
55+
| ^^^^^
56+
help: if you meant to create a null pointer, use `std::ptr::null()`
57+
|
58+
LL | usize(std::ptr::null());
59+
| ~~~~~~~~~~~~~~~~
60+
61+
error[E0308]: mismatched types
62+
--> $DIR/suggest-null-ptr.rs:27:19
63+
|
64+
LL | usize_mut(0);
65+
| --------- ^ expected `*mut usize`, found `usize`
66+
| |
67+
| arguments to this function are incorrect
68+
|
69+
= note: expected raw pointer `*mut usize`
70+
found type `usize`
71+
note: function defined here
72+
--> $DIR/suggest-null-ptr.rs:13:8
73+
|
74+
LL | fn usize_mut(ptr: *mut usize);
75+
| ^^^^^^^^^
76+
help: if you meant to create a null pointer, use `std::ptr::null_mut()`
77+
|
78+
LL | usize_mut(std::ptr::null_mut());
79+
| ~~~~~~~~~~~~~~~~~~~~
80+
81+
error: aborting due to 4 previous errors
82+
83+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)