Skip to content

Commit 9200a9e

Browse files
Merge branch 'master' into 11710
2 parents df48422 + 406d953 commit 9200a9e

33 files changed

+631
-54
lines changed

CHANGELOG.md

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,70 @@ document.
66

77
## Unreleased / Beta / In Rust Nightly
88

9-
[1e8fdf49...master](https://github.com/rust-lang/rust-clippy/compare/1e8fdf49...master)
9+
[7671c283...master](https://github.com/rust-lang/rust-clippy/compare/7671c283...master)
10+
11+
## Rust 1.74
12+
13+
Current stable, released 2023-11-16
14+
15+
[View all 94 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-08-11T15%3A29%3A18Z..2023-09-25T08%3A48%3A22Z+base%3Amaster)
16+
17+
### New Lints
18+
19+
* [`redundant_as_str`]
20+
[#11526](https://github.com/rust-lang/rust-clippy/pull/11526)
21+
* [`needless_borrows_for_generic_args`]
22+
[#11511](https://github.com/rust-lang/rust-clippy/pull/11511)
23+
* [`path_ends_with_ext`]
24+
[#11483](https://github.com/rust-lang/rust-clippy/pull/11483)
25+
* [`unnecessary_map_on_constructor`]
26+
[#11413](https://github.com/rust-lang/rust-clippy/pull/11413)
27+
* [`missing_asserts_for_indexing`]
28+
[#10692](https://github.com/rust-lang/rust-clippy/pull/10692)
29+
* [`iter_out_of_bounds`]
30+
[#11396](https://github.com/rust-lang/rust-clippy/pull/11396)
31+
* [`implied_bounds_in_impls`]
32+
[#11362](https://github.com/rust-lang/rust-clippy/pull/11362)
33+
* [`reserve_after_initialization`]
34+
[#11373](https://github.com/rust-lang/rust-clippy/pull/11373)
35+
* [`should_panic_without_expect`]
36+
[#11204](https://github.com/rust-lang/rust-clippy/pull/11204)
37+
38+
### Moves and Deprecations
39+
40+
* Renamed `incorrect_clone_impl_on_copy_type` to [`non_canonical_clone_impl`]
41+
[#11358](https://github.com/rust-lang/rust-clippy/pull/11358)
42+
* Renamed `incorrect_partial_ord_impl_on_ord_type` to [`non_canonical_partial_ord_impl`]
43+
[#11358](https://github.com/rust-lang/rust-clippy/pull/11358)
44+
* Moved [`non_canonical_clone_impl`] to `suspicious` (Now warn-by-default)
45+
[#11358](https://github.com/rust-lang/rust-clippy/pull/11358)
46+
* Moved [`non_canonical_partial_ord_impl`] to `suspicious` (Now warn-by-default)
47+
[#11358](https://github.com/rust-lang/rust-clippy/pull/11358)
48+
* Moved [`needless_pass_by_ref_mut`] to `nursery` (Now allow-by-default)
49+
[#11596](https://github.com/rust-lang/rust-clippy/pull/11596)
50+
51+
### Enhancements
52+
53+
* [`undocumented_unsafe_blocks`]: The config values [`accept-comment-above-statement`] and
54+
[`accept-comment-above-attributes`] to `true` by default
55+
[#11170](https://github.com/rust-lang/rust-clippy/pull/11170)
56+
* [`explicit_iter_loop`]: Added [`enforce-iter-loop-reborrow`] to disable reborrow linting by default
57+
[#11418](https://github.com/rust-lang/rust-clippy/pull/11418)
58+
59+
### ICE Fixes
60+
61+
* [`enum_variant_names`]: No longer crashes if the threshold is 0 and the enum has no variants
62+
[#11552](https://github.com/rust-lang/rust-clippy/pull/11552)
63+
* [`cast_possible_truncation`]: No longer crashes on values larger than `u64::MAX`
64+
[#11517](https://github.com/rust-lang/rust-clippy/pull/11517)
65+
* [`tuple_array_conversions`]: No longer crashes if the array length is not usize
66+
[#11379](https://github.com/rust-lang/rust-clippy/pull/11379)
67+
* [`useless_conversion`]: No longer crashes, when the receiver is a non-fn item
68+
[#11070](https://github.com/rust-lang/rust-clippy/pull/11070)
1069

1170
## Rust 1.73
1271

13-
Current stable, released 2023-10-05
72+
Released 2023-10-05
1473

1574
[View all 103 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-07-02T12%3A24%3A40Z..2023-08-11T11%3A09%3A56Z+base%3Amaster)
1675

@@ -5124,6 +5183,7 @@ Released 2018-09-13
51245183
[`iter_on_empty_collections`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_empty_collections
51255184
[`iter_on_single_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_single_items
51265185
[`iter_out_of_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_out_of_bounds
5186+
[`iter_over_hash_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_over_hash_type
51275187
[`iter_overeager_cloned`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_overeager_cloned
51285188
[`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next
51295189
[`iter_skip_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_zero

clippy.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
11
avoid-breaking-exported-api = false
2+
3+
# use the various `span_lint_*` methods instead, which also add a link to the docs
4+
disallowed-methods = [
5+
"rustc_lint::context::LintContext::struct_span_lint",
6+
"rustc_middle::ty::context::TyCtxt::struct_span_lint_hir"
7+
]

clippy_lints/src/attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ declare_clippy_lint! {
371371
/// let _ = 1 / random();
372372
/// }
373373
/// ```
374-
#[clippy::version = "1.73.0"]
374+
#[clippy::version = "1.74.0"]
375375
pub SHOULD_PANIC_WITHOUT_EXPECT,
376376
pedantic,
377377
"ensures that all `should_panic` attributes specify its expected panic message"

clippy_lints/src/casts/cast_possible_wrap.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
use clippy_utils::diagnostics::span_lint_and_then;
12
use rustc_hir::Expr;
2-
use rustc_lint::{LateContext, LintContext};
3+
use rustc_lint::LateContext;
34
use rustc_middle::ty::Ty;
45

56
use super::{utils, CAST_POSSIBLE_WRAP};
@@ -78,13 +79,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
7879
),
7980
};
8081

81-
cx.struct_span_lint(CAST_POSSIBLE_WRAP, expr.span, message, |diag| {
82+
span_lint_and_then(cx, CAST_POSSIBLE_WRAP, expr.span, &message, |diag| {
8283
if let EmitState::LintOnPtrSize(16) = should_lint {
8384
diag
84-
.note("`usize` and `isize` may be as small as 16 bits on some platforms")
85-
.note("for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types")
86-
} else {
87-
diag
88-
}
85+
.note("`usize` and `isize` may be as small as 16 bits on some platforms")
86+
.note("for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types");
87+
};
8988
});
9089
}

clippy_lints/src/copies.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ declare_clippy_lint! {
117117
/// ```
118118
#[clippy::version = "pre 1.29.0"]
119119
pub IF_SAME_THEN_ELSE,
120-
correctness,
120+
style,
121121
"`if` with the same `then` and `else` blocks"
122122
}
123123

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
232232
crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO,
233233
crate::items_after_test_module::ITEMS_AFTER_TEST_MODULE_INFO,
234234
crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO,
235+
crate::iter_over_hash_type::ITER_OVER_HASH_TYPE_INFO,
235236
crate::iter_without_into_iter::INTO_ITER_WITHOUT_ITER_INFO,
236237
crate::iter_without_into_iter::ITER_WITHOUT_INTO_ITER_INFO,
237238
crate::large_const_arrays::LARGE_CONST_ARRAYS_INFO,

clippy_lints/src/functions/impl_trait_in_params.rs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,10 @@ use rustc_hir as hir;
55
use rustc_hir::intravisit::FnKind;
66
use rustc_hir::{Body, GenericParam, Generics, HirId, ImplItem, ImplItemKind, TraitItem, TraitItemKind};
77
use rustc_lint::LateContext;
8-
use rustc_span::symbol::Ident;
9-
use rustc_span::{BytePos, Span};
108

119
use super::IMPL_TRAIT_IN_PARAMS;
1210

13-
fn report(
14-
cx: &LateContext<'_>,
15-
param: &GenericParam<'_>,
16-
ident: &Ident,
17-
generics: &Generics<'_>,
18-
first_param_span: Span,
19-
) {
11+
fn report(cx: &LateContext<'_>, param: &GenericParam<'_>, generics: &Generics<'_>) {
2012
// No generics with nested generics, and no generics like FnMut(x)
2113
span_lint_and_then(
2214
cx,
@@ -35,12 +27,7 @@ fn report(
3527
);
3628
} else {
3729
diag.span_suggestion_with_style(
38-
Span::new(
39-
first_param_span.lo() - rustc_span::BytePos(1),
40-
ident.span.hi(),
41-
ident.span.ctxt(),
42-
ident.span.parent(),
43-
),
30+
generics.span,
4431
"add a type parameter",
4532
format!("<{{ /* Generic name */ }}: {}>", &param.name.ident().as_str()[5..]),
4633
rustc_errors::Applicability::HasPlaceholders,
@@ -52,13 +39,13 @@ fn report(
5239
}
5340

5441
pub(super) fn check_fn<'tcx>(cx: &LateContext<'_>, kind: &'tcx FnKind<'_>, body: &'tcx Body<'_>, hir_id: HirId) {
55-
if let FnKind::ItemFn(ident, generics, _) = kind
42+
if let FnKind::ItemFn(_, generics, _) = kind
5643
&& cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public()
5744
&& !is_in_test_function(cx.tcx, hir_id)
5845
{
5946
for param in generics.params {
6047
if param.is_impl_trait() {
61-
report(cx, param, ident, generics, body.params[0].span);
48+
report(cx, param, generics);
6249
};
6350
}
6451
}
@@ -76,7 +63,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
7663
{
7764
for param in impl_item.generics.params {
7865
if param.is_impl_trait() {
79-
report(cx, param, &impl_item.ident, impl_item.generics, body.params[0].span);
66+
report(cx, param, impl_item.generics);
8067
}
8168
}
8269
}
@@ -92,8 +79,7 @@ pub(super) fn check_trait_item(cx: &LateContext<'_>, trait_item: &TraitItem<'_>,
9279
{
9380
for param in trait_item.generics.params {
9481
if param.is_impl_trait() {
95-
let sp = trait_item.ident.span.with_hi(trait_item.ident.span.hi() + BytePos(1));
96-
report(cx, param, &trait_item.ident, trait_item.generics, sp.shrink_to_hi());
82+
report(cx, param, trait_item.generics);
9783
}
9884
}
9985
}

clippy_lints/src/implied_bounds_in_impls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ declare_clippy_lint! {
4343
/// Box::new(123)
4444
/// }
4545
/// ```
46-
#[clippy::version = "1.73.0"]
46+
#[clippy::version = "1.74.0"]
4747
pub IMPLIED_BOUNDS_IN_IMPLS,
4848
nursery,
4949
"specifying bounds that are implied by other bounds in `impl Trait` type"
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use clippy_utils::diagnostics::span_lint;
2+
use clippy_utils::higher::ForLoop;
3+
use clippy_utils::match_any_def_paths;
4+
use clippy_utils::paths::{
5+
HASHMAP_DRAIN, HASHMAP_ITER, HASHMAP_ITER_MUT, HASHMAP_KEYS, HASHMAP_VALUES, HASHMAP_VALUES_MUT, HASHSET_DRAIN,
6+
HASHSET_ITER_TY,
7+
};
8+
use clippy_utils::ty::is_type_diagnostic_item;
9+
use rustc_lint::{LateContext, LateLintPass};
10+
use rustc_session::{declare_lint_pass, declare_tool_lint};
11+
use rustc_span::sym;
12+
13+
declare_clippy_lint! {
14+
/// ### What it does
15+
/// This is a restriction lint which prevents the use of hash types (i.e., `HashSet` and `HashMap`) in for loops.
16+
///
17+
/// ### Why is this bad?
18+
/// Because hash types are unordered, when iterated through such as in a for loop, the values are returned in
19+
/// an undefined order. As a result, on redundant systems this may cause inconsistencies and anomalies.
20+
/// In addition, the unknown order of the elements may reduce readability or introduce other undesired
21+
/// side effects.
22+
///
23+
/// ### Example
24+
/// ```no_run
25+
/// let my_map = std::collections::HashMap::<i32, String>::new();
26+
/// for (key, value) in my_map { /* ... */ }
27+
/// ```
28+
/// Use instead:
29+
/// ```no_run
30+
/// let my_map = std::collections::HashMap::<i32, String>::new();
31+
/// let mut keys = my_map.keys().clone().collect::<Vec<_>>();
32+
/// keys.sort();
33+
/// for key in keys {
34+
/// let value = &my_map[key];
35+
/// }
36+
/// ```
37+
#[clippy::version = "1.75.0"]
38+
pub ITER_OVER_HASH_TYPE,
39+
restriction,
40+
"iterating over unordered hash-based types (`HashMap` and `HashSet`)"
41+
}
42+
43+
declare_lint_pass!(IterOverHashType => [ITER_OVER_HASH_TYPE]);
44+
45+
impl LateLintPass<'_> for IterOverHashType {
46+
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>) {
47+
if let Some(for_loop) = ForLoop::hir(expr)
48+
&& !for_loop.body.span.from_expansion()
49+
&& let ty = cx.typeck_results().expr_ty(for_loop.arg).peel_refs()
50+
&& let Some(adt) = ty.ty_adt_def()
51+
&& let did = adt.did()
52+
&& (match_any_def_paths(
53+
cx,
54+
did,
55+
&[
56+
&HASHMAP_KEYS,
57+
&HASHMAP_VALUES,
58+
&HASHMAP_VALUES_MUT,
59+
&HASHMAP_ITER,
60+
&HASHMAP_ITER_MUT,
61+
&HASHMAP_DRAIN,
62+
&HASHSET_ITER_TY,
63+
&HASHSET_DRAIN,
64+
],
65+
)
66+
.is_some()
67+
|| is_type_diagnostic_item(cx, ty, sym::HashMap)
68+
|| is_type_diagnostic_item(cx, ty, sym::HashSet))
69+
{
70+
span_lint(
71+
cx,
72+
ITER_OVER_HASH_TYPE,
73+
expr.span,
74+
"iteration over unordered hash-based type",
75+
);
76+
};
77+
}
78+
}

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ mod item_name_repetitions;
165165
mod items_after_statements;
166166
mod items_after_test_module;
167167
mod iter_not_returning_iterator;
168+
mod iter_over_hash_type;
168169
mod iter_without_into_iter;
169170
mod large_const_arrays;
170171
mod large_enum_variant;
@@ -1066,6 +1067,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
10661067
store.register_late_pass(move |_| Box::new(manual_hash_one::ManualHashOne::new(msrv())));
10671068
store.register_late_pass(|_| Box::new(iter_without_into_iter::IterWithoutIntoIter));
10681069
store.register_late_pass(|_| Box::new(hash_borrow_str_semantics::HashBorrowStrSemantics));
1070+
store.register_late_pass(|_| Box::new(iter_over_hash_type::IterOverHashType));
10691071
// add lints here, do not remove this comment, it's used in `new_lint`
10701072
}
10711073

clippy_lints/src/loops/manual_memcpy.rs

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,9 @@ fn build_manual_memcpy_suggestion<'tcx>(
178178
let dst_base_str = snippet(cx, dst.base.span, "???");
179179
let src_base_str = snippet(cx, src.base.span, "???");
180180

181-
let dst = if dst_offset == sugg::EMPTY && dst_limit == sugg::EMPTY {
181+
let dst = if (dst_offset == sugg::EMPTY && dst_limit == sugg::EMPTY)
182+
|| is_array_length_equal_to_range(cx, start, end, dst.base)
183+
{
182184
dst_base_str
183185
} else {
184186
format!("{dst_base_str}[{}..{}]", dst_offset.maybe_par(), dst_limit.maybe_par()).into()
@@ -190,11 +192,13 @@ fn build_manual_memcpy_suggestion<'tcx>(
190192
"clone_from_slice"
191193
};
192194

193-
format!(
194-
"{dst}.{method_str}(&{src_base_str}[{}..{}]);",
195-
src_offset.maybe_par(),
196-
src_limit.maybe_par()
197-
)
195+
let src = if is_array_length_equal_to_range(cx, start, end, src.base) {
196+
src_base_str
197+
} else {
198+
format!("{src_base_str}[{}..{}]", src_offset.maybe_par(), src_limit.maybe_par()).into()
199+
};
200+
201+
format!("{dst}.{method_str}(&{src});")
198202
}
199203

200204
/// a wrapper of `Sugg`. Besides what `Sugg` do, this removes unnecessary `0`;
@@ -452,3 +456,34 @@ fn get_loop_counters<'a, 'tcx>(
452456
.into()
453457
})
454458
}
459+
460+
fn is_array_length_equal_to_range(cx: &LateContext<'_>, start: &Expr<'_>, end: &Expr<'_>, arr: &Expr<'_>) -> bool {
461+
fn extract_lit_value(expr: &Expr<'_>) -> Option<u128> {
462+
if let ExprKind::Lit(lit) = expr.kind
463+
&& let ast::LitKind::Int(value, _) = lit.node
464+
{
465+
Some(value)
466+
} else {
467+
None
468+
}
469+
}
470+
471+
let arr_ty = cx.typeck_results().expr_ty(arr).peel_refs();
472+
473+
if let ty::Array(_, s) = arr_ty.kind() {
474+
let size: u128 = if let Some(size) = s.try_eval_target_usize(cx.tcx, cx.param_env) {
475+
size.into()
476+
} else {
477+
return false;
478+
};
479+
480+
let range = match (extract_lit_value(start), extract_lit_value(end)) {
481+
(Some(start_value), Some(end_value)) => end_value - start_value,
482+
_ => return false,
483+
};
484+
485+
size == range
486+
} else {
487+
false
488+
}
489+
}

clippy_lints/src/missing_asserts_for_indexing.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ declare_clippy_lint! {
5757
/// v[0] + v[1] + v[2] + v[3]
5858
/// }
5959
/// ```
60-
#[clippy::version = "1.70.0"]
60+
#[clippy::version = "1.74.0"]
6161
pub MISSING_ASSERTS_FOR_INDEXING,
6262
restriction,
6363
"indexing into a slice multiple times without an `assert`"

0 commit comments

Comments
 (0)