mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 15:11:30 +00:00
Merge branch 'rust-lang:master' into clear-with-drain
This commit is contained in:
commit
1d168b31c3
67 changed files with 715 additions and 321 deletions
|
@ -11,3 +11,6 @@ target-dir = "target"
|
||||||
|
|
||||||
[unstable]
|
[unstable]
|
||||||
binary-dep-depinfo = true
|
binary-dep-depinfo = true
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
split-debuginfo = "unpacked"
|
||||||
|
|
2
.github/workflows/clippy_bors.yml
vendored
2
.github/workflows/clippy_bors.yml
vendored
|
@ -180,6 +180,8 @@ jobs:
|
||||||
|
|
||||||
# Run
|
# Run
|
||||||
- name: Build Integration Test
|
- name: Build Integration Test
|
||||||
|
env:
|
||||||
|
CARGO_PROFILE_DEV_SPLIT_DEBUGINFO: off
|
||||||
run: cargo test --test integration --features integration --no-run
|
run: cargo test --test integration --features integration --no-run
|
||||||
|
|
||||||
# Upload
|
# Upload
|
||||||
|
|
|
@ -4988,6 +4988,7 @@ Released 2018-09-13
|
||||||
[`unnecessary_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc
|
[`unnecessary_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc
|
||||||
[`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_self_imports
|
[`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_self_imports
|
||||||
[`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by
|
[`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by
|
||||||
|
[`unnecessary_struct_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_struct_initialization
|
||||||
[`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
|
[`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
|
||||||
[`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
|
[`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
|
||||||
[`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps
|
[`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// REUSE-IgnoreStart
|
||||||
|
|
||||||
Copyright 2014-2022 The Rust Project Developers
|
Copyright 2014-2022 The Rust Project Developers
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
@ -5,3 +7,5 @@ http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
option. All files in the project carrying such notice may not be
|
option. All files in the project carrying such notice may not be
|
||||||
copied, modified, or distributed except according to those terms.
|
copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
// REUSE-IgnoreEnd
|
||||||
|
|
|
@ -275,6 +275,8 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
<!-- REUSE-IgnoreStart -->
|
||||||
|
|
||||||
Copyright 2014-2022 The Rust Project Developers
|
Copyright 2014-2022 The Rust Project Developers
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
@ -282,3 +284,5 @@ Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
<LICENSE-MIT or [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)>, at your
|
<LICENSE-MIT or [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)>, at your
|
||||||
option. Files in the project may not be
|
option. Files in the project may not be
|
||||||
copied, modified, or distributed except according to those terms.
|
copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
<!-- REUSE-IgnoreEnd -->
|
||||||
|
|
|
@ -18,6 +18,7 @@ because that's clearly a non-descriptive name.
|
||||||
- [Cargo lints](#cargo-lints)
|
- [Cargo lints](#cargo-lints)
|
||||||
- [Rustfix tests](#rustfix-tests)
|
- [Rustfix tests](#rustfix-tests)
|
||||||
- [Testing manually](#testing-manually)
|
- [Testing manually](#testing-manually)
|
||||||
|
- [Running directly](#running-directly)
|
||||||
- [Lint declaration](#lint-declaration)
|
- [Lint declaration](#lint-declaration)
|
||||||
- [Lint registration](#lint-registration)
|
- [Lint registration](#lint-registration)
|
||||||
- [Lint passes](#lint-passes)
|
- [Lint passes](#lint-passes)
|
||||||
|
@ -186,6 +187,15 @@ cargo dev lint input.rs
|
||||||
from the working copy root. With tests in place, let's have a look at
|
from the working copy root. With tests in place, let's have a look at
|
||||||
implementing our lint now.
|
implementing our lint now.
|
||||||
|
|
||||||
|
## Running directly
|
||||||
|
|
||||||
|
While it's easier to just use `cargo dev lint`, it might be desirable to get
|
||||||
|
`target/release/cargo-clippy` and `target/release/clippy-driver` to work as well in some cases.
|
||||||
|
By default, they don't work because clippy dynamically links rustc. To help them find rustc,
|
||||||
|
add the path printed by`rustc --print target-libdir` (ran inside this workspace so that the rustc version matches)
|
||||||
|
to your library search path.
|
||||||
|
On linux, this can be done by setting the `LD_LIBRARY_PATH` environment variable to that path.
|
||||||
|
|
||||||
## Lint declaration
|
## Lint declaration
|
||||||
|
|
||||||
Let's start by opening the new file created in the `clippy_lints` crate at
|
Let's start by opening the new file created in the `clippy_lints` crate at
|
||||||
|
|
|
@ -495,18 +495,19 @@ struct NotSimplificationVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
|
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
|
||||||
if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind {
|
if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind &&
|
||||||
if let Some(suggestion) = simplify_not(self.cx, inner) {
|
!inner.span.from_expansion() &&
|
||||||
span_lint_and_sugg(
|
let Some(suggestion) = simplify_not(self.cx, inner)
|
||||||
self.cx,
|
{
|
||||||
NONMINIMAL_BOOL,
|
span_lint_and_sugg(
|
||||||
expr.span,
|
self.cx,
|
||||||
"this boolean expression can be simplified",
|
NONMINIMAL_BOOL,
|
||||||
"try",
|
expr.span,
|
||||||
suggestion,
|
"this boolean expression can be simplified",
|
||||||
Applicability::MachineApplicable,
|
"try",
|
||||||
);
|
suggestion,
|
||||||
}
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
|
|
|
@ -2,8 +2,9 @@ use clippy_utils::consts::{constant, Constant};
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||||
use clippy_utils::expr_or_init;
|
use clippy_utils::expr_or_init;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
|
use clippy_utils::sugg::Sugg;
|
||||||
use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
|
use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
|
||||||
use rustc_errors::{Applicability, SuggestionStyle};
|
use rustc_errors::{Applicability, Diagnostic, SuggestionStyle};
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
|
@ -163,19 +164,34 @@ pub(super) fn check(
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let name_of_cast_from = snippet(cx, cast_expr.span, "..");
|
|
||||||
let cast_to_snip = snippet(cx, cast_to_span, "..");
|
|
||||||
let suggestion = format!("{cast_to_snip}::try_from({name_of_cast_from})");
|
|
||||||
|
|
||||||
span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| {
|
span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| {
|
||||||
diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...");
|
diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...");
|
||||||
diag.span_suggestion_with_style(
|
if !cast_from.is_floating_point() {
|
||||||
expr.span,
|
offer_suggestion(cx, expr, cast_expr, cast_to_span, diag);
|
||||||
"... or use `try_from` and handle the error accordingly",
|
}
|
||||||
suggestion,
|
|
||||||
Applicability::Unspecified,
|
|
||||||
// always show the suggestion in a separate line
|
|
||||||
SuggestionStyle::ShowAlways,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn offer_suggestion(
|
||||||
|
cx: &LateContext<'_>,
|
||||||
|
expr: &Expr<'_>,
|
||||||
|
cast_expr: &Expr<'_>,
|
||||||
|
cast_to_span: Span,
|
||||||
|
diag: &mut Diagnostic,
|
||||||
|
) {
|
||||||
|
let cast_to_snip = snippet(cx, cast_to_span, "..");
|
||||||
|
let suggestion = if cast_to_snip == "_" {
|
||||||
|
format!("{}.try_into()", Sugg::hir(cx, cast_expr, "..").maybe_par())
|
||||||
|
} else {
|
||||||
|
format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, ".."))
|
||||||
|
};
|
||||||
|
|
||||||
|
diag.span_suggestion_with_style(
|
||||||
|
expr.span,
|
||||||
|
"... or use `try_from` and handle the error accordingly",
|
||||||
|
suggestion,
|
||||||
|
Applicability::Unspecified,
|
||||||
|
// always show the suggestion in a separate line
|
||||||
|
SuggestionStyle::ShowAlways,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity {
|
||||||
span: Span,
|
span: Span,
|
||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
) {
|
) {
|
||||||
if !cx.tcx.has_attr(def_id.to_def_id(), sym::test) {
|
if !cx.tcx.has_attr(def_id, sym::test) {
|
||||||
let expr = if is_async_fn(kind) {
|
let expr = if is_async_fn(kind) {
|
||||||
match get_async_fn_body(cx.tcx, body) {
|
match get_async_fn_body(cx.tcx, body) {
|
||||||
Some(b) => b,
|
Some(b) => b,
|
||||||
|
|
|
@ -619,6 +619,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
||||||
crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO,
|
crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO,
|
||||||
crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO,
|
crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO,
|
||||||
crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO,
|
crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO,
|
||||||
|
crate::unnecessary_struct_initialization::UNNECESSARY_STRUCT_INITIALIZATION_INFO,
|
||||||
crate::unnecessary_wraps::UNNECESSARY_WRAPS_INFO,
|
crate::unnecessary_wraps::UNNECESSARY_WRAPS_INFO,
|
||||||
crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO,
|
crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO,
|
||||||
crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO,
|
crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO,
|
||||||
|
|
|
@ -181,7 +181,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
|
||||||
self_ty,
|
self_ty,
|
||||||
..
|
..
|
||||||
}) = item.kind;
|
}) = item.kind;
|
||||||
if !cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
|
if !cx.tcx.has_attr(item.owner_id, sym::automatically_derived);
|
||||||
if !item.span.from_expansion();
|
if !item.span.from_expansion();
|
||||||
if let Some(def_id) = trait_ref.trait_def_id();
|
if let Some(def_id) = trait_ref.trait_def_id();
|
||||||
if cx.tcx.is_diagnostic_item(sym::Default, def_id);
|
if cx.tcx.is_diagnostic_item(sym::Default, def_id);
|
||||||
|
|
|
@ -212,7 +212,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
|
||||||
}) = item.kind
|
}) = item.kind
|
||||||
{
|
{
|
||||||
let ty = cx.tcx.type_of(item.owner_id).subst_identity();
|
let ty = cx.tcx.type_of(item.owner_id).subst_identity();
|
||||||
let is_automatically_derived = cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
|
let is_automatically_derived = cx.tcx.has_attr(item.owner_id, sym::automatically_derived);
|
||||||
|
|
||||||
check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
|
check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
|
||||||
check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived);
|
check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived);
|
||||||
|
|
|
@ -32,7 +32,7 @@ declare_clippy_lint! {
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// // Assuming that `clippy.toml` contains the following line:
|
/// // Assuming that `clippy.toml` contains the following line:
|
||||||
/// // allowed-locales = ["Latin", "Cyrillic"]
|
/// // allowed-scripts = ["Latin", "Cyrillic"]
|
||||||
/// let counter = 10; // OK, latin is allowed.
|
/// let counter = 10; // OK, latin is allowed.
|
||||||
/// let счётчик = 10; // OK, cyrillic is allowed.
|
/// let счётчик = 10; // OK, cyrillic is allowed.
|
||||||
/// let zähler = 10; // OK, it's still latin.
|
/// let zähler = 10; // OK, it's still latin.
|
||||||
|
|
|
@ -22,13 +22,13 @@ use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
|
||||||
|
|
||||||
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
|
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
|
||||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||||
let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
|
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
|
||||||
if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind {
|
if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind {
|
||||||
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
||||||
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
|
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
|
||||||
if let Some(attr) = attr {
|
if let Some(attr) = attr {
|
||||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
|
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
|
||||||
} else if is_public && !is_proc_macro(cx.sess(), attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
|
} else if is_public && !is_proc_macro(attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
|
||||||
check_must_use_candidate(
|
check_must_use_candidate(
|
||||||
cx,
|
cx,
|
||||||
sig.decl,
|
sig.decl,
|
||||||
|
@ -47,13 +47,10 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
|
||||||
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
||||||
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
|
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
|
||||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||||
let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
|
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
|
||||||
if let Some(attr) = attr {
|
if let Some(attr) = attr {
|
||||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
|
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
|
||||||
} else if is_public
|
} else if is_public && !is_proc_macro(attrs) && trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
|
||||||
&& !is_proc_macro(cx.sess(), attrs)
|
|
||||||
&& trait_ref_of_method(cx, item.owner_id.def_id).is_none()
|
|
||||||
{
|
|
||||||
check_must_use_candidate(
|
check_must_use_candidate(
|
||||||
cx,
|
cx,
|
||||||
sig.decl,
|
sig.decl,
|
||||||
|
@ -73,12 +70,12 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
|
||||||
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
|
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
|
||||||
|
|
||||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||||
let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
|
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
|
||||||
if let Some(attr) = attr {
|
if let Some(attr) = attr {
|
||||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
|
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
|
||||||
} else if let hir::TraitFn::Provided(eid) = *eid {
|
} else if let hir::TraitFn::Provided(eid) = *eid {
|
||||||
let body = cx.tcx.hir().body(eid);
|
let body = cx.tcx.hir().body(eid);
|
||||||
if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
|
if attr.is_none() && is_public && !is_proc_macro(attrs) {
|
||||||
check_must_use_candidate(
|
check_must_use_candidate(
|
||||||
cx,
|
cx,
|
||||||
sig.decl,
|
sig.decl,
|
||||||
|
|
|
@ -9,7 +9,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::{sym, Span};
|
use rustc_span::{sym, Span};
|
||||||
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
||||||
use rustc_trait_selection::traits::{self, FulfillmentError};
|
use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
|
@ -79,8 +79,10 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|
||||||
let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
|
let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
|
||||||
let span = decl.output.span();
|
let span = decl.output.span();
|
||||||
let infcx = cx.tcx.infer_ctxt().build();
|
let infcx = cx.tcx.infer_ctxt().build();
|
||||||
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
let cause = traits::ObligationCause::misc(span, fn_def_id);
|
let cause = traits::ObligationCause::misc(span, fn_def_id);
|
||||||
let send_errors = traits::fully_solve_bound(&infcx, cause, cx.param_env, ret_ty, send_trait);
|
ocx.register_bound(cause, cx.param_env, ret_ty, send_trait);
|
||||||
|
let send_errors = ocx.select_all_or_error();
|
||||||
if !send_errors.is_empty() {
|
if !send_errors.is_empty() {
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -167,7 +167,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
||||||
Finite
|
Finite
|
||||||
},
|
},
|
||||||
ExprKind::Block(block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
|
ExprKind::Block(block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
|
||||||
ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
|
ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
|
||||||
ExprKind::Call(path, _) => {
|
ExprKind::Call(path, _) => {
|
||||||
if let ExprKind::Path(ref qpath) = path.kind {
|
if let ExprKind::Path(ref qpath) = path.kind {
|
||||||
cx.qpath_res(qpath, path.hir_id)
|
cx.qpath_res(qpath, path.hir_id)
|
||||||
|
|
|
@ -302,6 +302,7 @@ mod unit_types;
|
||||||
mod unnamed_address;
|
mod unnamed_address;
|
||||||
mod unnecessary_owned_empty_strings;
|
mod unnecessary_owned_empty_strings;
|
||||||
mod unnecessary_self_imports;
|
mod unnecessary_self_imports;
|
||||||
|
mod unnecessary_struct_initialization;
|
||||||
mod unnecessary_wraps;
|
mod unnecessary_wraps;
|
||||||
mod unnested_or_patterns;
|
mod unnested_or_patterns;
|
||||||
mod unsafe_removed_from_name;
|
mod unsafe_removed_from_name;
|
||||||
|
@ -938,6 +939,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||||
store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped));
|
store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped));
|
||||||
store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
|
store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
|
||||||
store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv())));
|
store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv())));
|
||||||
|
store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct));
|
||||||
// add lints here, do not remove this comment, it's used in `new_lint`
|
// add lints here, do not remove this comment, it's used in `new_lint`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,8 +124,7 @@ fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'t
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: HirId) -> NeverLoopResult {
|
fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: HirId) -> NeverLoopResult {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Box(e)
|
ExprKind::Unary(_, e)
|
||||||
| ExprKind::Unary(_, e)
|
|
||||||
| ExprKind::Cast(e, _)
|
| ExprKind::Cast(e, _)
|
||||||
| ExprKind::Type(e, _)
|
| ExprKind::Type(e, _)
|
||||||
| ExprKind::Field(e, _)
|
| ExprKind::Field(e, _)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::match_function_call_with_def_id;
|
|
||||||
use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
|
use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
|
@ -184,16 +183,10 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
|
||||||
fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
|
fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let Some(block_expr) = block.expr;
|
if let Some(block_expr) = block.expr;
|
||||||
if let Some(args) = cx
|
|
||||||
.tcx
|
|
||||||
.lang_items()
|
|
||||||
.identity_future_fn()
|
|
||||||
.and_then(|def_id| match_function_call_with_def_id(cx, block_expr, def_id));
|
|
||||||
if args.len() == 1;
|
|
||||||
if let Expr {
|
if let Expr {
|
||||||
kind: ExprKind::Closure(&Closure { body, .. }),
|
kind: ExprKind::Closure(&Closure { body, .. }),
|
||||||
..
|
..
|
||||||
} = args[0];
|
} = block_expr;
|
||||||
let closure_body = cx.tcx.hir().body(body);
|
let closure_body = cx.tcx.hir().body(body);
|
||||||
if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
|
if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
|
||||||
then {
|
then {
|
||||||
|
|
|
@ -321,7 +321,6 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
|
||||||
self.has_significant_drop = true;
|
self.has_significant_drop = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Box(..) |
|
|
||||||
ExprKind::Array(..) |
|
ExprKind::Array(..) |
|
||||||
ExprKind::Call(..) |
|
ExprKind::Call(..) |
|
||||||
ExprKind::Unary(..) |
|
ExprKind::Unary(..) |
|
||||||
|
|
|
@ -33,10 +33,6 @@ struct SortByKeyDetection {
|
||||||
/// contains a and the other replaces it with b)
|
/// contains a and the other replaces it with b)
|
||||||
fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident: &Ident) -> bool {
|
fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident: &Ident) -> bool {
|
||||||
match (&a_expr.kind, &b_expr.kind) {
|
match (&a_expr.kind, &b_expr.kind) {
|
||||||
// Two boxes with mirrored contents
|
|
||||||
(ExprKind::Box(left_expr), ExprKind::Box(right_expr)) => {
|
|
||||||
mirrored_exprs(left_expr, a_ident, right_expr, b_ident)
|
|
||||||
},
|
|
||||||
// Two arrays with mirrored contents
|
// Two arrays with mirrored contents
|
||||||
(ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => {
|
(ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => {
|
||||||
iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident))
|
iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident))
|
||||||
|
|
|
@ -369,10 +369,10 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
|
||||||
Node::Item(item) => {
|
Node::Item(item) => {
|
||||||
if let ItemKind::Fn(_, _, body_id) = &item.kind
|
if let ItemKind::Fn(_, _, body_id) = &item.kind
|
||||||
&& let output_ty = return_ty(cx, item.owner_id)
|
&& let output_ty = return_ty(cx, item.owner_id)
|
||||||
&& Inherited::build(cx.tcx, item.owner_id.def_id).enter(|inherited| {
|
&& let inherited = Inherited::new(cx.tcx, item.owner_id.def_id)
|
||||||
let fn_ctxt = FnCtxt::new(inherited, cx.param_env, item.owner_id.def_id);
|
&& let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, item.owner_id.def_id)
|
||||||
fn_ctxt.can_coerce(ty, output_ty)
|
&& fn_ctxt.can_coerce(ty, output_ty)
|
||||||
}) {
|
{
|
||||||
if has_lifetime(output_ty) && has_lifetime(ty) {
|
if has_lifetime(output_ty) && has_lifetime(ty) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||||
| ExprKind::Type(inner, _)
|
| ExprKind::Type(inner, _)
|
||||||
| ExprKind::Unary(_, inner)
|
| ExprKind::Unary(_, inner)
|
||||||
| ExprKind::Field(inner, _)
|
| ExprKind::Field(inner, _)
|
||||||
| ExprKind::AddrOf(_, _, inner)
|
| ExprKind::AddrOf(_, _, inner) => has_no_effect(cx, inner),
|
||||||
| ExprKind::Box(inner) => has_no_effect(cx, inner),
|
|
||||||
ExprKind::Struct(_, fields, ref base) => {
|
ExprKind::Struct(_, fields, ref base) => {
|
||||||
!has_drop(cx, cx.typeck_results().expr_ty(expr))
|
!has_drop(cx, cx.typeck_results().expr_ty(expr))
|
||||||
&& fields.iter().all(|field| has_no_effect(cx, field.expr))
|
&& fields.iter().all(|field| has_no_effect(cx, field.expr))
|
||||||
|
@ -234,8 +233,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
|
||||||
| ExprKind::Type(inner, _)
|
| ExprKind::Type(inner, _)
|
||||||
| ExprKind::Unary(_, inner)
|
| ExprKind::Unary(_, inner)
|
||||||
| ExprKind::Field(inner, _)
|
| ExprKind::Field(inner, _)
|
||||||
| ExprKind::AddrOf(_, _, inner)
|
| ExprKind::AddrOf(_, _, inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
|
||||||
| ExprKind::Box(inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
|
|
||||||
ExprKind::Struct(_, fields, ref base) => {
|
ExprKind::Struct(_, fields, ref base) => {
|
||||||
if has_drop(cx, cx.typeck_results().expr_ty(expr)) {
|
if has_drop(cx, cx.typeck_results().expr_ty(expr)) {
|
||||||
None
|
None
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind;
|
if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind;
|
||||||
if !cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
|
if !cx.tcx.has_attr(item.owner_id, sym::automatically_derived);
|
||||||
if let Some(eq_trait) = cx.tcx.lang_items().eq_trait();
|
if let Some(eq_trait) = cx.tcx.lang_items().eq_trait();
|
||||||
if trait_ref.path.res.def_id() == eq_trait;
|
if trait_ref.path.res.def_id() == eq_trait;
|
||||||
then {
|
then {
|
||||||
|
|
|
@ -213,8 +213,7 @@ fn is_self_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, mut expr: &Expr<'_>, hir_
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
expr = match expr.kind {
|
expr = match expr.kind {
|
||||||
ExprKind::Box(e)
|
ExprKind::AddrOf(_, _, e)
|
||||||
| ExprKind::AddrOf(_, _, e)
|
|
||||||
| ExprKind::Block(
|
| ExprKind::Block(
|
||||||
&Block {
|
&Block {
|
||||||
stmts: [],
|
stmts: [],
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::FxHashSet;
|
|
||||||
use clippy_utils::{
|
use clippy_utils::{
|
||||||
diagnostics::span_lint_and_then,
|
diagnostics::span_lint_and_then,
|
||||||
get_attr,
|
get_attr,
|
||||||
source::{indent_of, snippet},
|
source::{indent_of, snippet},
|
||||||
};
|
};
|
||||||
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_errors::{Applicability, Diagnostic};
|
use rustc_errors::{Applicability, Diagnostic};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
self as hir,
|
self as hir,
|
||||||
|
@ -58,6 +58,7 @@ impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]);
|
||||||
pub struct SignificantDropTightening<'tcx> {
|
pub struct SignificantDropTightening<'tcx> {
|
||||||
/// Auxiliary structure used to avoid having to verify the same type multiple times.
|
/// Auxiliary structure used to avoid having to verify the same type multiple times.
|
||||||
seen_types: FxHashSet<Ty<'tcx>>,
|
seen_types: FxHashSet<Ty<'tcx>>,
|
||||||
|
type_cache: FxHashMap<Ty<'tcx>, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> SignificantDropTightening<'tcx> {
|
impl<'tcx> SignificantDropTightening<'tcx> {
|
||||||
|
@ -118,7 +119,7 @@ impl<'tcx> SignificantDropTightening<'tcx> {
|
||||||
stmt: &hir::Stmt<'_>,
|
stmt: &hir::Stmt<'_>,
|
||||||
cb: impl Fn(&mut SigDropAuxParams),
|
cb: impl Fn(&mut SigDropAuxParams),
|
||||||
) {
|
) {
|
||||||
let mut sig_drop_finder = SigDropFinder::new(cx, &mut self.seen_types);
|
let mut sig_drop_finder = SigDropFinder::new(cx, &mut self.seen_types, &mut self.type_cache);
|
||||||
sig_drop_finder.visit_expr(expr);
|
sig_drop_finder.visit_expr(expr);
|
||||||
if sig_drop_finder.has_sig_drop {
|
if sig_drop_finder.has_sig_drop {
|
||||||
cb(sdap);
|
cb(sdap);
|
||||||
|
@ -296,15 +297,24 @@ impl Default for SigDropAuxParams {
|
||||||
struct SigDropChecker<'cx, 'sdt, 'tcx> {
|
struct SigDropChecker<'cx, 'sdt, 'tcx> {
|
||||||
cx: &'cx LateContext<'tcx>,
|
cx: &'cx LateContext<'tcx>,
|
||||||
seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
|
seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
|
||||||
|
type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> {
|
impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> {
|
||||||
pub(crate) fn new(cx: &'cx LateContext<'tcx>, seen_types: &'sdt mut FxHashSet<Ty<'tcx>>) -> Self {
|
pub(crate) fn new(
|
||||||
|
cx: &'cx LateContext<'tcx>,
|
||||||
|
seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
|
||||||
|
type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
|
||||||
|
) -> Self {
|
||||||
seen_types.clear();
|
seen_types.clear();
|
||||||
Self { cx, seen_types }
|
Self {
|
||||||
|
cx,
|
||||||
|
seen_types,
|
||||||
|
type_cache,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
|
pub(crate) fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool {
|
||||||
if let Some(adt) = ty.ty_adt_def() {
|
if let Some(adt) = ty.ty_adt_def() {
|
||||||
let mut iter = get_attr(
|
let mut iter = get_attr(
|
||||||
self.cx.sess(),
|
self.cx.sess(),
|
||||||
|
@ -340,6 +350,16 @@ impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
|
||||||
|
// The borrow checker prevents us from using something fancier like or_insert_with.
|
||||||
|
if let Some(ty) = self.type_cache.get(&ty) {
|
||||||
|
return *ty;
|
||||||
|
}
|
||||||
|
let value = self.has_sig_drop_attr_uncached(ty);
|
||||||
|
self.type_cache.insert(ty, value);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
fn has_seen_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
fn has_seen_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
||||||
!self.seen_types.insert(ty)
|
!self.seen_types.insert(ty)
|
||||||
}
|
}
|
||||||
|
@ -353,11 +373,15 @@ struct SigDropFinder<'cx, 'sdt, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'sdt, 'tcx> SigDropFinder<'cx, 'sdt, 'tcx> {
|
impl<'cx, 'sdt, 'tcx> SigDropFinder<'cx, 'sdt, 'tcx> {
|
||||||
fn new(cx: &'cx LateContext<'tcx>, seen_types: &'sdt mut FxHashSet<Ty<'tcx>>) -> Self {
|
fn new(
|
||||||
|
cx: &'cx LateContext<'tcx>,
|
||||||
|
seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
|
||||||
|
type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cx,
|
cx,
|
||||||
has_sig_drop: false,
|
has_sig_drop: false,
|
||||||
sig_drop_checker: SigDropChecker::new(cx, seen_types),
|
sig_drop_checker: SigDropChecker::new(cx, seen_types, type_cache),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,7 +404,6 @@ impl<'cx, 'sdt, 'tcx> Visitor<'tcx> for SigDropFinder<'cx, 'sdt, 'tcx> {
|
||||||
| hir::ExprKind::Assign(..)
|
| hir::ExprKind::Assign(..)
|
||||||
| hir::ExprKind::AssignOp(..)
|
| hir::ExprKind::AssignOp(..)
|
||||||
| hir::ExprKind::Binary(..)
|
| hir::ExprKind::Binary(..)
|
||||||
| hir::ExprKind::Box(..)
|
|
||||||
| hir::ExprKind::Call(..)
|
| hir::ExprKind::Call(..)
|
||||||
| hir::ExprKind::Field(..)
|
| hir::ExprKind::Field(..)
|
||||||
| hir::ExprKind::If(..)
|
| hir::ExprKind::If(..)
|
||||||
|
|
|
@ -596,8 +596,7 @@ fn ident_difference_expr_with_base_location(
|
||||||
| (MethodCall(_), MethodCall(_))
|
| (MethodCall(_), MethodCall(_))
|
||||||
| (Call(_, _), Call(_, _))
|
| (Call(_, _), Call(_, _))
|
||||||
| (ConstBlock(_), ConstBlock(_))
|
| (ConstBlock(_), ConstBlock(_))
|
||||||
| (Array(_), Array(_))
|
| (Array(_), Array(_)) => {
|
||||||
| (Box(_), Box(_)) => {
|
|
||||||
// keep going
|
// keep going
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -2,8 +2,9 @@ use super::utils::check_cast;
|
||||||
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
|
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
|
use rustc_ast::ExprPrecedence;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::Expr;
|
use rustc_hir::{Expr, Node};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty::{cast::CastKind, Ty};
|
use rustc_middle::ty::{cast::CastKind, Ty};
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ pub(super) fn check<'tcx>(
|
||||||
) -> bool {
|
) -> bool {
|
||||||
use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
|
use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
|
||||||
let mut app = Applicability::MachineApplicable;
|
let mut app = Applicability::MachineApplicable;
|
||||||
let sugg = match check_cast(cx, e, from_ty, to_ty) {
|
let mut sugg = match check_cast(cx, e, from_ty, to_ty) {
|
||||||
Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
|
Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
|
||||||
Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
|
Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
|
||||||
.as_ty(to_ty.to_string())
|
.as_ty(to_ty.to_string())
|
||||||
|
@ -39,6 +40,12 @@ pub(super) fn check<'tcx>(
|
||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Node::Expr(parent) = cx.tcx.hir().get_parent(e.hir_id)
|
||||||
|
&& parent.precedence().order() > ExprPrecedence::Cast.order()
|
||||||
|
{
|
||||||
|
sugg = format!("({sugg})");
|
||||||
|
}
|
||||||
|
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
|
TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
|
||||||
|
|
|
@ -33,38 +33,37 @@ pub(super) fn check_cast<'tcx>(
|
||||||
let hir_id = e.hir_id;
|
let hir_id = e.hir_id;
|
||||||
let local_def_id = hir_id.owner.def_id;
|
let local_def_id = hir_id.owner.def_id;
|
||||||
|
|
||||||
Inherited::build(cx.tcx, local_def_id).enter(|inherited| {
|
let inherited = Inherited::new(cx.tcx, local_def_id);
|
||||||
let fn_ctxt = FnCtxt::new(inherited, cx.param_env, local_def_id);
|
let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, local_def_id);
|
||||||
|
|
||||||
// If we already have errors, we can't be sure we can pointer cast.
|
// If we already have errors, we can't be sure we can pointer cast.
|
||||||
|
assert!(
|
||||||
|
!fn_ctxt.errors_reported_since_creation(),
|
||||||
|
"Newly created FnCtxt contained errors"
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Ok(check) = cast::CastCheck::new(
|
||||||
|
&fn_ctxt,
|
||||||
|
e,
|
||||||
|
from_ty,
|
||||||
|
to_ty,
|
||||||
|
// We won't show any error to the user, so we don't care what the span is here.
|
||||||
|
DUMMY_SP,
|
||||||
|
DUMMY_SP,
|
||||||
|
hir::Constness::NotConst,
|
||||||
|
) {
|
||||||
|
let res = check.do_check(&fn_ctxt);
|
||||||
|
|
||||||
|
// do_check's documentation says that it might return Ok and create
|
||||||
|
// errors in the fcx instead of returning Err in some cases. Those cases
|
||||||
|
// should be filtered out before getting here.
|
||||||
assert!(
|
assert!(
|
||||||
!fn_ctxt.errors_reported_since_creation(),
|
!fn_ctxt.errors_reported_since_creation(),
|
||||||
"Newly created FnCtxt contained errors"
|
"`fn_ctxt` contained errors after cast check!"
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Ok(check) = cast::CastCheck::new(
|
res.ok()
|
||||||
&fn_ctxt,
|
} else {
|
||||||
e,
|
None
|
||||||
from_ty,
|
}
|
||||||
to_ty,
|
|
||||||
// We won't show any error to the user, so we don't care what the span is here.
|
|
||||||
DUMMY_SP,
|
|
||||||
DUMMY_SP,
|
|
||||||
hir::Constness::NotConst,
|
|
||||||
) {
|
|
||||||
let res = check.do_check(&fn_ctxt);
|
|
||||||
|
|
||||||
// do_check's documentation says that it might return Ok and create
|
|
||||||
// errors in the fcx instead of returning Err in some cases. Those cases
|
|
||||||
// should be filtered out before getting here.
|
|
||||||
assert!(
|
|
||||||
!fn_ctxt.errors_reported_since_creation(),
|
|
||||||
"`fn_ctxt` contained errors after cast check!"
|
|
||||||
);
|
|
||||||
|
|
||||||
res.ok()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
84
clippy_lints/src/unnecessary_struct_initialization.rs
Normal file
84
clippy_lints/src/unnecessary_struct_initialization.rs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
use clippy_utils::{diagnostics::span_lint_and_sugg, get_parent_expr, path_to_local, source::snippet, ty::is_copy};
|
||||||
|
use rustc_hir::{BindingAnnotation, Expr, ExprKind, Node, PatKind, UnOp};
|
||||||
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks for initialization of a `struct` by copying a base without setting
|
||||||
|
/// any field.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Readibility suffers from unnecessary struct building.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```rust
|
||||||
|
/// struct S { s: String }
|
||||||
|
///
|
||||||
|
/// let a = S { s: String::from("Hello, world!") };
|
||||||
|
/// let b = S { ..a };
|
||||||
|
/// ```
|
||||||
|
/// Use instead:
|
||||||
|
/// ```rust
|
||||||
|
/// struct S { s: String }
|
||||||
|
///
|
||||||
|
/// let a = S { s: String::from("Hello, world!") };
|
||||||
|
/// let b = a;
|
||||||
|
/// ```
|
||||||
|
#[clippy::version = "1.70.0"]
|
||||||
|
pub UNNECESSARY_STRUCT_INITIALIZATION,
|
||||||
|
complexity,
|
||||||
|
"struct built from a base that can be written mode concisely"
|
||||||
|
}
|
||||||
|
declare_lint_pass!(UnnecessaryStruct => [UNNECESSARY_STRUCT_INITIALIZATION]);
|
||||||
|
|
||||||
|
impl LateLintPass<'_> for UnnecessaryStruct {
|
||||||
|
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||||
|
if let ExprKind::Struct(_, &[], Some(base)) = expr.kind {
|
||||||
|
if let Some(parent) = get_parent_expr(cx, expr) &&
|
||||||
|
let parent_ty = cx.typeck_results().expr_ty_adjusted(parent) &&
|
||||||
|
parent_ty.is_any_ptr()
|
||||||
|
{
|
||||||
|
if is_copy(cx, cx.typeck_results().expr_ty(expr)) && path_to_local(base).is_some() {
|
||||||
|
// When the type implements `Copy`, a reference to the new struct works on the
|
||||||
|
// copy. Using the original would borrow it.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if parent_ty.is_mutable_ptr() && !is_mutable(cx, base) {
|
||||||
|
// The original can be used in a mutable reference context only if it is mutable.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: do not propose to replace *XX if XX is not Copy
|
||||||
|
if let ExprKind::Unary(UnOp::Deref, target) = base.kind &&
|
||||||
|
matches!(target.kind, ExprKind::Path(..)) &&
|
||||||
|
!is_copy(cx, cx.typeck_results().expr_ty(expr))
|
||||||
|
{
|
||||||
|
// `*base` cannot be used instead of the struct in the general case if it is not Copy.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
UNNECESSARY_STRUCT_INITIALIZATION,
|
||||||
|
expr.span,
|
||||||
|
"unnecessary struct building",
|
||||||
|
"replace with",
|
||||||
|
snippet(cx, base.span, "..").into_owned(),
|
||||||
|
rustc_errors::Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_mutable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||||
|
if let Some(hir_id) = path_to_local(expr) &&
|
||||||
|
let Node::Pat(pat) = cx.tcx.hir().get(hir_id)
|
||||||
|
{
|
||||||
|
matches!(pat.kind, PatKind::Binding(BindingAnnotation::MUT, ..))
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
|
@ -395,11 +395,6 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
self.expr(field!(let_expr.init));
|
self.expr(field!(let_expr.init));
|
||||||
},
|
},
|
||||||
ExprKind::Box(inner) => {
|
|
||||||
bind!(self, inner);
|
|
||||||
kind!("Box({inner})");
|
|
||||||
self.expr(inner);
|
|
||||||
},
|
|
||||||
ExprKind::Array(elements) => {
|
ExprKind::Array(elements) => {
|
||||||
bind!(self, elements);
|
bind!(self, elements);
|
||||||
kind!("Array({elements})");
|
kind!("Array({elements})");
|
||||||
|
|
|
@ -143,7 +143,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
||||||
(Paren(l), _) => eq_expr(l, r),
|
(Paren(l), _) => eq_expr(l, r),
|
||||||
(_, Paren(r)) => eq_expr(l, r),
|
(_, Paren(r)) => eq_expr(l, r),
|
||||||
(Err, Err) => true,
|
(Err, Err) => true,
|
||||||
(Box(l), Box(r)) | (Try(l), Try(r)) | (Await(l), Await(r)) => eq_expr(l, r),
|
(Try(l), Try(r)) | (Await(l), Await(r)) => eq_expr(l, r),
|
||||||
(Array(l), Array(r)) => over(l, r, |l, r| eq_expr(l, r)),
|
(Array(l), Array(r)) => over(l, r, |l, r| eq_expr(l, r)),
|
||||||
(Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
|
(Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
|
||||||
(Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
|
(Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
|
||||||
|
|
|
@ -145,8 +145,8 @@ pub fn get_unique_attr<'a>(
|
||||||
|
|
||||||
/// Return true if the attributes contain any of `proc_macro`,
|
/// Return true if the attributes contain any of `proc_macro`,
|
||||||
/// `proc_macro_derive` or `proc_macro_attribute`, false otherwise
|
/// `proc_macro_derive` or `proc_macro_attribute`, false otherwise
|
||||||
pub fn is_proc_macro(sess: &Session, attrs: &[ast::Attribute]) -> bool {
|
pub fn is_proc_macro(attrs: &[ast::Attribute]) -> bool {
|
||||||
attrs.iter().any(|attr| sess.is_proc_macro_attr(attr))
|
attrs.iter().any(rustc_ast::Attribute::is_proc_macro_attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the attributes contain `#[doc(hidden)]`
|
/// Return true if the attributes contain `#[doc(hidden)]`
|
||||||
|
|
|
@ -112,7 +112,6 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) {
|
||||||
/// Get the search patterns to use for the given expression
|
/// Get the search patterns to use for the given expression
|
||||||
fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) {
|
fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) {
|
||||||
match e.kind {
|
match e.kind {
|
||||||
ExprKind::Box(e) => (Pat::Str("box"), expr_search_pat(tcx, e).1),
|
|
||||||
ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")),
|
ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")),
|
||||||
ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")),
|
ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")),
|
||||||
ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat(tcx, e).1),
|
ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat(tcx, e).1),
|
||||||
|
|
|
@ -199,11 +199,9 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
|
||||||
},
|
},
|
||||||
|
|
||||||
// Memory allocation, custom operator, loop, or call to an unknown function
|
// Memory allocation, custom operator, loop, or call to an unknown function
|
||||||
ExprKind::Box(_)
|
ExprKind::Unary(..) | ExprKind::Binary(..) | ExprKind::Loop(..) | ExprKind::Call(..) => {
|
||||||
| ExprKind::Unary(..)
|
self.eagerness = Lazy;
|
||||||
| ExprKind::Binary(..)
|
},
|
||||||
| ExprKind::Loop(..)
|
|
||||||
| ExprKind::Call(..) => self.eagerness = Lazy,
|
|
||||||
|
|
||||||
ExprKind::ConstBlock(_)
|
ExprKind::ConstBlock(_)
|
||||||
| ExprKind::Array(_)
|
| ExprKind::Array(_)
|
||||||
|
|
|
@ -249,7 +249,6 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name)
|
both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name)
|
||||||
&& both(le, re, |l, r| self.eq_expr(l, r))
|
&& both(le, re, |l, r| self.eq_expr(l, r))
|
||||||
},
|
},
|
||||||
(&ExprKind::Box(l), &ExprKind::Box(r)) => self.eq_expr(l, r),
|
|
||||||
(&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => {
|
(&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => {
|
||||||
self.inner.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args)
|
self.inner.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args)
|
||||||
},
|
},
|
||||||
|
@ -628,7 +627,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
self.hash_expr(j);
|
self.hash_expr(j);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ExprKind::Box(e) | ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
|
ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
|
||||||
self.hash_expr(e);
|
self.hash_expr(e);
|
||||||
},
|
},
|
||||||
ExprKind::Call(fun, args) => {
|
ExprKind::Call(fun, args) => {
|
||||||
|
|
|
@ -1923,16 +1923,7 @@ pub fn is_async_fn(kind: FnKind<'_>) -> bool {
|
||||||
|
|
||||||
/// Peels away all the compiler generated code surrounding the body of an async function,
|
/// Peels away all the compiler generated code surrounding the body of an async function,
|
||||||
pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
|
pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
|
||||||
if let ExprKind::Call(
|
if let ExprKind::Closure(&Closure { body, .. }) = body.value.kind {
|
||||||
_,
|
|
||||||
&[
|
|
||||||
Expr {
|
|
||||||
kind: ExprKind::Closure(&Closure { body, .. }),
|
|
||||||
..
|
|
||||||
},
|
|
||||||
],
|
|
||||||
) = body.value.kind
|
|
||||||
{
|
|
||||||
if let ExprKind::Block(
|
if let ExprKind::Block(
|
||||||
Block {
|
Block {
|
||||||
stmts: [],
|
stmts: [],
|
||||||
|
|
|
@ -533,6 +533,14 @@ struct FormatArgsValues<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> FormatArgsValues<'tcx> {
|
impl<'tcx> FormatArgsValues<'tcx> {
|
||||||
|
fn new_empty(format_string_span: SpanData) -> Self {
|
||||||
|
Self {
|
||||||
|
value_args: Vec::new(),
|
||||||
|
pos_to_value_index: Vec::new(),
|
||||||
|
format_string_span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn new(args: &'tcx Expr<'tcx>, format_string_span: SpanData) -> Self {
|
fn new(args: &'tcx Expr<'tcx>, format_string_span: SpanData) -> Self {
|
||||||
let mut pos_to_value_index = Vec::new();
|
let mut pos_to_value_index = Vec::new();
|
||||||
let mut value_args = Vec::new();
|
let mut value_args = Vec::new();
|
||||||
|
@ -997,12 +1005,13 @@ impl<'tcx> FormatArgsExpn<'tcx> {
|
||||||
.find(|&name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl))?;
|
.find(|&name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl))?;
|
||||||
let newline = macro_name == sym::format_args_nl;
|
let newline = macro_name == sym::format_args_nl;
|
||||||
|
|
||||||
|
// ::core::fmt::Arguments::new_const(pieces)
|
||||||
// ::core::fmt::Arguments::new_v1(pieces, args)
|
// ::core::fmt::Arguments::new_v1(pieces, args)
|
||||||
// ::core::fmt::Arguments::new_v1_formatted(pieces, args, fmt, _unsafe_arg)
|
// ::core::fmt::Arguments::new_v1_formatted(pieces, args, fmt, _unsafe_arg)
|
||||||
if let ExprKind::Call(callee, [pieces, args, rest @ ..]) = expr.kind
|
if let ExprKind::Call(callee, [pieces, rest @ ..]) = expr.kind
|
||||||
&& let ExprKind::Path(QPath::TypeRelative(ty, seg)) = callee.kind
|
&& let ExprKind::Path(QPath::TypeRelative(ty, seg)) = callee.kind
|
||||||
&& let TyKind::Path(QPath::LangItem(LangItem::FormatArguments, _, _)) = ty.kind
|
&& let TyKind::Path(QPath::LangItem(LangItem::FormatArguments, _, _)) = ty.kind
|
||||||
&& matches!(seg.ident.as_str(), "new_v1" | "new_v1_formatted")
|
&& matches!(seg.ident.as_str(), "new_const" | "new_v1" | "new_v1_formatted")
|
||||||
{
|
{
|
||||||
let format_string = FormatString::new(cx, pieces)?;
|
let format_string = FormatString::new(cx, pieces)?;
|
||||||
|
|
||||||
|
@ -1026,7 +1035,7 @@ impl<'tcx> FormatArgsExpn<'tcx> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let positions = if let Some(fmt_arg) = rest.first() {
|
let positions = if let Some(fmt_arg) = rest.get(1) {
|
||||||
// If the argument contains format specs, `new_v1_formatted(_, _, fmt, _)`, parse
|
// If the argument contains format specs, `new_v1_formatted(_, _, fmt, _)`, parse
|
||||||
// them.
|
// them.
|
||||||
|
|
||||||
|
@ -1042,7 +1051,11 @@ impl<'tcx> FormatArgsExpn<'tcx> {
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
|
|
||||||
let values = FormatArgsValues::new(args, format_string.span.data());
|
let values = if let Some(args) = rest.first() {
|
||||||
|
FormatArgsValues::new(args, format_string.span.data())
|
||||||
|
} else {
|
||||||
|
FormatArgsValues::new_empty(format_string.span.data())
|
||||||
|
};
|
||||||
|
|
||||||
let args = izip!(positions, parsed_args, parser.arg_places)
|
let args = izip!(positions, parsed_args, parser.arg_places)
|
||||||
.map(|(position, parsed_arg, arg_span)| {
|
.map(|(position, parsed_arg, arg_span)| {
|
||||||
|
|
|
@ -37,7 +37,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
|
||||||
| ty::PredicateKind::ConstEvaluatable(..)
|
| ty::PredicateKind::ConstEvaluatable(..)
|
||||||
| ty::PredicateKind::ConstEquate(..)
|
| ty::PredicateKind::ConstEquate(..)
|
||||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
|
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
|
||||||
ty::PredicateKind::AliasEq(..) => panic!("alias eq predicate on function: {predicate:#?}"),
|
ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"),
|
||||||
ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"),
|
ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"),
|
||||||
ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"),
|
ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"),
|
||||||
ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"),
|
ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"),
|
||||||
|
@ -176,6 +176,10 @@ fn check_rvalue<'tcx>(
|
||||||
// FIXME(dyn-star)
|
// FIXME(dyn-star)
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
},
|
},
|
||||||
|
Rvalue::Cast(CastKind::Transmute, _, _) => Err((
|
||||||
|
span,
|
||||||
|
"transmute can attempt to turn pointers into integers, so is unstable in const fn".into(),
|
||||||
|
)),
|
||||||
// binops are fine on integers
|
// binops are fine on integers
|
||||||
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
|
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
|
||||||
check_operand(tcx, lhs, span, body)?;
|
check_operand(tcx, lhs, span, body)?;
|
||||||
|
@ -241,6 +245,7 @@ fn check_statement<'tcx>(
|
||||||
| StatementKind::StorageDead(_)
|
| StatementKind::StorageDead(_)
|
||||||
| StatementKind::Retag { .. }
|
| StatementKind::Retag { .. }
|
||||||
| StatementKind::AscribeUserType(..)
|
| StatementKind::AscribeUserType(..)
|
||||||
|
| StatementKind::PlaceMention(..)
|
||||||
| StatementKind::Coverage(..)
|
| StatementKind::Coverage(..)
|
||||||
| StatementKind::ConstEvalCounter
|
| StatementKind::ConstEvalCounter
|
||||||
| StatementKind::Nop => Ok(()),
|
| StatementKind::Nop => Ok(()),
|
||||||
|
|
|
@ -125,7 +125,6 @@ impl<'a> Sugg<'a> {
|
||||||
|
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
hir::ExprKind::AddrOf(..)
|
hir::ExprKind::AddrOf(..)
|
||||||
| hir::ExprKind::Box(..)
|
|
||||||
| hir::ExprKind::If(..)
|
| hir::ExprKind::If(..)
|
||||||
| hir::ExprKind::Let(..)
|
| hir::ExprKind::Let(..)
|
||||||
| hir::ExprKind::Closure { .. }
|
| hir::ExprKind::Closure { .. }
|
||||||
|
@ -180,7 +179,6 @@ impl<'a> Sugg<'a> {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
_ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0),
|
_ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0),
|
||||||
ast::ExprKind::AddrOf(..)
|
ast::ExprKind::AddrOf(..)
|
||||||
| ast::ExprKind::Box(..)
|
|
||||||
| ast::ExprKind::Closure { .. }
|
| ast::ExprKind::Closure { .. }
|
||||||
| ast::ExprKind::If(..)
|
| ast::ExprKind::If(..)
|
||||||
| ast::ExprKind::Let(..)
|
| ast::ExprKind::Let(..)
|
||||||
|
|
|
@ -599,10 +599,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
|
||||||
| ExprKind::Let(&Let { init: e, .. }) => {
|
| ExprKind::Let(&Let { init: e, .. }) => {
|
||||||
helper(typeck, false, e, f)?;
|
helper(typeck, false, e, f)?;
|
||||||
},
|
},
|
||||||
ExprKind::Block(&Block { expr: Some(e), .. }, _)
|
ExprKind::Block(&Block { expr: Some(e), .. }, _) | ExprKind::Cast(e, _) | ExprKind::Unary(_, e) => {
|
||||||
| ExprKind::Box(e)
|
|
||||||
| ExprKind::Cast(e, _)
|
|
||||||
| ExprKind::Unary(_, e) => {
|
|
||||||
helper(typeck, true, e, f)?;
|
helper(typeck, true, e, f)?;
|
||||||
},
|
},
|
||||||
ExprKind::Call(callee, args) => {
|
ExprKind::Call(callee, args) => {
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2023-03-10"
|
channel = "nightly-2023-03-24"
|
||||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||||
|
|
|
@ -49,6 +49,8 @@ The changelog for `rustc_tools_util` is available under:
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
<!-- REUSE-IgnoreStart -->
|
||||||
|
|
||||||
Copyright 2014-2022 The Rust Project Developers
|
Copyright 2014-2022 The Rust Project Developers
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
@ -56,3 +58,5 @@ http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
option. All files in the project carrying such notice may not be
|
option. All files in the project carrying such notice may not be
|
||||||
copied, modified, or distributed except according to those terms.
|
copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
<!-- REUSE-IgnoreEnd -->
|
||||||
|
|
|
@ -9,3 +9,4 @@ note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy
|
||||||
|
|
||||||
note: Clippy version: foo
|
note: Clippy version: foo
|
||||||
|
|
||||||
|
thread panicked while panicking. aborting.
|
||||||
|
|
|
@ -43,11 +43,7 @@ if let ExprKind::Block(block, None) = expr.kind
|
||||||
if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kind
|
if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kind
|
||||||
&& let FnRetTy::DefaultReturn(_) = fn_decl.output
|
&& let FnRetTy::DefaultReturn(_) = fn_decl.output
|
||||||
&& expr1 = &cx.tcx.hir().body(body_id).value
|
&& expr1 = &cx.tcx.hir().body(body_id).value
|
||||||
&& let ExprKind::Call(func, args) = expr1.kind
|
&& let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = expr1.kind
|
||||||
&& let ExprKind::Path(ref qpath) = func.kind
|
|
||||||
&& matches!(qpath, QPath::LangItem(LangItem::IdentityFuture, _))
|
|
||||||
&& args.len() == 1
|
|
||||||
&& let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = args[0].kind
|
|
||||||
&& let FnRetTy::DefaultReturn(_) = fn_decl1.output
|
&& let FnRetTy::DefaultReturn(_) = fn_decl1.output
|
||||||
&& expr2 = &cx.tcx.hir().body(body_id1).value
|
&& expr2 = &cx.tcx.hir().body(body_id1).value
|
||||||
&& let ExprKind::Block(block, None) = expr2.kind
|
&& let ExprKind::Block(block, None) = expr2.kind
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![feature(box_syntax)]
|
|
||||||
#![feature(lint_reasons)]
|
#![feature(lint_reasons)]
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::borrowed_box,
|
clippy::borrowed_box,
|
||||||
|
@ -34,7 +33,7 @@ fn ok_box_trait(boxed_trait: &Box<dyn Z>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warn_call() {
|
fn warn_call() {
|
||||||
let x = box A;
|
let x = Box::new(A);
|
||||||
x.foo();
|
x.foo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,41 +42,41 @@ fn warn_arg(x: Box<A>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nowarn_closure_arg() {
|
fn nowarn_closure_arg() {
|
||||||
let x = Some(box A);
|
let x = Some(Box::new(A));
|
||||||
x.map_or((), |x| take_ref(&x));
|
x.map_or((), |x| take_ref(&x));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warn_rename_call() {
|
fn warn_rename_call() {
|
||||||
let x = box A;
|
let x = Box::new(A);
|
||||||
|
|
||||||
let y = x;
|
let y = x;
|
||||||
y.foo(); // via autoderef
|
y.foo(); // via autoderef
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warn_notuse() {
|
fn warn_notuse() {
|
||||||
let bz = box A;
|
let bz = Box::new(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warn_pass() {
|
fn warn_pass() {
|
||||||
let bz = box A;
|
let bz = Box::new(A);
|
||||||
take_ref(&bz); // via deref coercion
|
take_ref(&bz); // via deref coercion
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nowarn_return() -> Box<A> {
|
fn nowarn_return() -> Box<A> {
|
||||||
box A // moved out, "escapes"
|
Box::new(A) // moved out, "escapes"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nowarn_move() {
|
fn nowarn_move() {
|
||||||
let bx = box A;
|
let bx = Box::new(A);
|
||||||
drop(bx) // moved in, "escapes"
|
drop(bx) // moved in, "escapes"
|
||||||
}
|
}
|
||||||
fn nowarn_call() {
|
fn nowarn_call() {
|
||||||
let bx = box A;
|
let bx = Box::new(A);
|
||||||
bx.clone(); // method only available to Box, not via autoderef
|
bx.clone(); // method only available to Box, not via autoderef
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nowarn_pass() {
|
fn nowarn_pass() {
|
||||||
let bx = box A;
|
let bx = Box::new(A);
|
||||||
take_box(&bx); // fn needs &Box
|
take_box(&bx); // fn needs &Box
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,30 +85,20 @@ fn take_ref(x: &A) {}
|
||||||
|
|
||||||
fn nowarn_ref_take() {
|
fn nowarn_ref_take() {
|
||||||
// false positive, should actually warn
|
// false positive, should actually warn
|
||||||
let x = box A;
|
let x = Box::new(A);
|
||||||
let y = &x;
|
let y = &x;
|
||||||
take_box(y);
|
take_box(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nowarn_match() {
|
fn nowarn_match() {
|
||||||
let x = box A; // moved into a match
|
let x = Box::new(A); // moved into a match
|
||||||
match x {
|
match x {
|
||||||
y => drop(y),
|
y => drop(y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warn_match() {
|
fn warn_match() {
|
||||||
let x = box A;
|
let x = Box::new(A);
|
||||||
match &x {
|
|
||||||
// not moved
|
|
||||||
y => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn nowarn_large_array() {
|
|
||||||
// should not warn, is large array
|
|
||||||
// and should not be on stack
|
|
||||||
let x = box [1; 10000];
|
|
||||||
match &x {
|
match &x {
|
||||||
// not moved
|
// not moved
|
||||||
y => (),
|
y => (),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: local variable doesn't need to be boxed here
|
error: local variable doesn't need to be boxed here
|
||||||
--> $DIR/boxed_local.rs:41:13
|
--> $DIR/boxed_local.rs:40:13
|
||||||
|
|
|
|
||||||
LL | fn warn_arg(x: Box<A>) {
|
LL | fn warn_arg(x: Box<A>) {
|
||||||
| ^
|
| ^
|
||||||
|
@ -7,19 +7,19 @@ LL | fn warn_arg(x: Box<A>) {
|
||||||
= note: `-D clippy::boxed-local` implied by `-D warnings`
|
= note: `-D clippy::boxed-local` implied by `-D warnings`
|
||||||
|
|
||||||
error: local variable doesn't need to be boxed here
|
error: local variable doesn't need to be boxed here
|
||||||
--> $DIR/boxed_local.rs:132:12
|
--> $DIR/boxed_local.rs:121:12
|
||||||
|
|
|
|
||||||
LL | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {}
|
LL | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {}
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: local variable doesn't need to be boxed here
|
error: local variable doesn't need to be boxed here
|
||||||
--> $DIR/boxed_local.rs:196:44
|
--> $DIR/boxed_local.rs:185:44
|
||||||
|
|
|
|
||||||
LL | fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 {
|
LL | fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 {
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: local variable doesn't need to be boxed here
|
error: local variable doesn't need to be boxed here
|
||||||
--> $DIR/boxed_local.rs:203:16
|
--> $DIR/boxed_local.rs:192:16
|
||||||
|
|
|
|
||||||
LL | fn foo(x: Box<u32>) {}
|
LL | fn foo(x: Box<u32>) {}
|
||||||
| ^
|
| ^
|
||||||
|
|
|
@ -29,6 +29,12 @@ fn main() {
|
||||||
1f64 as isize;
|
1f64 as isize;
|
||||||
1f64 as usize;
|
1f64 as usize;
|
||||||
1f32 as u32 as u16;
|
1f32 as u32 as u16;
|
||||||
|
{
|
||||||
|
let _x: i8 = 1i32 as _;
|
||||||
|
1f32 as i32;
|
||||||
|
1f64 as i32;
|
||||||
|
1f32 as u8;
|
||||||
|
}
|
||||||
// Test clippy::cast_possible_wrap
|
// Test clippy::cast_possible_wrap
|
||||||
1u8 as i8;
|
1u8 as i8;
|
||||||
1u16 as i16;
|
1u16 as i16;
|
||||||
|
|
|
@ -44,10 +44,6 @@ LL | 1f32 as i32;
|
||||||
|
|
|
|
||||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
= note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
|
= note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
|
||||||
help: ... or use `try_from` and handle the error accordingly
|
|
||||||
|
|
|
||||||
LL | i32::try_from(1f32);
|
|
||||||
| ~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
error: casting `f32` to `u32` may truncate the value
|
error: casting `f32` to `u32` may truncate the value
|
||||||
--> $DIR/cast.rs:25:5
|
--> $DIR/cast.rs:25:5
|
||||||
|
@ -56,10 +52,6 @@ LL | 1f32 as u32;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
help: ... or use `try_from` and handle the error accordingly
|
|
||||||
|
|
|
||||||
LL | u32::try_from(1f32);
|
|
||||||
| ~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
error: casting `f32` to `u32` may lose the sign of the value
|
error: casting `f32` to `u32` may lose the sign of the value
|
||||||
--> $DIR/cast.rs:25:5
|
--> $DIR/cast.rs:25:5
|
||||||
|
@ -76,10 +68,6 @@ LL | 1f64 as f32;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
help: ... or use `try_from` and handle the error accordingly
|
|
||||||
|
|
|
||||||
LL | f32::try_from(1f64);
|
|
||||||
| ~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
error: casting `i32` to `i8` may truncate the value
|
error: casting `i32` to `i8` may truncate the value
|
||||||
--> $DIR/cast.rs:27:5
|
--> $DIR/cast.rs:27:5
|
||||||
|
@ -112,10 +100,6 @@ LL | 1f64 as isize;
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
help: ... or use `try_from` and handle the error accordingly
|
|
||||||
|
|
|
||||||
LL | isize::try_from(1f64);
|
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
error: casting `f64` to `usize` may truncate the value
|
error: casting `f64` to `usize` may truncate the value
|
||||||
--> $DIR/cast.rs:30:5
|
--> $DIR/cast.rs:30:5
|
||||||
|
@ -124,10 +108,6 @@ LL | 1f64 as usize;
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
help: ... or use `try_from` and handle the error accordingly
|
|
||||||
|
|
|
||||||
LL | usize::try_from(1f64);
|
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
error: casting `f64` to `usize` may lose the sign of the value
|
error: casting `f64` to `usize` may lose the sign of the value
|
||||||
--> $DIR/cast.rs:30:5
|
--> $DIR/cast.rs:30:5
|
||||||
|
@ -154,10 +134,6 @@ LL | 1f32 as u32 as u16;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
help: ... or use `try_from` and handle the error accordingly
|
|
||||||
|
|
|
||||||
LL | u32::try_from(1f32) as u16;
|
|
||||||
| ~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
error: casting `f32` to `u32` may lose the sign of the value
|
error: casting `f32` to `u32` may lose the sign of the value
|
||||||
--> $DIR/cast.rs:31:5
|
--> $DIR/cast.rs:31:5
|
||||||
|
@ -165,8 +141,50 @@ error: casting `f32` to `u32` may lose the sign of the value
|
||||||
LL | 1f32 as u32 as u16;
|
LL | 1f32 as u32 as u16;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: casting `i32` to `i8` may truncate the value
|
||||||
|
--> $DIR/cast.rs:33:22
|
||||||
|
|
|
||||||
|
LL | let _x: i8 = 1i32 as _;
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
|
help: ... or use `try_from` and handle the error accordingly
|
||||||
|
|
|
||||||
|
LL | let _x: i8 = 1i32.try_into();
|
||||||
|
| ~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: casting `f32` to `i32` may truncate the value
|
||||||
|
--> $DIR/cast.rs:34:9
|
||||||
|
|
|
||||||
|
LL | 1f32 as i32;
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
|
|
||||||
|
error: casting `f64` to `i32` may truncate the value
|
||||||
|
--> $DIR/cast.rs:35:9
|
||||||
|
|
|
||||||
|
LL | 1f64 as i32;
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
|
|
||||||
|
error: casting `f32` to `u8` may truncate the value
|
||||||
|
--> $DIR/cast.rs:36:9
|
||||||
|
|
|
||||||
|
LL | 1f32 as u8;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
|
|
||||||
|
error: casting `f32` to `u8` may lose the sign of the value
|
||||||
|
--> $DIR/cast.rs:36:9
|
||||||
|
|
|
||||||
|
LL | 1f32 as u8;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: casting `u8` to `i8` may wrap around the value
|
error: casting `u8` to `i8` may wrap around the value
|
||||||
--> $DIR/cast.rs:33:5
|
--> $DIR/cast.rs:39:5
|
||||||
|
|
|
|
||||||
LL | 1u8 as i8;
|
LL | 1u8 as i8;
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -174,43 +192,43 @@ LL | 1u8 as i8;
|
||||||
= note: `-D clippy::cast-possible-wrap` implied by `-D warnings`
|
= note: `-D clippy::cast-possible-wrap` implied by `-D warnings`
|
||||||
|
|
||||||
error: casting `u16` to `i16` may wrap around the value
|
error: casting `u16` to `i16` may wrap around the value
|
||||||
--> $DIR/cast.rs:34:5
|
--> $DIR/cast.rs:40:5
|
||||||
|
|
|
|
||||||
LL | 1u16 as i16;
|
LL | 1u16 as i16;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: casting `u32` to `i32` may wrap around the value
|
error: casting `u32` to `i32` may wrap around the value
|
||||||
--> $DIR/cast.rs:35:5
|
--> $DIR/cast.rs:41:5
|
||||||
|
|
|
|
||||||
LL | 1u32 as i32;
|
LL | 1u32 as i32;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: casting `u64` to `i64` may wrap around the value
|
error: casting `u64` to `i64` may wrap around the value
|
||||||
--> $DIR/cast.rs:36:5
|
--> $DIR/cast.rs:42:5
|
||||||
|
|
|
|
||||||
LL | 1u64 as i64;
|
LL | 1u64 as i64;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: casting `usize` to `isize` may wrap around the value
|
error: casting `usize` to `isize` may wrap around the value
|
||||||
--> $DIR/cast.rs:37:5
|
--> $DIR/cast.rs:43:5
|
||||||
|
|
|
|
||||||
LL | 1usize as isize;
|
LL | 1usize as isize;
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: casting `i32` to `u32` may lose the sign of the value
|
error: casting `i32` to `u32` may lose the sign of the value
|
||||||
--> $DIR/cast.rs:40:5
|
--> $DIR/cast.rs:46:5
|
||||||
|
|
|
|
||||||
LL | -1i32 as u32;
|
LL | -1i32 as u32;
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: casting `isize` to `usize` may lose the sign of the value
|
error: casting `isize` to `usize` may lose the sign of the value
|
||||||
--> $DIR/cast.rs:42:5
|
--> $DIR/cast.rs:48:5
|
||||||
|
|
|
|
||||||
LL | -1isize as usize;
|
LL | -1isize as usize;
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: casting `i64` to `i8` may truncate the value
|
error: casting `i64` to `i8` may truncate the value
|
||||||
--> $DIR/cast.rs:109:5
|
--> $DIR/cast.rs:115:5
|
||||||
|
|
|
|
||||||
LL | (-99999999999i64).min(1) as i8; // should be linted because signed
|
LL | (-99999999999i64).min(1) as i8; // should be linted because signed
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -222,7 +240,7 @@ LL | i8::try_from((-99999999999i64).min(1)); // should be linted because sig
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: casting `u64` to `u8` may truncate the value
|
error: casting `u64` to `u8` may truncate the value
|
||||||
--> $DIR/cast.rs:121:5
|
--> $DIR/cast.rs:127:5
|
||||||
|
|
|
|
||||||
LL | 999999u64.clamp(0, 256) as u8; // should still be linted
|
LL | 999999u64.clamp(0, 256) as u8; // should still be linted
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -234,7 +252,7 @@ LL | u8::try_from(999999u64.clamp(0, 256)); // should still be linted
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: casting `main::E2` to `u8` may truncate the value
|
error: casting `main::E2` to `u8` may truncate the value
|
||||||
--> $DIR/cast.rs:142:21
|
--> $DIR/cast.rs:148:21
|
||||||
|
|
|
|
||||||
LL | let _ = self as u8;
|
LL | let _ = self as u8;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
@ -246,7 +264,7 @@ LL | let _ = u8::try_from(self);
|
||||||
| ~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: casting `main::E2::B` to `u8` will truncate the value
|
error: casting `main::E2::B` to `u8` will truncate the value
|
||||||
--> $DIR/cast.rs:143:21
|
--> $DIR/cast.rs:149:21
|
||||||
|
|
|
|
||||||
LL | let _ = Self::B as u8;
|
LL | let _ = Self::B as u8;
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
@ -254,7 +272,7 @@ LL | let _ = Self::B as u8;
|
||||||
= note: `-D clippy::cast-enum-truncation` implied by `-D warnings`
|
= note: `-D clippy::cast-enum-truncation` implied by `-D warnings`
|
||||||
|
|
||||||
error: casting `main::E5` to `i8` may truncate the value
|
error: casting `main::E5` to `i8` may truncate the value
|
||||||
--> $DIR/cast.rs:179:21
|
--> $DIR/cast.rs:185:21
|
||||||
|
|
|
|
||||||
LL | let _ = self as i8;
|
LL | let _ = self as i8;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
@ -266,13 +284,13 @@ LL | let _ = i8::try_from(self);
|
||||||
| ~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: casting `main::E5::A` to `i8` will truncate the value
|
error: casting `main::E5::A` to `i8` will truncate the value
|
||||||
--> $DIR/cast.rs:180:21
|
--> $DIR/cast.rs:186:21
|
||||||
|
|
|
|
||||||
LL | let _ = Self::A as i8;
|
LL | let _ = Self::A as i8;
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: casting `main::E6` to `i16` may truncate the value
|
error: casting `main::E6` to `i16` may truncate the value
|
||||||
--> $DIR/cast.rs:194:21
|
--> $DIR/cast.rs:200:21
|
||||||
|
|
|
|
||||||
LL | let _ = self as i16;
|
LL | let _ = self as i16;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
@ -284,7 +302,7 @@ LL | let _ = i16::try_from(self);
|
||||||
| ~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
|
error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
|
||||||
--> $DIR/cast.rs:209:21
|
--> $DIR/cast.rs:215:21
|
||||||
|
|
|
|
||||||
LL | let _ = self as usize;
|
LL | let _ = self as usize;
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
@ -296,7 +314,7 @@ LL | let _ = usize::try_from(self);
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: casting `main::E10` to `u16` may truncate the value
|
error: casting `main::E10` to `u16` may truncate the value
|
||||||
--> $DIR/cast.rs:250:21
|
--> $DIR/cast.rs:256:21
|
||||||
|
|
|
|
||||||
LL | let _ = self as u16;
|
LL | let _ = self as u16;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
@ -308,7 +326,7 @@ LL | let _ = u16::try_from(self);
|
||||||
| ~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: casting `u32` to `u8` may truncate the value
|
error: casting `u32` to `u8` may truncate the value
|
||||||
--> $DIR/cast.rs:258:13
|
--> $DIR/cast.rs:264:13
|
||||||
|
|
|
|
||||||
LL | let c = (q >> 16) as u8;
|
LL | let c = (q >> 16) as u8;
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
@ -316,11 +334,11 @@ LL | let c = (q >> 16) as u8;
|
||||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
help: ... or use `try_from` and handle the error accordingly
|
help: ... or use `try_from` and handle the error accordingly
|
||||||
|
|
|
|
||||||
LL | let c = u8::try_from((q >> 16));
|
LL | let c = u8::try_from(q >> 16);
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: casting `u32` to `u8` may truncate the value
|
error: casting `u32` to `u8` may truncate the value
|
||||||
--> $DIR/cast.rs:261:13
|
--> $DIR/cast.rs:267:13
|
||||||
|
|
|
|
||||||
LL | let c = (q / 1000) as u8;
|
LL | let c = (q / 1000) as u8;
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
@ -328,8 +346,8 @@ LL | let c = (q / 1000) as u8;
|
||||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
help: ... or use `try_from` and handle the error accordingly
|
help: ... or use `try_from` and handle the error accordingly
|
||||||
|
|
|
|
||||||
LL | let c = u8::try_from((q / 1000));
|
LL | let c = u8::try_from(q / 1000);
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: aborting due to 36 previous errors
|
error: aborting due to 41 previous errors
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,7 @@ impl core::ops::Mul<i32> for Vec1 {
|
||||||
|
|
||||||
#[allow(clippy::no_effect)]
|
#[allow(clippy::no_effect)]
|
||||||
#[warn(clippy::erasing_op)]
|
#[warn(clippy::erasing_op)]
|
||||||
fn main() {
|
fn test(x: u8) {
|
||||||
let x: u8 = 0;
|
|
||||||
|
|
||||||
x * 0;
|
x * 0;
|
||||||
0 & x;
|
0 & x;
|
||||||
0 / x;
|
0 / x;
|
||||||
|
@ -41,3 +39,7 @@ fn main() {
|
||||||
0 * Vec1 { x: 5 };
|
0 * Vec1 { x: 5 };
|
||||||
Vec1 { x: 5 } * 0;
|
Vec1 { x: 5 } * 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test(0)
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: this operation will always return zero. This is likely not the intended outcome
|
error: this operation will always return zero. This is likely not the intended outcome
|
||||||
--> $DIR/erasing_op.rs:37:5
|
--> $DIR/erasing_op.rs:35:5
|
||||||
|
|
|
|
||||||
LL | x * 0;
|
LL | x * 0;
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
@ -7,25 +7,25 @@ LL | x * 0;
|
||||||
= note: `-D clippy::erasing-op` implied by `-D warnings`
|
= note: `-D clippy::erasing-op` implied by `-D warnings`
|
||||||
|
|
||||||
error: this operation will always return zero. This is likely not the intended outcome
|
error: this operation will always return zero. This is likely not the intended outcome
|
||||||
--> $DIR/erasing_op.rs:38:5
|
--> $DIR/erasing_op.rs:36:5
|
||||||
|
|
|
|
||||||
LL | 0 & x;
|
LL | 0 & x;
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: this operation will always return zero. This is likely not the intended outcome
|
error: this operation will always return zero. This is likely not the intended outcome
|
||||||
--> $DIR/erasing_op.rs:39:5
|
--> $DIR/erasing_op.rs:37:5
|
||||||
|
|
|
|
||||||
LL | 0 / x;
|
LL | 0 / x;
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: this operation will always return zero. This is likely not the intended outcome
|
error: this operation will always return zero. This is likely not the intended outcome
|
||||||
--> $DIR/erasing_op.rs:41:5
|
--> $DIR/erasing_op.rs:39:5
|
||||||
|
|
|
|
||||||
LL | 0 * Vec1 { x: 5 };
|
LL | 0 * Vec1 { x: 5 };
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this operation will always return zero. This is likely not the intended outcome
|
error: this operation will always return zero. This is likely not the intended outcome
|
||||||
--> $DIR/erasing_op.rs:42:5
|
--> $DIR/erasing_op.rs:40:5
|
||||||
|
|
|
|
||||||
LL | Vec1 { x: 5 } * 0;
|
LL | Vec1 { x: 5 } * 0;
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut i = 1i32;
|
let mut i = 1i32;
|
||||||
let mut var1 = 0i32;
|
let mut var1 = 13i32;
|
||||||
let mut var2 = -1i32;
|
let mut var2 = -1i32;
|
||||||
1 + i;
|
1 + i;
|
||||||
i * 2;
|
i * 2;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![warn(clippy::needless_update)]
|
#![warn(clippy::needless_update)]
|
||||||
#![allow(clippy::no_effect)]
|
#![allow(clippy::no_effect, clippy::unnecessary_struct_initialization)]
|
||||||
|
|
||||||
struct S {
|
struct S {
|
||||||
pub a: i32,
|
pub a: i32,
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
#![feature(box_syntax, fn_traits, unboxed_closures)]
|
#![feature(fn_traits, unboxed_closures)]
|
||||||
#![warn(clippy::no_effect_underscore_binding)]
|
#![warn(clippy::no_effect_underscore_binding)]
|
||||||
#![allow(dead_code, path_statements)]
|
#![allow(dead_code, path_statements)]
|
||||||
#![allow(clippy::deref_addrof, clippy::redundant_field_names, clippy::uninlined_format_args)]
|
#![allow(
|
||||||
|
clippy::deref_addrof,
|
||||||
|
clippy::redundant_field_names,
|
||||||
|
clippy::uninlined_format_args,
|
||||||
|
clippy::unnecessary_struct_initialization
|
||||||
|
)]
|
||||||
|
|
||||||
struct Unit;
|
struct Unit;
|
||||||
struct Tuple(i32);
|
struct Tuple(i32);
|
||||||
|
@ -102,7 +107,6 @@ fn main() {
|
||||||
*&42;
|
*&42;
|
||||||
&6;
|
&6;
|
||||||
(5, 6, 7);
|
(5, 6, 7);
|
||||||
box 42;
|
|
||||||
..;
|
..;
|
||||||
5..;
|
5..;
|
||||||
..5;
|
..5;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:92:5
|
--> $DIR/no_effect.rs:97:5
|
||||||
|
|
|
|
||||||
LL | 0;
|
LL | 0;
|
||||||
| ^^
|
| ^^
|
||||||
|
@ -7,157 +7,151 @@ LL | 0;
|
||||||
= note: `-D clippy::no-effect` implied by `-D warnings`
|
= note: `-D clippy::no-effect` implied by `-D warnings`
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:93:5
|
--> $DIR/no_effect.rs:98:5
|
||||||
|
|
|
|
||||||
LL | s2;
|
LL | s2;
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:94:5
|
--> $DIR/no_effect.rs:99:5
|
||||||
|
|
|
|
||||||
LL | Unit;
|
LL | Unit;
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:95:5
|
--> $DIR/no_effect.rs:100:5
|
||||||
|
|
|
|
||||||
LL | Tuple(0);
|
LL | Tuple(0);
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:96:5
|
--> $DIR/no_effect.rs:101:5
|
||||||
|
|
|
|
||||||
LL | Struct { field: 0 };
|
LL | Struct { field: 0 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:97:5
|
--> $DIR/no_effect.rs:102:5
|
||||||
|
|
|
|
||||||
LL | Struct { ..s };
|
LL | Struct { ..s };
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:98:5
|
--> $DIR/no_effect.rs:103:5
|
||||||
|
|
|
|
||||||
LL | Union { a: 0 };
|
LL | Union { a: 0 };
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:99:5
|
--> $DIR/no_effect.rs:104:5
|
||||||
|
|
|
|
||||||
LL | Enum::Tuple(0);
|
LL | Enum::Tuple(0);
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:100:5
|
--> $DIR/no_effect.rs:105:5
|
||||||
|
|
|
|
||||||
LL | Enum::Struct { field: 0 };
|
LL | Enum::Struct { field: 0 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:101:5
|
--> $DIR/no_effect.rs:106:5
|
||||||
|
|
|
|
||||||
LL | 5 + 6;
|
LL | 5 + 6;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:102:5
|
--> $DIR/no_effect.rs:107:5
|
||||||
|
|
|
|
||||||
LL | *&42;
|
LL | *&42;
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:103:5
|
--> $DIR/no_effect.rs:108:5
|
||||||
|
|
|
|
||||||
LL | &6;
|
LL | &6;
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:104:5
|
--> $DIR/no_effect.rs:109:5
|
||||||
|
|
|
|
||||||
LL | (5, 6, 7);
|
LL | (5, 6, 7);
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:105:5
|
--> $DIR/no_effect.rs:110:5
|
||||||
|
|
|
||||||
LL | box 42;
|
|
||||||
| ^^^^^^^
|
|
||||||
|
|
||||||
error: statement with no effect
|
|
||||||
--> $DIR/no_effect.rs:106:5
|
|
||||||
|
|
|
|
||||||
LL | ..;
|
LL | ..;
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:107:5
|
--> $DIR/no_effect.rs:111:5
|
||||||
|
|
|
|
||||||
LL | 5..;
|
LL | 5..;
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:108:5
|
--> $DIR/no_effect.rs:112:5
|
||||||
|
|
|
|
||||||
LL | ..5;
|
LL | ..5;
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:109:5
|
--> $DIR/no_effect.rs:113:5
|
||||||
|
|
|
|
||||||
LL | 5..6;
|
LL | 5..6;
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:110:5
|
--> $DIR/no_effect.rs:114:5
|
||||||
|
|
|
|
||||||
LL | 5..=6;
|
LL | 5..=6;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:111:5
|
--> $DIR/no_effect.rs:115:5
|
||||||
|
|
|
|
||||||
LL | [42, 55];
|
LL | [42, 55];
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:112:5
|
--> $DIR/no_effect.rs:116:5
|
||||||
|
|
|
|
||||||
LL | [42, 55][1];
|
LL | [42, 55][1];
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:113:5
|
--> $DIR/no_effect.rs:117:5
|
||||||
|
|
|
|
||||||
LL | (42, 55).1;
|
LL | (42, 55).1;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:114:5
|
--> $DIR/no_effect.rs:118:5
|
||||||
|
|
|
|
||||||
LL | [42; 55];
|
LL | [42; 55];
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:115:5
|
--> $DIR/no_effect.rs:119:5
|
||||||
|
|
|
|
||||||
LL | [42; 55][13];
|
LL | [42; 55][13];
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:117:5
|
--> $DIR/no_effect.rs:121:5
|
||||||
|
|
|
|
||||||
LL | || x += 5;
|
LL | || x += 5;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: statement with no effect
|
error: statement with no effect
|
||||||
--> $DIR/no_effect.rs:119:5
|
--> $DIR/no_effect.rs:123:5
|
||||||
|
|
|
|
||||||
LL | FooString { s: s };
|
LL | FooString { s: s };
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: binding to `_` prefixed variable with no side-effect
|
error: binding to `_` prefixed variable with no side-effect
|
||||||
--> $DIR/no_effect.rs:120:5
|
--> $DIR/no_effect.rs:124:5
|
||||||
|
|
|
|
||||||
LL | let _unused = 1;
|
LL | let _unused = 1;
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
@ -165,22 +159,22 @@ LL | let _unused = 1;
|
||||||
= note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings`
|
= note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings`
|
||||||
|
|
||||||
error: binding to `_` prefixed variable with no side-effect
|
error: binding to `_` prefixed variable with no side-effect
|
||||||
--> $DIR/no_effect.rs:121:5
|
--> $DIR/no_effect.rs:125:5
|
||||||
|
|
|
|
||||||
LL | let _penguin = || println!("Some helpful closure");
|
LL | let _penguin = || println!("Some helpful closure");
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: binding to `_` prefixed variable with no side-effect
|
error: binding to `_` prefixed variable with no side-effect
|
||||||
--> $DIR/no_effect.rs:122:5
|
--> $DIR/no_effect.rs:126:5
|
||||||
|
|
|
|
||||||
LL | let _duck = Struct { field: 0 };
|
LL | let _duck = Struct { field: 0 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: binding to `_` prefixed variable with no side-effect
|
error: binding to `_` prefixed variable with no side-effect
|
||||||
--> $DIR/no_effect.rs:123:5
|
--> $DIR/no_effect.rs:127:5
|
||||||
|
|
|
|
||||||
LL | let _cat = [2, 4, 6, 8][2];
|
LL | let _cat = [2, 4, 6, 8][2];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 30 previous errors
|
error: aborting due to 29 previous errors
|
||||||
|
|
||||||
|
|
|
@ -63,3 +63,32 @@ fn issue9428() {
|
||||||
println!("foo");
|
println!("foo");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn issue_10523() {
|
||||||
|
macro_rules! a {
|
||||||
|
($v:expr) => {
|
||||||
|
$v.is_some()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let x: Option<u32> = None;
|
||||||
|
if !a!(x) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn issue_10523_1() {
|
||||||
|
macro_rules! a {
|
||||||
|
($v:expr) => {
|
||||||
|
!$v.is_some()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let x: Option<u32> = None;
|
||||||
|
if a!(x) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn issue_10523_2() {
|
||||||
|
macro_rules! a {
|
||||||
|
() => {
|
||||||
|
!None::<u32>.is_some()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if a!() {}
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#![warn(clippy::overflow_check_conditional)]
|
#![warn(clippy::overflow_check_conditional)]
|
||||||
|
|
||||||
fn main() {
|
fn test(a: u32, b: u32, c: u32) {
|
||||||
let a: u32 = 1;
|
|
||||||
let b: u32 = 2;
|
|
||||||
let c: u32 = 3;
|
|
||||||
if a + b < a {}
|
if a + b < a {}
|
||||||
if a > a + b {}
|
if a > a + b {}
|
||||||
if a + b < b {}
|
if a + b < b {}
|
||||||
|
@ -23,3 +20,7 @@ fn main() {
|
||||||
if i > i + j {}
|
if i > i + j {}
|
||||||
if i - j < i {}
|
if i - j < i {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test(1, 2, 3)
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: you are trying to use classic C overflow conditions that will fail in Rust
|
error: you are trying to use classic C overflow conditions that will fail in Rust
|
||||||
--> $DIR/overflow_check_conditional.rs:7:8
|
--> $DIR/overflow_check_conditional.rs:4:8
|
||||||
|
|
|
|
||||||
LL | if a + b < a {}
|
LL | if a + b < a {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -7,43 +7,43 @@ LL | if a + b < a {}
|
||||||
= note: `-D clippy::overflow-check-conditional` implied by `-D warnings`
|
= note: `-D clippy::overflow-check-conditional` implied by `-D warnings`
|
||||||
|
|
||||||
error: you are trying to use classic C overflow conditions that will fail in Rust
|
error: you are trying to use classic C overflow conditions that will fail in Rust
|
||||||
--> $DIR/overflow_check_conditional.rs:8:8
|
--> $DIR/overflow_check_conditional.rs:5:8
|
||||||
|
|
|
|
||||||
LL | if a > a + b {}
|
LL | if a > a + b {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: you are trying to use classic C overflow conditions that will fail in Rust
|
error: you are trying to use classic C overflow conditions that will fail in Rust
|
||||||
--> $DIR/overflow_check_conditional.rs:9:8
|
--> $DIR/overflow_check_conditional.rs:6:8
|
||||||
|
|
|
|
||||||
LL | if a + b < b {}
|
LL | if a + b < b {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: you are trying to use classic C overflow conditions that will fail in Rust
|
error: you are trying to use classic C overflow conditions that will fail in Rust
|
||||||
--> $DIR/overflow_check_conditional.rs:10:8
|
--> $DIR/overflow_check_conditional.rs:7:8
|
||||||
|
|
|
|
||||||
LL | if b > a + b {}
|
LL | if b > a + b {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: you are trying to use classic C underflow conditions that will fail in Rust
|
error: you are trying to use classic C underflow conditions that will fail in Rust
|
||||||
--> $DIR/overflow_check_conditional.rs:11:8
|
--> $DIR/overflow_check_conditional.rs:8:8
|
||||||
|
|
|
|
||||||
LL | if a - b > b {}
|
LL | if a - b > b {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: you are trying to use classic C underflow conditions that will fail in Rust
|
error: you are trying to use classic C underflow conditions that will fail in Rust
|
||||||
--> $DIR/overflow_check_conditional.rs:12:8
|
--> $DIR/overflow_check_conditional.rs:9:8
|
||||||
|
|
|
|
||||||
LL | if b < a - b {}
|
LL | if b < a - b {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: you are trying to use classic C underflow conditions that will fail in Rust
|
error: you are trying to use classic C underflow conditions that will fail in Rust
|
||||||
--> $DIR/overflow_check_conditional.rs:13:8
|
--> $DIR/overflow_check_conditional.rs:10:8
|
||||||
|
|
|
|
||||||
LL | if a - b > a {}
|
LL | if a - b > a {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: you are trying to use classic C underflow conditions that will fail in Rust
|
error: you are trying to use classic C underflow conditions that will fail in Rust
|
||||||
--> $DIR/overflow_check_conditional.rs:14:8
|
--> $DIR/overflow_check_conditional.rs:11:8
|
||||||
|
|
|
|
||||||
LL | if a < a - b {}
|
LL | if a < a - b {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// would otherwise be responsible for
|
// would otherwise be responsible for
|
||||||
#![warn(clippy::useless_transmute)]
|
#![warn(clippy::useless_transmute)]
|
||||||
#![warn(clippy::transmute_ptr_to_ptr)]
|
#![warn(clippy::transmute_ptr_to_ptr)]
|
||||||
#![allow(dead_code, unused_unsafe, clippy::borrow_as_ptr)]
|
#![allow(unused, clippy::borrow_as_ptr)]
|
||||||
|
|
||||||
use std::mem::{size_of, transmute};
|
use std::mem::{size_of, transmute};
|
||||||
|
|
||||||
|
@ -77,3 +77,9 @@ fn cannot_be_expressed_as_pointer_cast(in_param: Single) -> Pair {
|
||||||
|
|
||||||
unsafe { transmute::<Single, Pair>(in_param) }
|
unsafe { transmute::<Single, Pair>(in_param) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn issue_10449() {
|
||||||
|
fn f() {}
|
||||||
|
|
||||||
|
let _x: u8 = unsafe { *(f as *const u8) };
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// would otherwise be responsible for
|
// would otherwise be responsible for
|
||||||
#![warn(clippy::useless_transmute)]
|
#![warn(clippy::useless_transmute)]
|
||||||
#![warn(clippy::transmute_ptr_to_ptr)]
|
#![warn(clippy::transmute_ptr_to_ptr)]
|
||||||
#![allow(dead_code, unused_unsafe, clippy::borrow_as_ptr)]
|
#![allow(unused, clippy::borrow_as_ptr)]
|
||||||
|
|
||||||
use std::mem::{size_of, transmute};
|
use std::mem::{size_of, transmute};
|
||||||
|
|
||||||
|
@ -77,3 +77,9 @@ fn cannot_be_expressed_as_pointer_cast(in_param: Single) -> Pair {
|
||||||
|
|
||||||
unsafe { transmute::<Single, Pair>(in_param) }
|
unsafe { transmute::<Single, Pair>(in_param) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn issue_10449() {
|
||||||
|
fn f() {}
|
||||||
|
|
||||||
|
let _x: u8 = unsafe { *std::mem::transmute::<fn(), *const u8>(f) };
|
||||||
|
}
|
||||||
|
|
|
@ -58,5 +58,11 @@ error: transmute from a reference to a pointer
|
||||||
LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) }
|
LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8`
|
||||||
|
|
||||||
error: aborting due to 9 previous errors
|
error: transmute from `fn()` to `*const u8` which could be expressed as a pointer cast instead
|
||||||
|
--> $DIR/transmutes_expressible_as_ptr_casts.rs:84:28
|
||||||
|
|
|
||||||
|
LL | let _x: u8 = unsafe { *std::mem::transmute::<fn(), *const u8>(f) };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(f as *const u8)`
|
||||||
|
|
||||||
|
error: aborting due to 10 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
#![feature(box_syntax)]
|
#![allow(
|
||||||
#![allow(clippy::deref_addrof, dead_code, unused, clippy::no_effect)]
|
clippy::deref_addrof,
|
||||||
|
dead_code,
|
||||||
|
unused,
|
||||||
|
clippy::no_effect,
|
||||||
|
clippy::unnecessary_struct_initialization
|
||||||
|
)]
|
||||||
#![warn(clippy::unnecessary_operation)]
|
#![warn(clippy::unnecessary_operation)]
|
||||||
|
|
||||||
struct Tuple(i32);
|
struct Tuple(i32);
|
||||||
|
@ -59,7 +64,6 @@ fn main() {
|
||||||
5;6;get_number();
|
5;6;get_number();
|
||||||
get_number();
|
get_number();
|
||||||
get_number();
|
get_number();
|
||||||
get_number();
|
|
||||||
5;get_number();
|
5;get_number();
|
||||||
42;get_number();
|
42;get_number();
|
||||||
assert!([42, 55].len() > get_usize());
|
assert!([42, 55].len() > get_usize());
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
#![feature(box_syntax)]
|
#![allow(
|
||||||
#![allow(clippy::deref_addrof, dead_code, unused, clippy::no_effect)]
|
clippy::deref_addrof,
|
||||||
|
dead_code,
|
||||||
|
unused,
|
||||||
|
clippy::no_effect,
|
||||||
|
clippy::unnecessary_struct_initialization
|
||||||
|
)]
|
||||||
#![warn(clippy::unnecessary_operation)]
|
#![warn(clippy::unnecessary_operation)]
|
||||||
|
|
||||||
struct Tuple(i32);
|
struct Tuple(i32);
|
||||||
|
@ -57,7 +62,6 @@ fn main() {
|
||||||
*&get_number();
|
*&get_number();
|
||||||
&get_number();
|
&get_number();
|
||||||
(5, 6, get_number());
|
(5, 6, get_number());
|
||||||
box get_number();
|
|
||||||
get_number()..;
|
get_number()..;
|
||||||
..get_number();
|
..get_number();
|
||||||
5..get_number();
|
5..get_number();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:51:5
|
--> $DIR/unnecessary_operation.rs:56:5
|
||||||
|
|
|
|
||||||
LL | Tuple(get_number());
|
LL | Tuple(get_number());
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
| ^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
||||||
|
@ -7,109 +7,103 @@ LL | Tuple(get_number());
|
||||||
= note: `-D clippy::unnecessary-operation` implied by `-D warnings`
|
= note: `-D clippy::unnecessary-operation` implied by `-D warnings`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:52:5
|
--> $DIR/unnecessary_operation.rs:57:5
|
||||||
|
|
|
|
||||||
LL | Struct { field: get_number() };
|
LL | Struct { field: get_number() };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:53:5
|
--> $DIR/unnecessary_operation.rs:58:5
|
||||||
|
|
|
|
||||||
LL | Struct { ..get_struct() };
|
LL | Struct { ..get_struct() };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_struct();`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_struct();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:54:5
|
--> $DIR/unnecessary_operation.rs:59:5
|
||||||
|
|
|
|
||||||
LL | Enum::Tuple(get_number());
|
LL | Enum::Tuple(get_number());
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:55:5
|
--> $DIR/unnecessary_operation.rs:60:5
|
||||||
|
|
|
|
||||||
LL | Enum::Struct { field: get_number() };
|
LL | Enum::Struct { field: get_number() };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:56:5
|
--> $DIR/unnecessary_operation.rs:61:5
|
||||||
|
|
|
|
||||||
LL | 5 + get_number();
|
LL | 5 + get_number();
|
||||||
| ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
|
| ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:57:5
|
--> $DIR/unnecessary_operation.rs:62:5
|
||||||
|
|
|
|
||||||
LL | *&get_number();
|
LL | *&get_number();
|
||||||
| ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
| ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:58:5
|
--> $DIR/unnecessary_operation.rs:63:5
|
||||||
|
|
|
|
||||||
LL | &get_number();
|
LL | &get_number();
|
||||||
| ^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
| ^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:59:5
|
--> $DIR/unnecessary_operation.rs:64:5
|
||||||
|
|
|
|
||||||
LL | (5, 6, get_number());
|
LL | (5, 6, get_number());
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;6;get_number();`
|
| ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;6;get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:60:5
|
--> $DIR/unnecessary_operation.rs:65:5
|
||||||
|
|
|
||||||
LL | box get_number();
|
|
||||||
| ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
|
||||||
|
|
||||||
error: unnecessary operation
|
|
||||||
--> $DIR/unnecessary_operation.rs:61:5
|
|
||||||
|
|
|
|
||||||
LL | get_number()..;
|
LL | get_number()..;
|
||||||
| ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
| ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:62:5
|
--> $DIR/unnecessary_operation.rs:66:5
|
||||||
|
|
|
|
||||||
LL | ..get_number();
|
LL | ..get_number();
|
||||||
| ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
| ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:63:5
|
--> $DIR/unnecessary_operation.rs:67:5
|
||||||
|
|
|
|
||||||
LL | 5..get_number();
|
LL | 5..get_number();
|
||||||
| ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
|
| ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:64:5
|
--> $DIR/unnecessary_operation.rs:68:5
|
||||||
|
|
|
|
||||||
LL | [42, get_number()];
|
LL | [42, get_number()];
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
|
| ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:65:5
|
--> $DIR/unnecessary_operation.rs:69:5
|
||||||
|
|
|
|
||||||
LL | [42, 55][get_usize()];
|
LL | [42, 55][get_usize()];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());`
|
| ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:66:5
|
--> $DIR/unnecessary_operation.rs:70:5
|
||||||
|
|
|
|
||||||
LL | (42, get_number()).1;
|
LL | (42, get_number()).1;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
|
| ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:67:5
|
--> $DIR/unnecessary_operation.rs:71:5
|
||||||
|
|
|
|
||||||
LL | [get_number(); 55];
|
LL | [get_number(); 55];
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
| ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:68:5
|
--> $DIR/unnecessary_operation.rs:72:5
|
||||||
|
|
|
|
||||||
LL | [42; 55][get_usize()];
|
LL | [42; 55][get_usize()];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42; 55].len() > get_usize());`
|
| ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42; 55].len() > get_usize());`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:69:5
|
--> $DIR/unnecessary_operation.rs:73:5
|
||||||
|
|
|
|
||||||
LL | / {
|
LL | / {
|
||||||
LL | | get_number()
|
LL | | get_number()
|
||||||
|
@ -117,12 +111,12 @@ LL | | };
|
||||||
| |______^ help: statement can be reduced to: `get_number();`
|
| |______^ help: statement can be reduced to: `get_number();`
|
||||||
|
|
||||||
error: unnecessary operation
|
error: unnecessary operation
|
||||||
--> $DIR/unnecessary_operation.rs:72:5
|
--> $DIR/unnecessary_operation.rs:76:5
|
||||||
|
|
|
|
||||||
LL | / FooString {
|
LL | / FooString {
|
||||||
LL | | s: String::from("blah"),
|
LL | | s: String::from("blah"),
|
||||||
LL | | };
|
LL | | };
|
||||||
| |______^ help: statement can be reduced to: `String::from("blah");`
|
| |______^ help: statement can be reduced to: `String::from("blah");`
|
||||||
|
|
||||||
error: aborting due to 20 previous errors
|
error: aborting due to 19 previous errors
|
||||||
|
|
||||||
|
|
73
tests/ui/unnecessary_struct_initialization.fixed
Normal file
73
tests/ui/unnecessary_struct_initialization.fixed
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![allow(unused)]
|
||||||
|
#![warn(clippy::unnecessary_struct_initialization)]
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
f: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct T {
|
||||||
|
f: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct U {
|
||||||
|
f: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for U {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
// Do not lint: `Self` does not implement `Copy`
|
||||||
|
Self { ..*self }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy)]
|
||||||
|
struct V {
|
||||||
|
f: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for V {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
// Lint: `Self` implements `Copy`
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Should lint: `a` would be consumed anyway
|
||||||
|
let a = S { f: String::from("foo") };
|
||||||
|
let mut b = a;
|
||||||
|
|
||||||
|
// Should lint: `b` would be consumed, and is mutable
|
||||||
|
let c = &mut b;
|
||||||
|
|
||||||
|
// Should not lint as `d` is not mutable
|
||||||
|
let d = S { f: String::from("foo") };
|
||||||
|
let e = &mut S { ..d };
|
||||||
|
|
||||||
|
// Should lint as `f` would be consumed anyway
|
||||||
|
let f = S { f: String::from("foo") };
|
||||||
|
let g = &f;
|
||||||
|
|
||||||
|
// Should lint: the result of an expression is mutable
|
||||||
|
let h = &mut *Box::new(S { f: String::from("foo") });
|
||||||
|
|
||||||
|
// Should not lint: `m` would be both alive and borrowed
|
||||||
|
let m = T { f: 17 };
|
||||||
|
let n = &T { ..m };
|
||||||
|
|
||||||
|
// Should not lint: `m` should not be modified
|
||||||
|
let o = &mut T { ..m };
|
||||||
|
o.f = 32;
|
||||||
|
assert_eq!(m.f, 17);
|
||||||
|
|
||||||
|
// Should not lint: `m` should not be modified
|
||||||
|
let o = &mut T { ..m } as *mut T;
|
||||||
|
unsafe { &mut *o }.f = 32;
|
||||||
|
assert_eq!(m.f, 17);
|
||||||
|
|
||||||
|
// Should lint: the result of an expression is mutable and temporary
|
||||||
|
let p = &mut *Box::new(T { f: 5 });
|
||||||
|
}
|
77
tests/ui/unnecessary_struct_initialization.rs
Normal file
77
tests/ui/unnecessary_struct_initialization.rs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![allow(unused)]
|
||||||
|
#![warn(clippy::unnecessary_struct_initialization)]
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
f: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct T {
|
||||||
|
f: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct U {
|
||||||
|
f: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for U {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
// Do not lint: `Self` does not implement `Copy`
|
||||||
|
Self { ..*self }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy)]
|
||||||
|
struct V {
|
||||||
|
f: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for V {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
// Lint: `Self` implements `Copy`
|
||||||
|
Self { ..*self }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Should lint: `a` would be consumed anyway
|
||||||
|
let a = S { f: String::from("foo") };
|
||||||
|
let mut b = S { ..a };
|
||||||
|
|
||||||
|
// Should lint: `b` would be consumed, and is mutable
|
||||||
|
let c = &mut S { ..b };
|
||||||
|
|
||||||
|
// Should not lint as `d` is not mutable
|
||||||
|
let d = S { f: String::from("foo") };
|
||||||
|
let e = &mut S { ..d };
|
||||||
|
|
||||||
|
// Should lint as `f` would be consumed anyway
|
||||||
|
let f = S { f: String::from("foo") };
|
||||||
|
let g = &S { ..f };
|
||||||
|
|
||||||
|
// Should lint: the result of an expression is mutable
|
||||||
|
let h = &mut S {
|
||||||
|
..*Box::new(S { f: String::from("foo") })
|
||||||
|
};
|
||||||
|
|
||||||
|
// Should not lint: `m` would be both alive and borrowed
|
||||||
|
let m = T { f: 17 };
|
||||||
|
let n = &T { ..m };
|
||||||
|
|
||||||
|
// Should not lint: `m` should not be modified
|
||||||
|
let o = &mut T { ..m };
|
||||||
|
o.f = 32;
|
||||||
|
assert_eq!(m.f, 17);
|
||||||
|
|
||||||
|
// Should not lint: `m` should not be modified
|
||||||
|
let o = &mut T { ..m } as *mut T;
|
||||||
|
unsafe { &mut *o }.f = 32;
|
||||||
|
assert_eq!(m.f, 17);
|
||||||
|
|
||||||
|
// Should lint: the result of an expression is mutable and temporary
|
||||||
|
let p = &mut T {
|
||||||
|
..*Box::new(T { f: 5 })
|
||||||
|
};
|
||||||
|
}
|
46
tests/ui/unnecessary_struct_initialization.stderr
Normal file
46
tests/ui/unnecessary_struct_initialization.stderr
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
error: unnecessary struct building
|
||||||
|
--> $DIR/unnecessary_struct_initialization.rs:34:9
|
||||||
|
|
|
||||||
|
LL | Self { ..*self }
|
||||||
|
| ^^^^^^^^^^^^^^^^ help: replace with: `*self`
|
||||||
|
|
|
||||||
|
= note: `-D clippy::unnecessary-struct-initialization` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: unnecessary struct building
|
||||||
|
--> $DIR/unnecessary_struct_initialization.rs:41:17
|
||||||
|
|
|
||||||
|
LL | let mut b = S { ..a };
|
||||||
|
| ^^^^^^^^^ help: replace with: `a`
|
||||||
|
|
||||||
|
error: unnecessary struct building
|
||||||
|
--> $DIR/unnecessary_struct_initialization.rs:44:18
|
||||||
|
|
|
||||||
|
LL | let c = &mut S { ..b };
|
||||||
|
| ^^^^^^^^^ help: replace with: `b`
|
||||||
|
|
||||||
|
error: unnecessary struct building
|
||||||
|
--> $DIR/unnecessary_struct_initialization.rs:52:14
|
||||||
|
|
|
||||||
|
LL | let g = &S { ..f };
|
||||||
|
| ^^^^^^^^^ help: replace with: `f`
|
||||||
|
|
||||||
|
error: unnecessary struct building
|
||||||
|
--> $DIR/unnecessary_struct_initialization.rs:55:18
|
||||||
|
|
|
||||||
|
LL | let h = &mut S {
|
||||||
|
| __________________^
|
||||||
|
LL | | ..*Box::new(S { f: String::from("foo") })
|
||||||
|
LL | | };
|
||||||
|
| |_____^ help: replace with: `*Box::new(S { f: String::from("foo") })`
|
||||||
|
|
||||||
|
error: unnecessary struct building
|
||||||
|
--> $DIR/unnecessary_struct_initialization.rs:74:18
|
||||||
|
|
|
||||||
|
LL | let p = &mut T {
|
||||||
|
| __________________^
|
||||||
|
LL | | ..*Box::new(T { f: 5 })
|
||||||
|
LL | | };
|
||||||
|
| |_____^ help: replace with: `*Box::new(T { f: 5 })`
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
Loading…
Reference in a new issue