Skip to content

Commit

Permalink
Merge branch 'rust-lang:master' into manual_unwrap_or_if_let
Browse files Browse the repository at this point in the history
  • Loading branch information
lochetti authored Jun 17, 2024
2 parents 70ca9a1 + 0625183 commit a95824d
Show file tree
Hide file tree
Showing 142 changed files with 3,065 additions and 1,118 deletions.
115 changes: 115 additions & 0 deletions .github/workflows/lintcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: Lintcheck

on: pull_request

env:
RUST_BACKTRACE: 1
CARGO_INCREMENTAL: 0

concurrency:
# For a given workflow, if we push to the same PR, cancel all previous builds on that PR.
group: "${{ github.workflow }}-${{ github.event.pull_request.number}}"
cancel-in-progress: true

jobs:
# Generates `lintcheck-logs/base.json` and stores it in a cache
base:
runs-on: ubuntu-latest

outputs:
key: ${{ steps.key.outputs.key }}

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2

# HEAD is the generated merge commit `refs/pull/N/merge` between the PR and `master`, `HEAD^`
# being the commit from `master` that is the base of the merge
- name: Checkout base
run: git checkout HEAD^

# Use the lintcheck from the PR to generate the JSON in case the PR modifies lintcheck in some
# way
- name: Checkout current lintcheck
run: |
rm -rf lintcheck
git checkout ${{ github.sha }} -- lintcheck
- name: Create cache key
id: key
run: echo "key=lintcheck-base-${{ hashfiles('lintcheck/**') }}-$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"

- name: Cache results
id: cache
uses: actions/cache@v4
with:
path: lintcheck-logs/base.json
key: ${{ steps.key.outputs.key }}

- name: Run lintcheck
if: steps.cache.outputs.cache-hit != 'true'
run: cargo lintcheck --format json

- name: Rename JSON file
if: steps.cache.outputs.cache-hit != 'true'
run: mv lintcheck-logs/lintcheck_crates_logs.json lintcheck-logs/base.json

# Generates `lintcheck-logs/head.json` and stores it in a cache
head:
runs-on: ubuntu-latest

outputs:
key: ${{ steps.key.outputs.key }}

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Create cache key
id: key
run: echo "key=lintcheck-head-${{ github.sha }}" >> "$GITHUB_OUTPUT"

- name: Cache results
id: cache
uses: actions/cache@v4
with:
path: lintcheck-logs/head.json
key: ${{ steps.key.outputs.key }}

- name: Run lintcheck
if: steps.cache.outputs.cache-hit != 'true'
run: cargo lintcheck --format json

- name: Rename JSON file
if: steps.cache.outputs.cache-hit != 'true'
run: mv lintcheck-logs/lintcheck_crates_logs.json lintcheck-logs/head.json

# Retrieves `lintcheck-logs/base.json` and `lintcheck-logs/head.json` from the cache and prints
# the diff to the GH actions step summary
diff:
runs-on: ubuntu-latest

needs: [base, head]

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Restore base JSON
uses: actions/cache/restore@v4
with:
key: ${{ needs.base.outputs.key }}
path: lintcheck-logs/base.json
fail-on-cache-miss: true

- name: Restore head JSON
uses: actions/cache/restore@v4
with:
key: ${{ needs.head.outputs.key }}
path: lintcheck-logs/head.json
fail-on-cache-miss: true

