Skip to content

Commit fd9cebe

Browse files
committed
Auto merge of rust-lang#8210 - guerinoni:master, r=Manishearth
Add borrow_as_ptr lint Closes: rust-lang#6995 - \[x] Followed [lint naming conventions][lint_naming] - \[x] Added passing UI tests (including committed `.stderr` file) - \[x] `cargo test` passes locally - \[x] Executed `cargo dev update_lints` - \[x] Added lint documentation - \[x] Run `cargo dev fmt` --- changelog: new lint: [`borrow_as_ptr`]
2 parents fccf07b + 3298de7 commit fd9cebe

35 files changed

+294
-75
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -2887,6 +2887,7 @@ Released 2018-09-13
28872887
[`blocks_in_if_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_if_conditions
28882888
[`bool_assert_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_assert_comparison
28892889
[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison
2890+
[`borrow_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr
28902891
[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const
28912892
[`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box
28922893
[`box_collection`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_collection

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
77

8-
[There are over 450 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
8+
[There are over 500 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
99

1010
Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html).
1111
You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category.

clippy_lints/src/borrow_as_ptr.rs

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::is_no_std_crate;
3+
use clippy_utils::source::snippet_opt;
4+
use clippy_utils::{meets_msrv, msrvs};
5+
use if_chain::if_chain;
6+
use rustc_errors::Applicability;
7+
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, TyKind};
8+
use rustc_lint::{LateContext, LateLintPass};
9+
use rustc_semver::RustcVersion;
10+
use rustc_session::{declare_tool_lint, impl_lint_pass};
11+
12+
declare_clippy_lint! {
13+
/// ### What it does
14+
/// Checks for the usage of `&expr as *const T` or
15+
/// `&mut expr as *mut T`, and suggest using `ptr::addr_of` or
16+
/// `ptr::addr_of_mut` instead.
17+
///
18+
/// ### Why is this bad?
19+
/// This would improve readability and avoid creating a reference
20+
/// that points to an uninitialized value or unaligned place.
21+
/// Read the `ptr::addr_of` docs for more information.
22+
///
23+
/// ### Example
24+
/// ```rust
25+
/// let val = 1;
26+
/// let p = &val as *const i32;
27+
///
28+
/// let mut val_mut = 1;
29+
/// let p_mut = &mut val_mut as *mut i32;
30+
/// ```
31+
/// Use instead:
32+
/// ```rust
33+
/// let val = 1;
34+
/// let p = std::ptr::addr_of!(val);
35+
///
36+
/// let mut val_mut = 1;
37+
/// let p_mut = std::ptr::addr_of_mut!(val_mut);
38+
/// ```
39+
#[clippy::version = "1.60.0"]
40+
pub BORROW_AS_PTR,
41+
pedantic,
42+
"borrowing just to cast to a raw pointer"
43+
}
44+
45+
impl_lint_pass!(BorrowAsPtr => [BORROW_AS_PTR]);
46+
47+
pub struct BorrowAsPtr {
48+
msrv: Option<RustcVersion>,
49+
}
50+
51+
impl BorrowAsPtr {
52+
#[must_use]
53+
pub fn new(msrv: Option<RustcVersion>) -> Self {
54+
Self { msrv }
55+
}
56+
}
57+
58+
impl<'tcx> LateLintPass<'tcx> for BorrowAsPtr {
59+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
60+
if !meets_msrv(self.msrv.as_ref(), &msrvs::BORROW_AS_PTR) {
61+
return;
62+
}
63+
64+
if expr.span.from_expansion() {
65+
return;
66+
}
67+
68+
if_chain! {
69+
if let ExprKind::Cast(left_expr, ty) = &expr.kind;
70+
if let TyKind::Ptr(_) = ty.kind;
71+
if let ExprKind::AddrOf(BorrowKind::Ref, mutability, e) = &left_expr.kind;
72+
73+
then {
74+
let core_or_std = if is_no_std_crate(cx) { "core" } else { "std" };
75+
let macro_name = match mutability {
76+
Mutability::Not => "addr_of",
77+
Mutability::Mut => "addr_of_mut",
78+
};
79+
80+
span_lint_and_sugg(
81+
cx,
82+
BORROW_AS_PTR,
83+
expr.span,
84+
"borrow as raw pointer",
85+
"try",
86+
format!(
87+
"{}::ptr::{}!({})",
88+
core_or_std,
89+
macro_name,
90+
snippet_opt(cx, e.span).unwrap()
91+
),
92+
Applicability::MachineApplicable,
93+
);
94+
}
95+
}
96+
}
97+
}

clippy_lints/src/lib.register_lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ store.register_lints(&[
5959
bool_assert_comparison::BOOL_ASSERT_COMPARISON,
6060
booleans::LOGIC_BUG,
6161
booleans::NONMINIMAL_BOOL,
62+
borrow_as_ptr::BORROW_AS_PTR,
6263
bytecount::NAIVE_BYTECOUNT,
6364
cargo_common_metadata::CARGO_COMMON_METADATA,
6465
case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,

clippy_lints/src/lib.register_pedantic.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
77
LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK),
88
LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
99
LintId::of(bit_mask::VERBOSE_BIT_MASK),
10+
LintId::of(borrow_as_ptr::BORROW_AS_PTR),
1011
LintId::of(bytecount::NAIVE_BYTECOUNT),
1112
LintId::of(case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS),
1213
LintId::of(casts::CAST_LOSSLESS),

clippy_lints/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ mod blacklisted_name;
174174
mod blocks_in_if_conditions;
175175
mod bool_assert_comparison;
176176
mod booleans;
177+
mod borrow_as_ptr;
177178
mod bytecount;
178179
mod cargo_common_metadata;
179180
mod case_sensitive_file_extension_comparisons;
@@ -857,6 +858,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
857858
store.register_late_pass(|| Box::new(return_self_not_must_use::ReturnSelfNotMustUse));
858859
store.register_late_pass(|| Box::new(init_numbered_fields::NumberedFields));
859860
store.register_early_pass(|| Box::new(single_char_lifetime_names::SingleCharLifetimeNames));
861+
store.register_late_pass(move || Box::new(borrow_as_ptr::BorrowAsPtr::new(msrv)));
860862
// add lints here, do not remove this comment, it's used in `new_lint`
861863
}
862864

clippy_utils/src/msrvs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ macro_rules! msrv_aliases {
1414
msrv_aliases! {
1515
1,53,0 { OR_PATTERNS }
1616
1,52,0 { STR_SPLIT_ONCE }
17+
1,51,0 { BORROW_AS_PTR }
1718
1,50,0 { BOOL_THEN }
1819
1,47,0 { TAU }
1920
1,46,0 { CONST_IF_MATCH }

tests/ui/as_conversions.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// aux-build:macro_rules.rs
22

33
#![warn(clippy::as_conversions)]
4+
#![allow(clippy::borrow_as_ptr)]
45

56
#[macro_use]
67
extern crate macro_rules;

tests/ui/as_conversions.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: using a potentially dangerous silent `as` conversion
2-
--> $DIR/as_conversions.rs:14:13
2+
--> $DIR/as_conversions.rs:15:13
33
|
44
LL | let i = 0u32 as u64;
55
| ^^^^^^^^^^^
@@ -8,15 +8,15 @@ LL | let i = 0u32 as u64;
88
= help: consider using a safe wrapper for this conversion
99

1010
error: using a potentially dangerous silent `as` conversion
11-
--> $DIR/as_conversions.rs:16:13
11+
--> $DIR/as_conversions.rs:17:13
1212
|
1313
LL | let j = &i as *const u64 as *mut u64;
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1515
|
1616
= help: consider using a safe wrapper for this conversion
1717

1818
error: using a potentially dangerous silent `as` conversion
19-
--> $DIR/as_conversions.rs:16:13
19+
--> $DIR/as_conversions.rs:17:13
2020
|
2121
LL | let j = &i as *const u64 as *mut u64;
2222
| ^^^^^^^^^^^^^^^^

tests/ui/borrow_as_ptr.fixed

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// run-rustfix
2+
#![warn(clippy::borrow_as_ptr)]
3+
4+
fn main() {
5+
let val = 1;
6+
let _p = std::ptr::addr_of!(val);
7+
8+
let mut val_mut = 1;
9+
let _p_mut = std::ptr::addr_of_mut!(val_mut);
10+
}

tests/ui/borrow_as_ptr.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// run-rustfix
2+
#![warn(clippy::borrow_as_ptr)]
3+
4+
fn main() {
5+
let val = 1;
6+
let _p = &val as *const i32;
7+
8+
let mut val_mut = 1;
9+
let _p_mut = &mut val_mut as *mut i32;
10+
}

tests/ui/borrow_as_ptr.stderr

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: borrow as raw pointer
2+
--> $DIR/borrow_as_ptr.rs:6:14
3+
|
4+
LL | let _p = &val as *const i32;
5+
| ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of!(val)`
6+
|
7+
= note: `-D clippy::borrow-as-ptr` implied by `-D warnings`
8+
9+
error: borrow as raw pointer
10+
--> $DIR/borrow_as_ptr.rs:9:18
11+
|
12+
LL | let _p_mut = &mut val_mut as *mut i32;
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(val_mut)`
14+
15+
error: aborting due to 2 previous errors
16+

tests/ui/borrow_as_ptr_no_std.fixed

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// run-rustfix
2+
#![warn(clippy::borrow_as_ptr)]
3+
#![feature(lang_items, start, libc)]
4+
#![no_std]
5+
6+
#[start]
7+
fn main(_argc: isize, _argv: *const *const u8) -> isize {
8+
let val = 1;
9+
let _p = core::ptr::addr_of!(val);
10+
11+
let mut val_mut = 1;
12+
let _p_mut = core::ptr::addr_of_mut!(val_mut);
13+
0
14+
}
15+
16+
#[panic_handler]
17+
fn panic(_info: &core::panic::PanicInfo) -> ! {
18+
loop {}
19+
}
20+
21+
#[lang = "eh_personality"]
22+
extern "C" fn eh_personality() {}

tests/ui/borrow_as_ptr_no_std.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// run-rustfix
2+
#![warn(clippy::borrow_as_ptr)]
3+
#![feature(lang_items, start, libc)]
4+
#![no_std]
5+
6+
#[start]
7+
fn main(_argc: isize, _argv: *const *const u8) -> isize {
8+
let val = 1;
9+
let _p = &val as *const i32;
10+
11+
let mut val_mut = 1;
12+
let _p_mut = &mut val_mut as *mut i32;
13+
0
14+
}
15+
16+
#[panic_handler]
17+
fn panic(_info: &core::panic::PanicInfo) -> ! {
18+
loop {}
19+
}
20+
21+
#[lang = "eh_personality"]
22+
extern "C" fn eh_personality() {}

tests/ui/borrow_as_ptr_no_std.stderr

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: borrow as raw pointer
2+
--> $DIR/borrow_as_ptr_no_std.rs:9:14
3+
|
4+
LL | let _p = &val as *const i32;
5+
| ^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::addr_of!(val)`
6+
|
7+
= note: `-D clippy::borrow-as-ptr` implied by `-D warnings`
8+
9+
error: borrow as raw pointer
10+
--> $DIR/borrow_as_ptr_no_std.rs:12:18
11+
|
12+
LL | let _p_mut = &mut val_mut as *mut i32;
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::addr_of_mut!(val_mut)`
14+
15+
error: aborting due to 2 previous errors
16+

tests/ui/cast_alignment.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
extern crate libc;
55

66
#[warn(clippy::cast_ptr_alignment)]
7-
#[allow(clippy::no_effect, clippy::unnecessary_operation, clippy::cast_lossless)]
7+
#[allow(
8+
clippy::no_effect,
9+
clippy::unnecessary_operation,
10+
clippy::cast_lossless,
11+
clippy::borrow_as_ptr
12+
)]
13+
814
fn main() {
915
/* These should be warned against */
1016

tests/ui/cast_alignment.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) (1 < 2 bytes)
2-
--> $DIR/cast_alignment.rs:12:5
2+
--> $DIR/cast_alignment.rs:18:5
33
|
44
LL | (&1u8 as *const u8) as *const u16;
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: `-D clippy::cast-ptr-alignment` implied by `-D warnings`
88

99
error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes)
10-
--> $DIR/cast_alignment.rs:13:5
10+
--> $DIR/cast_alignment.rs:19:5
1111
|
1212
LL | (&mut 1u8 as *mut u8) as *mut u16;
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1414

1515
error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) (1 < 2 bytes)
16-
--> $DIR/cast_alignment.rs:16:5
16+
--> $DIR/cast_alignment.rs:22:5
1717
|
1818
LL | (&1u8 as *const u8).cast::<u16>();
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2020

2121
error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes)
22-
--> $DIR/cast_alignment.rs:17:5
22+
--> $DIR/cast_alignment.rs:23:5
2323
|
2424
LL | (&mut 1u8 as *mut u8).cast::<u16>();
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/ui/cast_ref_to_mut.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![warn(clippy::cast_ref_to_mut)]
2-
#![allow(clippy::no_effect)]
2+
#![allow(clippy::no_effect, clippy::borrow_as_ptr)]
33

44
extern "C" {
55
// N.B., mutability can be easily incorrect in FFI calls -- as

tests/ui/mutex_atomic.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![warn(clippy::all)]
22
#![warn(clippy::mutex_integer)]
33
#![warn(clippy::mutex_atomic)]
4+
#![allow(clippy::borrow_as_ptr)]
45

56
fn main() {
67
use std::sync::Mutex;

0 commit comments

Comments
 (0)