Skip to content

Commit 56ab392

Browse files
committed
Merge commit '4f3ab69ea0a0908260944443c739426cc384ae1a' into clippyup
2 parents 11a338a + 4f3ab69 commit 56ab392

File tree

97 files changed

+2555
-356
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+2555
-356
lines changed

src/tools/clippy/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -4203,6 +4203,7 @@ Released 2018-09-13
42034203
[`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const
42044204
[`float_equality_without_abs`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_equality_without_abs
42054205
[`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons
4206+
[`fn_null_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_null_check
42064207
[`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools
42074208
[`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast
42084209
[`fn_to_numeric_cast_any`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_any
@@ -4460,6 +4461,7 @@ Released 2018-09-13
44604461
[`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none
44614462
[`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite
44624463
[`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch
4464+
[`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false
44634465
[`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters
44644466
[`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma
44654467
[`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence
@@ -4545,6 +4547,7 @@ Released 2018-09-13
45454547
[`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match
45464548
[`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else
45474549
[`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count
4550+
[`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref
45484551
[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
45494552
[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
45504553
[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
@@ -4590,6 +4593,7 @@ Released 2018-09-13
45904593
[`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool
45914594
[`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_char
45924595
[`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float
4596+
[`transmute_null_to_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_null_to_fn
45934597
[`transmute_num_to_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_num_to_bytes
45944598
[`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr
45954599
[`transmute_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref

src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv
5454

5555
diag.span_suggestion(
5656
expr.span,
57-
&format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"),
57+
format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"),
5858
sugg,
5959
rustc_errors::Applicability::HasPlaceholders,
6060
);

src/tools/clippy/clippy_lints/src/declared_lints.rs

+4
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
161161
crate::float_literal::LOSSY_FLOAT_LITERAL_INFO,
162162
crate::floating_point_arithmetic::IMPRECISE_FLOPS_INFO,
163163
crate::floating_point_arithmetic::SUBOPTIMAL_FLOPS_INFO,
164+
crate::fn_null_check::FN_NULL_CHECK_INFO,
164165
crate::format::USELESS_FORMAT_INFO,
165166
crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO,
166167
crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO,
@@ -494,6 +495,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
494495
crate::pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE_INFO,
495496
crate::pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF_INFO,
496497
crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO,
498+
crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO,
497499
crate::precedence::PRECEDENCE_INFO,
498500
crate::ptr::CMP_NULL_INFO,
499501
crate::ptr::INVALID_NULL_PTR_USAGE_INFO,
@@ -535,6 +537,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
535537
crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO,
536538
crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO,
537539
crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO,
540+
crate::size_of_ref::SIZE_OF_REF_INFO,
538541
crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO,
539542
crate::std_instead_of_core::ALLOC_INSTEAD_OF_CORE_INFO,
540543
crate::std_instead_of_core::STD_INSTEAD_OF_ALLOC_INFO,
@@ -568,6 +571,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
568571
crate::transmute::TRANSMUTE_INT_TO_BOOL_INFO,
569572
crate::transmute::TRANSMUTE_INT_TO_CHAR_INFO,
570573
crate::transmute::TRANSMUTE_INT_TO_FLOAT_INFO,
574+
crate::transmute::TRANSMUTE_NULL_TO_FN_INFO,
571575
crate::transmute::TRANSMUTE_NUM_TO_BYTES_INFO,
572576
crate::transmute::TRANSMUTE_PTR_TO_PTR_INFO,
573577
crate::transmute::TRANSMUTE_PTR_TO_REF_INFO,

src/tools/clippy/clippy_lints/src/dereference.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1282,10 +1282,10 @@ fn referent_used_exactly_once<'tcx>(
12821282
possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir)));
12831283
}
12841284
let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1;
1285-
// If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
1286-
// that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
1287-
// itself. See the comment in that method for an explanation as to why.
1288-
possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location)
1285+
// If `place.local` were not included here, the `copyable_iterator::warn` test would fail. The
1286+
// reason is that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible
1287+
// borrower of itself. See the comment in that method for an explanation as to why.
1288+
possible_borrower.at_most_borrowers(cx, &[local, place.local], place.local, location)
12891289
&& used_exactly_once(mir, place.local).unwrap_or(false)
12901290
} else {
12911291
false

src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
324324
let maybe_neg_sugg = |expr, hir_id| {
325325
let sugg = Sugg::hir(cx, expr, "..");
326326
if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id {
327-
format!("-{sugg}")
327+
format!("-{}", sugg.maybe_par())
328328
} else {
329329
sugg.to_string()
330330
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
use clippy_utils::consts::{constant, Constant};
2+
use clippy_utils::diagnostics::span_lint_and_help;
3+
use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
4+
use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind};
5+
use rustc_lint::{LateContext, LateLintPass};
6+
use rustc_session::{declare_lint_pass, declare_tool_lint};
7+
use rustc_span::sym;
8+
9+
declare_clippy_lint! {
10+
/// ### What it does
11+
/// Checks for comparing a function pointer to null.
12+
///
13+
/// ### Why is this bad?
14+
/// Function pointers are assumed to not be null.
15+
///
16+
/// ### Example
17+
/// ```rust,ignore
18+
/// let fn_ptr: fn() = /* somehow obtained nullable function pointer */
19+
///
20+
/// if (fn_ptr as *const ()).is_null() { ... }
21+
/// ```
22+
/// Use instead:
23+
/// ```rust,ignore
24+
/// let fn_ptr: Option<fn()> = /* somehow obtained nullable function pointer */
25+
///
26+
/// if fn_ptr.is_none() { ... }
27+
/// ```
28+
#[clippy::version = "1.67.0"]
29+
pub FN_NULL_CHECK,
30+
correctness,
31+
"`fn()` type assumed to be nullable"
32+
}
33+
declare_lint_pass!(FnNullCheck => [FN_NULL_CHECK]);
34+
35+
fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
36+
span_lint_and_help(
37+
cx,
38+
FN_NULL_CHECK,
39+
expr.span,
40+
"function pointer assumed to be nullable, even though it isn't",
41+
None,
42+
"try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value",
43+
);
44+
}
45+
46+
fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
47+
if let ExprKind::Cast(cast_expr, cast_ty) = expr.kind
48+
&& let TyKind::Ptr(_) = cast_ty.kind
49+
{
50+
cx.typeck_results().expr_ty_adjusted(cast_expr).is_fn()
51+
} else {
52+
false
53+
}
54+
}
55+
56+
impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
57+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
58+
match expr.kind {
59+
// Catching:
60+
// (fn_ptr as *<const/mut> <ty>).is_null()
61+
ExprKind::MethodCall(method_name, receiver, _, _)
62+
if method_name.ident.as_str() == "is_null" && is_fn_ptr_cast(cx, receiver) =>
63+
{
64+
lint_expr(cx, expr);
65+
},
66+
67+
ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
68+
let to_check: &Expr<'_>;
69+
if is_fn_ptr_cast(cx, left) {
70+
to_check = right;
71+
} else if is_fn_ptr_cast(cx, right) {
72+
to_check = left;
73+
} else {
74+
return;
75+
}
76+
77+
match to_check.kind {
78+
// Catching:
79+
// (fn_ptr as *<const/mut> <ty>) == (0 as <ty>)
80+
ExprKind::Cast(cast_expr, _) if is_integer_literal(cast_expr, 0) => {
81+
lint_expr(cx, expr);
82+
},
83+
84+
// Catching:
85+
// (fn_ptr as *<const/mut> <ty>) == std::ptr::null()
86+
ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::ptr_null) => {
87+
lint_expr(cx, expr);
88+
},
89+
90+
// Catching:
91+
// (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
92+
_ if matches!(
93+
constant(cx, cx.typeck_results(), to_check),
94+
Some((Constant::RawPtr(0), _))
95+
) =>
96+
{
97+
lint_expr(cx, expr);
98+
},
99+
100+
_ => {},
101+
}
102+
},
103+
_ => {},
104+
}
105+
}
106+
}

src/tools/clippy/clippy_lints/src/format_args.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ fn check_format_in_format_args(
382382
call_site,
383383
&format!("`format!` in `{name}!` args"),
384384
|diag| {
385-
diag.help(&format!(
385+
diag.help(format!(
386386
"combine the `format!(..)` arguments with the outer `{name}!(..)` call"
387387
));
388388
diag.help("or consider changing `format!` to `format_args!`");

src/tools/clippy/clippy_lints/src/functions/mod.rs

+28-5
Original file line numberDiff line numberDiff line change
@@ -63,30 +63,53 @@ declare_clippy_lint! {
6363
/// arguments but are not marked `unsafe`.
6464
///
6565
/// ### Why is this bad?
66-
/// The function should probably be marked `unsafe`, since
67-
/// for an arbitrary raw pointer, there is no way of telling for sure if it is
68-
/// valid.
66+
/// The function should almost definitely be marked `unsafe`, since for an
67+
/// arbitrary raw pointer, there is no way of telling for sure if it is valid.
68+
///
69+
/// In general, this lint should **never be disabled** unless it is definitely a
70+
/// false positive (please submit an issue if so) since it breaks Rust's
71+
/// soundness guarantees, directly exposing API users to potentially dangerous
72+
/// program behavior. This is also true for internal APIs, as it is easy to leak
73+
/// unsoundness.
74+
///
75+
/// ### Context
76+
/// In Rust, an `unsafe {...}` block is used to indicate that the code in that
77+
/// section has been verified in some way that the compiler can not. For a
78+
/// function that accepts a raw pointer then accesses the pointer's data, this is
79+
/// generally impossible as the incoming pointer could point anywhere, valid or
80+
/// not. So, the signature should be marked `unsafe fn`: this indicates that the
81+
/// function's caller must provide some verification that the arguments it sends
82+
/// are valid (and then call the function within an `unsafe` block).
6983
///
7084
/// ### Known problems
7185
/// * It does not check functions recursively so if the pointer is passed to a
7286
/// private non-`unsafe` function which does the dereferencing, the lint won't
73-
/// trigger.
87+
/// trigger (false negative).
7488
/// * It only checks for arguments whose type are raw pointers, not raw pointers
7589
/// got from an argument in some other way (`fn foo(bar: &[*const u8])` or
76-
/// `some_argument.get_raw_ptr()`).
90+
/// `some_argument.get_raw_ptr()`) (false negative).
7791
///
7892
/// ### Example
7993
/// ```rust,ignore
8094
/// pub fn foo(x: *const u8) {
8195
/// println!("{}", unsafe { *x });
8296
/// }
97+
///
98+
/// // this call "looks" safe but will segfault or worse!
99+
/// // foo(invalid_ptr);
83100
/// ```
84101
///
85102
/// Use instead:
86103
/// ```rust,ignore
87104
/// pub unsafe fn foo(x: *const u8) {
88105
/// println!("{}", unsafe { *x });
89106
/// }
107+
///
108+
/// // this would cause a compiler error for calling without `unsafe`
109+
/// // foo(invalid_ptr);
110+
///
111+
/// // sound call if the caller knows the pointer is valid
112+
/// unsafe { foo(valid_ptr); }
90113
/// ```
91114
#[clippy::version = "pre 1.29.0"]
92115
pub NOT_UNSAFE_PTR_ARG_DEREF,

src/tools/clippy/clippy_lints/src/large_const_arrays.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ declare_clippy_lint! {
3434
}
3535

3636
pub struct LargeConstArrays {
37-
maximum_allowed_size: u64,
37+
maximum_allowed_size: u128,
3838
}
3939

4040
impl LargeConstArrays {
4141
#[must_use]
42-
pub fn new(maximum_allowed_size: u64) -> Self {
42+
pub fn new(maximum_allowed_size: u128) -> Self {
4343
Self { maximum_allowed_size }
4444
}
4545
}
@@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
5656
if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
5757
if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
5858
if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
59-
if self.maximum_allowed_size < element_count * element_size;
59+
if self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size);
6060

6161
then {
6262
let hi_pos = item.ident.span.lo() - BytePos::from_usize(1);

src/tools/clippy/clippy_lints/src/large_enum_variant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
111111
);
112112
diag.span_label(
113113
def.variants[variants_size[1].ind].span,
114-
&if variants_size[1].fields_size.is_empty() {
114+
if variants_size[1].fields_size.is_empty() {
115115
"the second-largest variant carries no data at all".to_owned()
116116
} else {
117117
format!(

src/tools/clippy/clippy_lints/src/large_stack_arrays.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ declare_clippy_lint! {
2424
}
2525

2626
pub struct LargeStackArrays {
27-
maximum_allowed_size: u64,
27+
maximum_allowed_size: u128,
2828
}
2929

3030
impl LargeStackArrays {
3131
#[must_use]
32-
pub fn new(maximum_allowed_size: u64) -> Self {
32+
pub fn new(maximum_allowed_size: u128) -> Self {
3333
Self { maximum_allowed_size }
3434
}
3535
}
@@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
4545
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
4646
&& !cx.tcx.hir().parent_iter(expr.hir_id)
4747
.any(|(_, node)| matches!(node, Node::Item(Item { kind: ItemKind::Static(..), .. })))
48-
&& self.maximum_allowed_size < element_count * element_size {
48+
&& self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size) {
4949
span_lint_and_help(
5050
cx,
5151
LARGE_STACK_ARRAYS,

src/tools/clippy/clippy_lints/src/len_zero.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ fn check_for_is_empty<'tcx>(
361361
db.span_note(span, "`is_empty` defined here");
362362
}
363363
if let Some(self_kind) = self_kind {
364-
db.note(&output.expected_sig(self_kind));
364+
db.note(output.expected_sig(self_kind));
365365
}
366366
});
367367
}

src/tools/clippy/clippy_lints/src/lib.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ mod explicit_write;
125125
mod fallible_impl_from;
126126
mod float_literal;
127127
mod floating_point_arithmetic;
128+
mod fn_null_check;
128129
mod format;
129130
mod format_args;
130131
mod format_impl;
@@ -234,6 +235,7 @@ mod partialeq_ne_impl;
234235
mod partialeq_to_none;
235236
mod pass_by_ref_or_value;
236237
mod pattern_type_mismatch;
238+
mod permissions_set_readonly_false;
237239
mod precedence;
238240
mod ptr;
239241
mod ptr_offset_with_cast;
@@ -263,6 +265,7 @@ mod shadow;
263265
mod single_char_lifetime_names;
264266
mod single_component_path_imports;
265267
mod size_of_in_element_count;
268+
mod size_of_ref;
266269
mod slow_vector_initialization;
267270
mod std_instead_of_core;
268271
mod strings;
@@ -334,7 +337,7 @@ pub fn read_conf(sess: &Session, path: &io::Result<Option<PathBuf>>) -> Conf {
334337
Ok(Some(path)) => path,
335338
Ok(None) => return Conf::default(),
336339
Err(error) => {
337-
sess.struct_err(&format!("error finding Clippy's configuration file: {error}"))
340+
sess.struct_err(format!("error finding Clippy's configuration file: {error}"))
338341
.emit();
339342
return Conf::default();
340343
},
@@ -902,6 +905,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
902905
store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow));
903906
store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv())));
904907
store.register_late_pass(|_| Box::new(semicolon_block::SemicolonBlock));
908+
store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck));
909+
store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
910+
store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
905911
// add lints here, do not remove this comment, it's used in `new_lint`
906912
}
907913

src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pub(super) fn check<'tcx>(
7777
applicability,
7878
);
7979

80-
diag.note(&format!(
80+
diag.note(format!(
8181
"`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`"
8282
));
8383
},

src/tools/clippy/clippy_lints/src/manual_async_fn.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
7676
let help = format!("make the function `async` and {ret_sugg}");
7777
diag.span_suggestion(
7878
header_span,
79-
&help,
79+
help,
8080
format!("async {}{ret_snip}", &header_snip[..ret_pos]),
8181
Applicability::MachineApplicable
8282
);

0 commit comments

Comments
 (0)