- name: Diff results
run: cargo lintcheck diff lintcheck-logs/base.json lintcheck-logs/head.json >> $GITHUB_STEP_SUMMARY
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5362,6 +5362,7 @@ Released 2018-09-13
[`extra_unused_type_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_type_parameters
[`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from
[`field_reassign_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default
[`field_scoped_visibility_modifiers`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_scoped_visibility_modifiers
[`filetype_is_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#filetype_is_file
[`filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_map
[`filter_map_bool_then`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_bool_then
Expand Down Expand Up @@ -5520,6 +5521,7 @@ Released 2018-09-13
[`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map
[`manual_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten
[`manual_hash_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one
[`manual_inspect`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_inspect
[`manual_instant_elapsed`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_instant_elapsed
[`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check
[`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite
Expand All @@ -5532,6 +5534,7 @@ Released 2018-09-13
[`manual_next_back`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_next_back
[`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
[`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
[`manual_pattern_char_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison
[`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
[`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_patterns
[`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "clippy"
version = "0.1.80"
version = "0.1.81"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
Expand Down
1 change: 1 addition & 0 deletions book/src/lint_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check)
* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive)
* [`manual_pattern_char_comparison`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison)
* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains)
* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid)
* [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain)
Expand Down
2 changes: 1 addition & 1 deletion book/src/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ You can configure lint levels on the command line by adding
cargo clippy -- -Aclippy::style -Wclippy::double_neg -Dclippy::perf
```

For [CI] all warnings can be elevated to errors which will inturn fail
For [CI] all warnings can be elevated to errors which will in turn fail
the build and cause Clippy to exit with a code other than `0`.

```
Expand Down
2 changes: 1 addition & 1 deletion clippy_config/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "clippy_config"
version = "0.1.80"
version = "0.1.81"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
2 changes: 1 addition & 1 deletion clippy_config/src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ define_Conf! {
///
/// Suppress lints whenever the suggested change would cause breakage for other crates.
(avoid_breaking_exported_api: bool = true),
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS.
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS, MANUAL_PATTERN_CHAR_COMPARISON.
///
/// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
#[default_text = ""]
Expand Down
2 changes: 1 addition & 1 deletion clippy_config/src/msrvs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ macro_rules! msrv_aliases {
// names may refer to stabilized feature flags or library items
msrv_aliases! {
1,77,0 { C_STR_LITERALS }
1,76,0 { PTR_FROM_REF }
1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN }
1,68,0 { PATH_MAIN_SEPARATOR_STR }
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "clippy_lints"
version = "0.1.80"
version = "0.1.81"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
Expand Down
13 changes: 6 additions & 7 deletions clippy_lints/src/allow_attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,19 @@ use rustc_session::declare_lint_pass;
declare_clippy_lint! {
/// ### What it does
/// Checks for usage of the `#[allow]` attribute and suggests replacing it with
/// the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html))
/// `#[expect]`. (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html))
///
/// The expect attribute is still unstable and requires the `lint_reasons`
/// The expect attribute is still unstable and requires the `lint_reasons` feature
/// on nightly. It can be enabled by adding `#![feature(lint_reasons)]` to
/// the crate root.
///
/// This lint only warns outer attributes (`#[allow]`), as inner attributes
/// This lint only warns on outer attributes (`#[allow]`), as inner attributes
/// (`#![allow]`) are usually used to enable or disable lints on a global scale.
///
/// ### Why restrict this?
/// `#[allow]` attributes can linger after their reason for existence is gone.
/// `#[expect]` attributes suppress the lint emission, but emit a warning if
/// the expectation is unfulfilled. This can be useful to be notified when the
/// lint is no longer triggered, which may indicate the attribute can be removed.
/// The `#[allow]` attribute does not warn when the expected lint is no longer triggered,
/// whereas `#[expect]` calls attention to this fact. This can be a useful reminder to
/// remove attributes that are no longer needed.
///
/// ### Example
/// ```rust,ignore
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/arc_with_non_send_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ declare_clippy_lint! {
/// `Arc<T>` is a thread-safe `Rc<T>` and guarantees that updates to the reference counter
/// use atomic operations. To send an `Arc<T>` across thread boundaries and
/// share ownership between multiple threads, `T` must be [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#thread-safety),
/// so either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc`
/// so either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc`.
///
/// ### Example
/// ```no_run
Expand Down
78 changes: 77 additions & 1 deletion clippy_lints/src/assigning_clones.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::HirNode;
use clippy_utils::mir::{enclosing_mir, PossibleBorrowerMap};
use clippy_utils::sugg::Sugg;
use clippy_utils::{is_trait_method, local_is_initialized, path_to_local};
use rustc_errors::Applicability;
use rustc_hir::{self as hir, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir;
use rustc_middle::ty::{self, Instance, Mutability};
use rustc_session::impl_lint_pass;
use rustc_span::def_id::DefId;
use rustc_span::symbol::sym;
use rustc_span::{ExpnKind, SyntaxContext};
use rustc_span::{ExpnKind, Span, SyntaxContext};

declare_clippy_lint! {
/// ### What it does
Expand Down Expand Up @@ -144,6 +146,7 @@ fn extract_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<
};

Some(CallCandidate {
span: expr.span,
target,
kind,
method_def_id: resolved_method.def_id(),
Expand Down Expand Up @@ -215,13 +218,85 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
return false;
};

if clone_source_borrows_from_dest(cx, lhs, call.span) {
return false;
}

// Now take a look if the impl block defines an implementation for the method that we're interested
// in. If not, then we're using a default implementation, which is not interesting, so we will
// not suggest the lint.
let implemented_fns = cx.tcx.impl_item_implementor_ids(impl_block);
implemented_fns.contains_key(&provided_fn.def_id)
}

/// Checks if the data being cloned borrows from the place that is being assigned to:
///
/// ```
/// let mut s = String::new();
/// let s2 = &s;
/// s = s2.to_owned();
/// ```
///
/// This cannot be written `s2.clone_into(&mut s)` because it has conflicting borrows.
fn clone_source_borrows_from_dest(cx: &LateContext<'_>, lhs: &Expr<'_>, call_span: Span) -> bool {
/// If this basic block only exists to drop a local as part of an assignment, returns its
/// successor. Otherwise returns the basic block that was passed in.
fn skip_drop_block(mir: &mir::Body<'_>, bb: mir::BasicBlock) -> mir::BasicBlock {
if let mir::TerminatorKind::Drop { target, .. } = mir.basic_blocks[bb].terminator().kind {
target
} else {
bb
}
}

let Some(mir) = enclosing_mir(cx.tcx, lhs.hir_id) else {
return false;
};
let PossibleBorrowerMap { map: borrow_map, .. } = PossibleBorrowerMap::new(cx, mir);

// The operation `dest = src.to_owned()` in MIR is split up across 3 blocks *if* the type has `Drop`
// code. For types that don't, the second basic block is simply skipped.
// For the doc example above that would be roughly:
//
// bb0:
// s2 = &s
// s_temp = ToOwned::to_owned(move s2) -> bb1
//
// bb1:
// drop(s) -> bb2 // drop the old string
//
// bb2:
// s = s_temp
for bb in mir.basic_blocks.iter() {
let terminator = bb.terminator();

// Look for the to_owned/clone call.
if terminator.source_info.span != call_span {
continue;
}

if let mir::TerminatorKind::Call { ref args, target: Some(assign_bb), .. } = terminator.kind
&& let [source] = &**args
&& let mir::Operand::Move(source) = &source.node
&& let assign_bb = skip_drop_block(mir, assign_bb)
// Skip any storage statements as they are just noise
&& let Some(assignment) = mir.basic_blocks[assign_bb].statements
.iter()
.find(|stmt| {
!matches!(stmt.kind, mir::StatementKind::StorageDead(_) | mir::StatementKind::StorageLive(_))
})
&& let mir::StatementKind::Assign(box (borrowed, _)) = &assignment.kind
&& let Some(borrowers) = borrow_map.get(&borrowed.local)
&& borrowers.contains(source.local)
{
return true;
}

return false;
}
false
}

fn suggest<'tcx>(
cx: &LateContext<'tcx>,
ctxt: SyntaxContext,
Expand Down Expand Up @@ -255,6 +330,7 @@ enum TargetTrait {

#[derive(Debug)]
struct CallCandidate<'tcx> {
span: Span,
target: TargetTrait,
kind: CallKind<'tcx>,
// DefId of the called method from an impl block that implements the target trait
Expand Down
11 changes: 6 additions & 5 deletions clippy_lints/src/attrs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,14 @@ declare_clippy_lint! {

declare_clippy_lint! {
/// ### What it does
/// Checks for attributes that allow lints without a reason.
///
/// (This requires the `lint_reasons` feature)
/// Checks for attributes that allow lints without specifying the reason
/// they should be allowed. (This requires the `lint_reasons` feature.)
///
/// ### Why restrict this?
/// Justifying each `allow` helps readers understand the reasoning,
/// and may allow removing `allow` attributes if their purpose is obsolete.
/// There should always be a specific reason to allow a lint. This reason
/// should be documented using the `reason` parameter, so that readers can
/// understand why the `allow` is required, or remove it if it's no
/// longer needed.
///
/// ### Example
/// ```no_run
Expand Down
Loading

0 comments on commit a95824d

Please sign in to comment.