Merge commit '7248d06384c6a90de58c04c1f46be88821278d8b' into sync-from-clippy
This commit is contained in:
@@ -3800,6 +3800,7 @@ Released 2018-09-13
|
|||||||
[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
|
[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
|
||||||
[`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect
|
[`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect
|
||||||
[`iter_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_count
|
[`iter_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_count
|
||||||
|
[`iter_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map
|
||||||
[`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop
|
[`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop
|
||||||
[`iter_next_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_slice
|
[`iter_next_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_slice
|
||||||
[`iter_not_returning_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_not_returning_iterator
|
[`iter_not_returning_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_not_returning_iterator
|
||||||
|
|||||||
@@ -110,23 +110,28 @@ Just make sure to remove the dependencies again before finally making a pull req
|
|||||||
[IntelliJ_rust_homepage]: https://intellij-rust.github.io/
|
[IntelliJ_rust_homepage]: https://intellij-rust.github.io/
|
||||||
|
|
||||||
### Rust Analyzer
|
### Rust Analyzer
|
||||||
As of [#6869][6869], [`rust-analyzer`][ra_homepage] can understand that Clippy uses compiler-internals
|
For [`rust-analyzer`][ra_homepage] to work correctly make sure that in the `rust-analyzer` configuration you set
|
||||||
using `extern crate` when `package.metadata.rust-analyzer.rustc_private` is set to `true` in Clippy's `Cargo.toml.`
|
|
||||||
You will require a `nightly` toolchain with the `rustc-dev` component installed.
|
|
||||||
Make sure that in the `rust-analyzer` configuration, you set
|
|
||||||
```json
|
```json
|
||||||
{ "rust-analyzer.rustc.source": "discover" }
|
{ "rust-analyzer.rustc.source": "discover" }
|
||||||
```
|
```
|
||||||
and
|
|
||||||
```json
|
|
||||||
{ "rust-analyzer.updates.channel": "nightly" }
|
|
||||||
```
|
|
||||||
You should be able to see information on things like `Expr` or `EarlyContext` now if you hover them, also
|
You should be able to see information on things like `Expr` or `EarlyContext` now if you hover them, also
|
||||||
a lot more type hints.
|
a lot more type hints.
|
||||||
This will work with `rust-analyzer 2021-03-15` shipped in nightly `1.52.0-nightly (107896c32 2021-03-15)` or later.
|
|
||||||
|
To have `rust-analyzer` also work in the `clippy_dev` and `lintcheck` crates, add the following configuration
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"rust-analyzer.linkedProjects": [
|
||||||
|
"./Cargo.toml",
|
||||||
|
"clippy_dev/Cargo.toml",
|
||||||
|
"lintcheck/Cargo.toml",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
[ra_homepage]: https://rust-analyzer.github.io/
|
[ra_homepage]: https://rust-analyzer.github.io/
|
||||||
[6869]: https://github.com/rust-lang/rust-clippy/pull/6869
|
|
||||||
|
|
||||||
## How Clippy works
|
## How Clippy works
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ We start by opening the test file created at `tests/ui/foo_functions.rs`.
|
|||||||
Update the file with some examples to get started:
|
Update the file with some examples to get started:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
#![allow(unused)]
|
||||||
#![warn(clippy::foo_functions)]
|
#![warn(clippy::foo_functions)]
|
||||||
|
|
||||||
// Impl methods
|
// Impl methods
|
||||||
|
|||||||
@@ -123,7 +123,8 @@ There are three ways to do this, depending on if the target trait has a
|
|||||||
diagnostic item, lang item or neither.
|
diagnostic item, lang item or neither.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use clippy_utils::{implements_trait, is_trait_method, match_trait_method, paths};
|
use clippy_utils::ty::implements_trait;
|
||||||
|
use clippy_utils::is_trait_method;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
impl LateLintPass<'_> for MyStructLint {
|
impl LateLintPass<'_> for MyStructLint {
|
||||||
@@ -143,13 +144,6 @@ impl LateLintPass<'_> for MyStructLint {
|
|||||||
.map_or(false, |id| implements_trait(cx, ty, id, &[])) {
|
.map_or(false, |id| implements_trait(cx, ty, id, &[])) {
|
||||||
// `expr` implements `Drop` trait
|
// `expr` implements `Drop` trait
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Using the type path with the expression
|
|
||||||
// we use `match_trait_method` function from Clippy's utils
|
|
||||||
// (This method should be avoided if possible)
|
|
||||||
if match_trait_method(cx, expr, &paths::INTO) {
|
|
||||||
// `expr` implements `Into` trait
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -233,8 +227,9 @@ functions to deal with macros:
|
|||||||
crates
|
crates
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#[macro_use]
|
use rustc_middle::lint::in_external_macro;
|
||||||
extern crate a_crate_with_macros;
|
|
||||||
|
use a_crate_with_macros::foo;
|
||||||
|
|
||||||
// `foo` is defined in `a_crate_with_macros`
|
// `foo` is defined in `a_crate_with_macros`
|
||||||
foo!("bar");
|
foo!("bar");
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ pub(crate) fn get_stabilization_version() -> String {
|
|||||||
fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String {
|
fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String {
|
||||||
let mut contents = format!(
|
let mut contents = format!(
|
||||||
indoc! {"
|
indoc! {"
|
||||||
|
#![allow(unused)]
|
||||||
#![warn(clippy::{})]
|
#![warn(clippy::{})]
|
||||||
|
|
||||||
fn main() {{
|
fn main() {{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use clippy_utils::{meets_msrv, msrvs};
|
|||||||
use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
|
use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||||
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_semver::RustcVersion;
|
use rustc_semver::RustcVersion;
|
||||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@@ -79,6 +80,7 @@ fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg
|
|||||||
(LitKind::Byte(b'a') | LitKind::Char('a'), LitKind::Byte(b'z') | LitKind::Char('z'))
|
(LitKind::Byte(b'a') | LitKind::Char('a'), LitKind::Byte(b'z') | LitKind::Char('z'))
|
||||||
| (LitKind::Byte(b'A') | LitKind::Char('A'), LitKind::Byte(b'Z') | LitKind::Char('Z'))
|
| (LitKind::Byte(b'A') | LitKind::Char('A'), LitKind::Byte(b'Z') | LitKind::Char('Z'))
|
||||||
)
|
)
|
||||||
|
&& !in_external_macro(cx.sess(), span)
|
||||||
{
|
{
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
|
use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
|
||||||
use clippy_utils::path_res;
|
|
||||||
use clippy_utils::source::snippet_with_context;
|
use clippy_utils::source::snippet_with_context;
|
||||||
use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item};
|
use clippy_utils::ty::{has_debug_impl, is_copy, is_type_diagnostic_item};
|
||||||
use clippy_utils::usage::local_used_after_expr;
|
use clippy_utils::usage::local_used_after_expr;
|
||||||
|
use clippy_utils::{is_expr_final_block_expr, path_res};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::{Expr, ExprKind};
|
use rustc_hir::{Expr, ExprKind};
|
||||||
@@ -58,6 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let semicolon = if is_expr_final_block_expr(cx.tcx, e) {";"} else {""};
|
||||||
let mut app = Applicability::MachineApplicable;
|
let mut app = Applicability::MachineApplicable;
|
||||||
match method_segment.ident.as_str() {
|
match method_segment.ident.as_str() {
|
||||||
"is_ok" if type_suitable_to_unwrap(cx, substs.type_at(1)) => {
|
"is_ok" if type_suitable_to_unwrap(cx, substs.type_at(1)) => {
|
||||||
@@ -68,8 +69,9 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
|
|||||||
"called `assert!` with `Result::is_ok`",
|
"called `assert!` with `Result::is_ok`",
|
||||||
"replace with",
|
"replace with",
|
||||||
format!(
|
format!(
|
||||||
"{}.unwrap()",
|
"{}.unwrap(){}",
|
||||||
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
|
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0,
|
||||||
|
semicolon
|
||||||
),
|
),
|
||||||
app,
|
app,
|
||||||
);
|
);
|
||||||
@@ -82,8 +84,9 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
|
|||||||
"called `assert!` with `Result::is_err`",
|
"called `assert!` with `Result::is_err`",
|
||||||
"replace with",
|
"replace with",
|
||||||
format!(
|
format!(
|
||||||
"{}.unwrap_err()",
|
"{}.unwrap_err(){}",
|
||||||
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
|
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0,
|
||||||
|
semicolon
|
||||||
),
|
),
|
||||||
app,
|
app,
|
||||||
);
|
);
|
||||||
@@ -94,13 +97,6 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This checks whether a given type is known to implement Debug.
|
|
||||||
fn has_debug_impl<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
|
||||||
cx.tcx
|
|
||||||
.get_diagnostic_item(sym::Debug)
|
|
||||||
.map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn type_suitable_to_unwrap<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
fn type_suitable_to_unwrap<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
has_debug_impl(cx, ty) && !ty.is_unit() && !ty.is_never()
|
has_debug_impl(cx, ty) && !ty.is_unit() && !ty.is_never()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use rustc_ast::{ExprPrecedence, LitKind};
|
use rustc_ast::LitKind;
|
||||||
use rustc_hir::{Block, ExprKind};
|
use rustc_hir::{Block, ExprKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
|
||||||
use clippy_utils::{diagnostics::span_lint_and_then, is_else_clause, source::snippet_block_with_applicability};
|
use clippy_utils::{diagnostics::span_lint_and_then, is_else_clause, sugg::Sugg};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
@@ -55,27 +55,42 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx
|
|||||||
if let ExprKind::If(check, then, Some(else_)) = expr.kind
|
if let ExprKind::If(check, then, Some(else_)) = expr.kind
|
||||||
&& let Some(then_lit) = int_literal(then)
|
&& let Some(then_lit) = int_literal(then)
|
||||||
&& let Some(else_lit) = int_literal(else_)
|
&& let Some(else_lit) = int_literal(else_)
|
||||||
&& check_int_literal_equals_val(then_lit, 1)
|
|
||||||
&& check_int_literal_equals_val(else_lit, 0)
|
|
||||||
{
|
{
|
||||||
|
let inverted = if
|
||||||
|
check_int_literal_equals_val(then_lit, 1)
|
||||||
|
&& check_int_literal_equals_val(else_lit, 0) {
|
||||||
|
false
|
||||||
|
} else if
|
||||||
|
check_int_literal_equals_val(then_lit, 0)
|
||||||
|
&& check_int_literal_equals_val(else_lit, 1) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
// Expression isn't boolean, exit
|
||||||
|
return;
|
||||||
|
};
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let snippet = snippet_block_with_applicability(ctx, check.span, "..", None, &mut applicability);
|
let snippet = {
|
||||||
let snippet_with_braces = {
|
let mut sugg = Sugg::hir_with_applicability(ctx, check, "..", &mut applicability);
|
||||||
let need_parens = should_have_parentheses(check);
|
if inverted {
|
||||||
let (left_paren, right_paren) = if need_parens {("(", ")")} else {("", "")};
|
sugg = !sugg;
|
||||||
format!("{left_paren}{snippet}{right_paren}")
|
}
|
||||||
|
sugg
|
||||||
};
|
};
|
||||||
|
|
||||||
let ty = ctx.typeck_results().expr_ty(then_lit); // then and else must be of same type
|
let ty = ctx.typeck_results().expr_ty(then_lit); // then and else must be of same type
|
||||||
|
|
||||||
let suggestion = {
|
let suggestion = {
|
||||||
let wrap_in_curly = is_else_clause(ctx.tcx, expr);
|
let wrap_in_curly = is_else_clause(ctx.tcx, expr);
|
||||||
let (left_curly, right_curly) = if wrap_in_curly {("{", "}")} else {("", "")};
|
let mut s = Sugg::NonParen(format!("{ty}::from({snippet})").into());
|
||||||
format!(
|
if wrap_in_curly {
|
||||||
"{left_curly}{ty}::from({snippet}){right_curly}"
|
s = s.blockify();
|
||||||
)
|
}
|
||||||
|
s
|
||||||
}; // when used in else clause if statement should be wrapped in curly braces
|
}; // when used in else clause if statement should be wrapped in curly braces
|
||||||
|
|
||||||
|
let into_snippet = snippet.clone().maybe_par();
|
||||||
|
let as_snippet = snippet.as_ty(ty);
|
||||||
|
|
||||||
span_lint_and_then(ctx,
|
span_lint_and_then(ctx,
|
||||||
BOOL_TO_INT_WITH_IF,
|
BOOL_TO_INT_WITH_IF,
|
||||||
expr.span,
|
expr.span,
|
||||||
@@ -87,7 +102,7 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx
|
|||||||
suggestion,
|
suggestion,
|
||||||
applicability,
|
applicability,
|
||||||
);
|
);
|
||||||
diag.note(format!("`{snippet_with_braces} as {ty}` or `{snippet_with_braces}.into()` can also be valid options"));
|
diag.note(format!("`{as_snippet}` or `{into_snippet}.into()` can also be valid options"));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -119,7 +134,3 @@ fn check_int_literal_equals_val<'tcx>(expr: &'tcx rustc_hir::Expr<'tcx>, expecte
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_have_parentheses<'tcx>(check: &'tcx rustc_hir::Expr<'tcx>) -> bool {
|
|
||||||
check.precedence().order() < ExprPrecedence::Cast.order()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
&Term(n) => {
|
&Term(n) => {
|
||||||
let snip = snippet_opt(self.cx, self.terminals[n as usize].span)?;
|
let snip = snippet_opt(self.cx, self.terminals[n as usize].span.source_callsite())?;
|
||||||
self.output.push_str(&snip);
|
self.output.push_str(&snip);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -297,13 +297,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
|
|||||||
if !is_lint_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
|
if !is_lint_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
|
||||||
&& position.lint_explicit_deref() =>
|
&& position.lint_explicit_deref() =>
|
||||||
{
|
{
|
||||||
|
let ty_changed_count = usize::from(!deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)));
|
||||||
self.state = Some((
|
self.state = Some((
|
||||||
State::DerefMethod {
|
State::DerefMethod {
|
||||||
ty_changed_count: if deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)) {
|
ty_changed_count,
|
||||||
0
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
},
|
|
||||||
is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
|
is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
|
||||||
target_mut,
|
target_mut,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_help;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::{is_default_equivalent, peel_blocks};
|
use clippy_utils::{is_default_equivalent, peel_blocks};
|
||||||
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
def::{DefKind, Res},
|
def::{DefKind, Res},
|
||||||
Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
|
Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
|
||||||
@@ -100,15 +101,28 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
|
|||||||
ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
|
ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if should_emit {
|
if should_emit {
|
||||||
let path_string = cx.tcx.def_path_str(adt_def.did());
|
let struct_span = cx.tcx.def_span(adt_def.did());
|
||||||
span_lint_and_help(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
DERIVABLE_IMPLS,
|
DERIVABLE_IMPLS,
|
||||||
item.span,
|
item.span,
|
||||||
"this `impl` can be derived",
|
"this `impl` can be derived",
|
||||||
None,
|
|diag| {
|
||||||
&format!("try annotating `{}` with `#[derive(Default)]`", path_string),
|
diag.span_suggestion_hidden(
|
||||||
|
item.span,
|
||||||
|
"remove the manual implementation...",
|
||||||
|
String::new(),
|
||||||
|
Applicability::MachineApplicable
|
||||||
|
);
|
||||||
|
diag.span_suggestion(
|
||||||
|
struct_span.shrink_to_lo(),
|
||||||
|
"...and instead derive it",
|
||||||
|
"#[derive(Default)]\n".to_string(),
|
||||||
|
Applicability::MachineApplicable
|
||||||
|
);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,12 +71,12 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
|
|||||||
let value = arg.param.value;
|
let value = arg.param.value;
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if format_args.format_string.parts == [kw::Empty];
|
if format_args.format_string.parts == [kw::Empty];
|
||||||
|
if arg.format.is_default();
|
||||||
if match cx.typeck_results().expr_ty(value).peel_refs().kind() {
|
if match cx.typeck_results().expr_ty(value).peel_refs().kind() {
|
||||||
ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(sym::String, adt.did()),
|
ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(sym::String, adt.did()),
|
||||||
ty::Str => true,
|
ty::Str => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if !arg.format.has_string_formatting();
|
|
||||||
then {
|
then {
|
||||||
let is_new_string = match value.kind {
|
let is_new_string = match value.kind {
|
||||||
ExprKind::Binary(..) => true,
|
ExprKind::Binary(..) => true,
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs {
|
|||||||
if let ExpnKind::Macro(_, name) = outermost_expn_data.kind;
|
if let ExpnKind::Macro(_, name) = outermost_expn_data.kind;
|
||||||
then {
|
then {
|
||||||
for arg in &format_args.args {
|
for arg in &format_args.args {
|
||||||
if arg.format.has_string_formatting() {
|
if !arg.format.is_default() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if is_aliased(&format_args, arg.param.value.hir_id) {
|
if is_aliased(&format_args, arg.param.value.hir_id) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_help;
|
use clippy_utils::diagnostics::span_lint_and_help;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use if_chain::if_chain;
|
use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
|
||||||
use rustc_hir::{Expr, ExprKind};
|
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::layout::LayoutOf;
|
use rustc_middle::ty::layout::LayoutOf;
|
||||||
use rustc_middle::ty::{self, ConstKind};
|
use rustc_middle::ty::{self, ConstKind};
|
||||||
@@ -39,29 +38,28 @@ impl_lint_pass!(LargeStackArrays => [LARGE_STACK_ARRAYS]);
|
|||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
|
impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||||
if_chain! {
|
if let ExprKind::Repeat(_, _) = expr.kind
|
||||||
if let ExprKind::Repeat(_, _) = expr.kind;
|
&& let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind()
|
||||||
if let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind();
|
&& let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind()
|
||||||
if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
|
&& let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx)
|
||||||
if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
|
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
|
||||||
if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
|
&& !cx.tcx.hir().parent_iter(expr.hir_id)
|
||||||
if self.maximum_allowed_size < element_count * element_size;
|
.any(|(_, node)| matches!(node, Node::Item(Item { kind: ItemKind::Static(..), .. })))
|
||||||
then {
|
&& self.maximum_allowed_size < element_count * element_size {
|
||||||
span_lint_and_help(
|
span_lint_and_help(
|
||||||
cx,
|
cx,
|
||||||
LARGE_STACK_ARRAYS,
|
LARGE_STACK_ARRAYS,
|
||||||
expr.span,
|
expr.span,
|
||||||
&format!(
|
&format!(
|
||||||
"allocating a local array larger than {} bytes",
|
"allocating a local array larger than {} bytes",
|
||||||
self.maximum_allowed_size
|
self.maximum_allowed_size
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
&format!(
|
&format!(
|
||||||
"consider allocating on the heap with `vec!{}.into_boxed_slice()`",
|
"consider allocating on the heap with `vec!{}.into_boxed_slice()`",
|
||||||
snippet(cx, expr.span, "[...]")
|
snippet(cx, expr.span, "[...]")
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
|
|||||||
LintId::of(methods::ITERATOR_STEP_BY_ZERO),
|
LintId::of(methods::ITERATOR_STEP_BY_ZERO),
|
||||||
LintId::of(methods::ITER_CLONED_COLLECT),
|
LintId::of(methods::ITER_CLONED_COLLECT),
|
||||||
LintId::of(methods::ITER_COUNT),
|
LintId::of(methods::ITER_COUNT),
|
||||||
|
LintId::of(methods::ITER_KV_MAP),
|
||||||
LintId::of(methods::ITER_NEXT_SLICE),
|
LintId::of(methods::ITER_NEXT_SLICE),
|
||||||
LintId::of(methods::ITER_NTH),
|
LintId::of(methods::ITER_NTH),
|
||||||
LintId::of(methods::ITER_NTH_ZERO),
|
LintId::of(methods::ITER_NTH_ZERO),
|
||||||
@@ -351,7 +352,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
|
|||||||
LintId::of(useless_conversion::USELESS_CONVERSION),
|
LintId::of(useless_conversion::USELESS_CONVERSION),
|
||||||
LintId::of(vec::USELESS_VEC),
|
LintId::of(vec::USELESS_VEC),
|
||||||
LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
|
LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
|
||||||
LintId::of(write::POSITIONAL_NAMED_FORMAT_PARAMETERS),
|
|
||||||
LintId::of(write::PRINTLN_EMPTY_STRING),
|
LintId::of(write::PRINTLN_EMPTY_STRING),
|
||||||
LintId::of(write::PRINT_LITERAL),
|
LintId::of(write::PRINT_LITERAL),
|
||||||
LintId::of(write::PRINT_WITH_NEWLINE),
|
LintId::of(write::PRINT_WITH_NEWLINE),
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec!
|
|||||||
LintId::of(methods::GET_LAST_WITH_LEN),
|
LintId::of(methods::GET_LAST_WITH_LEN),
|
||||||
LintId::of(methods::INSPECT_FOR_EACH),
|
LintId::of(methods::INSPECT_FOR_EACH),
|
||||||
LintId::of(methods::ITER_COUNT),
|
LintId::of(methods::ITER_COUNT),
|
||||||
|
LintId::of(methods::ITER_KV_MAP),
|
||||||
LintId::of(methods::MANUAL_FILTER_MAP),
|
LintId::of(methods::MANUAL_FILTER_MAP),
|
||||||
LintId::of(methods::MANUAL_FIND_MAP),
|
LintId::of(methods::MANUAL_FIND_MAP),
|
||||||
LintId::of(methods::MANUAL_SPLIT_ONCE),
|
LintId::of(methods::MANUAL_SPLIT_ONCE),
|
||||||
|
|||||||
@@ -313,6 +313,7 @@ store.register_lints(&[
|
|||||||
methods::ITERATOR_STEP_BY_ZERO,
|
methods::ITERATOR_STEP_BY_ZERO,
|
||||||
methods::ITER_CLONED_COLLECT,
|
methods::ITER_CLONED_COLLECT,
|
||||||
methods::ITER_COUNT,
|
methods::ITER_COUNT,
|
||||||
|
methods::ITER_KV_MAP,
|
||||||
methods::ITER_NEXT_SLICE,
|
methods::ITER_NEXT_SLICE,
|
||||||
methods::ITER_NTH,
|
methods::ITER_NTH,
|
||||||
methods::ITER_NTH_ZERO,
|
methods::ITER_NTH_ZERO,
|
||||||
@@ -595,7 +596,6 @@ store.register_lints(&[
|
|||||||
vec_init_then_push::VEC_INIT_THEN_PUSH,
|
vec_init_then_push::VEC_INIT_THEN_PUSH,
|
||||||
wildcard_imports::ENUM_GLOB_USE,
|
wildcard_imports::ENUM_GLOB_USE,
|
||||||
wildcard_imports::WILDCARD_IMPORTS,
|
wildcard_imports::WILDCARD_IMPORTS,
|
||||||
write::POSITIONAL_NAMED_FORMAT_PARAMETERS,
|
|
||||||
write::PRINTLN_EMPTY_STRING,
|
write::PRINTLN_EMPTY_STRING,
|
||||||
write::PRINT_LITERAL,
|
write::PRINT_LITERAL,
|
||||||
write::PRINT_STDERR,
|
write::PRINT_STDERR,
|
||||||
|
|||||||
@@ -35,5 +35,4 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec!
|
|||||||
LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
|
LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
|
||||||
LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
|
LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
|
||||||
LintId::of(swap_ptr_to_ref::SWAP_PTR_TO_REF),
|
LintId::of(swap_ptr_to_ref::SWAP_PTR_TO_REF),
|
||||||
LintId::of(write::POSITIONAL_NAMED_FORMAT_PARAMETERS),
|
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ extern crate rustc_lint;
|
|||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
extern crate rustc_mir_dataflow;
|
extern crate rustc_mir_dataflow;
|
||||||
extern crate rustc_parse;
|
extern crate rustc_parse;
|
||||||
extern crate rustc_parse_format;
|
|
||||||
extern crate rustc_session;
|
extern crate rustc_session;
|
||||||
extern crate rustc_span;
|
extern crate rustc_span;
|
||||||
extern crate rustc_target;
|
extern crate rustc_target;
|
||||||
@@ -425,7 +424,6 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
store.register_pre_expansion_pass(|| Box::new(write::Write::default()));
|
|
||||||
store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv }));
|
store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv }));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,7 +522,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
#[cfg(feature = "internal")]
|
#[cfg(feature = "internal")]
|
||||||
{
|
{
|
||||||
if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
|
if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
|
||||||
store.register_late_pass(|| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new()));
|
store.register_late_pass(|_| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -879,6 +877,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
ignore_publish: cargo_ignore_publish,
|
ignore_publish: cargo_ignore_publish,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
store.register_late_pass(|_| Box::new(write::Write::default()));
|
||||||
store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef));
|
store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef));
|
||||||
store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets));
|
store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets));
|
||||||
store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings));
|
store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use super::ERR_EXPECT;
|
use super::ERR_EXPECT;
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::ty::implements_trait;
|
use clippy_utils::ty::has_debug_impl;
|
||||||
use clippy_utils::{meets_msrv, msrvs, ty::is_type_diagnostic_item};
|
use clippy_utils::{meets_msrv, msrvs, ty::is_type_diagnostic_item};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@@ -28,7 +28,7 @@ pub(super) fn check(
|
|||||||
// Tests if the T type in a `Result<T, E>` is not None
|
// Tests if the T type in a `Result<T, E>` is not None
|
||||||
if let Some(data_type) = get_data_type(cx, result_type);
|
if let Some(data_type) = get_data_type(cx, result_type);
|
||||||
// Tests if the T type in a `Result<T, E>` implements debug
|
// Tests if the T type in a `Result<T, E>` implements debug
|
||||||
if has_debug_impl(data_type, cx);
|
if has_debug_impl(cx, data_type);
|
||||||
|
|
||||||
then {
|
then {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
@@ -51,10 +51,3 @@ fn get_data_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option<Ty<'a>> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a type, very if the Debug trait has been impl'd
|
|
||||||
fn has_debug_impl<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool {
|
|
||||||
cx.tcx
|
|
||||||
.get_diagnostic_item(sym::Debug)
|
|
||||||
.map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
|
|
||||||
}
|
|
||||||
|
|||||||
87
clippy_lints/src/methods/iter_kv_map.rs
Normal file
87
clippy_lints/src/methods/iter_kv_map.rs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
|
use super::ITER_KV_MAP;
|
||||||
|
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_sugg, span_lint_and_then};
|
||||||
|
use clippy_utils::source::{snippet, snippet_with_applicability};
|
||||||
|
use clippy_utils::sugg;
|
||||||
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
|
use clippy_utils::visitors::is_local_used;
|
||||||
|
use rustc_hir::{BindingAnnotation, Body, BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
|
||||||
|
use rustc_lint::{LateContext, LintContext};
|
||||||
|
use rustc_middle::ty;
|
||||||
|
use rustc_span::sym;
|
||||||
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
/// lint use of:
|
||||||
|
/// - `hashmap.iter().map(|(_, v)| v)`
|
||||||
|
/// - `hashmap.into_iter().map(|(_, v)| v)`
|
||||||
|
/// on `HashMaps` and `BTreeMaps` in std
|
||||||
|
|
||||||
|
pub(super) fn check<'tcx>(
|
||||||
|
cx: &LateContext<'tcx>,
|
||||||
|
map_type: &'tcx str, // iter / into_iter
|
||||||
|
expr: &'tcx Expr<'tcx>, // .iter().map(|(_, v_| v))
|
||||||
|
recv: &'tcx Expr<'tcx>, // hashmap
|
||||||
|
m_arg: &'tcx Expr<'tcx>, // |(_, v)| v
|
||||||
|
) {
|
||||||
|
if_chain! {
|
||||||
|
if !expr.span.from_expansion();
|
||||||
|
if let ExprKind::Closure(c) = m_arg.kind;
|
||||||
|
if let Body {params: [p], value: body_expr, generator_kind: _ } = cx.tcx.hir().body(c.body);
|
||||||
|
if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind;
|
||||||
|
|
||||||
|
let (replacement_kind, binded_ident) = match (&key_pat.kind, &val_pat.kind) {
|
||||||
|
(key, PatKind::Binding(_, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", value),
|
||||||
|
(PatKind::Binding(_, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", key),
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let ty = cx.typeck_results().expr_ty(recv);
|
||||||
|
if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap);
|
||||||
|
|
||||||
|
then {
|
||||||
|
let mut applicability = rustc_errors::Applicability::MachineApplicable;
|
||||||
|
let recv_snippet = snippet_with_applicability(cx, recv.span, "map", &mut applicability);
|
||||||
|
let into_prefix = if map_type == "into_iter" {"into_"} else {""};
|
||||||
|
|
||||||
|
if_chain! {
|
||||||
|
if let ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body_expr.kind;
|
||||||
|
if let [local_ident] = path.segments;
|
||||||
|
if local_ident.ident.as_str() == binded_ident.as_str();
|
||||||
|
|
||||||
|
then {
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
ITER_KV_MAP,
|
||||||
|
expr.span,
|
||||||
|
&format!("iterating on a map's {}s", replacement_kind),
|
||||||
|
"try",
|
||||||
|
format!("{}.{}{}s()", recv_snippet, into_prefix, replacement_kind),
|
||||||
|
applicability,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
ITER_KV_MAP,
|
||||||
|
expr.span,
|
||||||
|
&format!("iterating on a map's {}s", replacement_kind),
|
||||||
|
"try",
|
||||||
|
format!("{}.{}{}s().map(|{}| {})", recv_snippet, into_prefix, replacement_kind, binded_ident,
|
||||||
|
snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)),
|
||||||
|
applicability,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the pattern is a `PatWild`, or is an ident prefixed with `_`
|
||||||
|
/// that is not locally used.
|
||||||
|
fn pat_is_wild<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool {
|
||||||
|
match *pat {
|
||||||
|
PatKind::Wild => true,
|
||||||
|
PatKind::Binding(_, id, ident, None) if ident.as_str().starts_with('_') => !is_local_used(cx, body, id),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,6 +35,7 @@ mod into_iter_on_ref;
|
|||||||
mod is_digit_ascii_radix;
|
mod is_digit_ascii_radix;
|
||||||
mod iter_cloned_collect;
|
mod iter_cloned_collect;
|
||||||
mod iter_count;
|
mod iter_count;
|
||||||
|
mod iter_kv_map;
|
||||||
mod iter_next_slice;
|
mod iter_next_slice;
|
||||||
mod iter_nth;
|
mod iter_nth;
|
||||||
mod iter_nth_zero;
|
mod iter_nth_zero;
|
||||||
@@ -3036,6 +3037,37 @@ declare_clippy_lint! {
|
|||||||
"use of `File::read_to_end` or `File::read_to_string`"
|
"use of `File::read_to_end` or `File::read_to_string`"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
///
|
||||||
|
/// Checks for iterating a map (`HashMap` or `BTreeMap`) and
|
||||||
|
/// ignoring either the keys or values.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
///
|
||||||
|
/// Readability. There are `keys` and `values` methods that
|
||||||
|
/// can be used to express that we only need the keys or the values.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use std::collections::HashMap;
|
||||||
|
/// let map: HashMap<u32, u32> = HashMap::new();
|
||||||
|
/// let values = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```
|
||||||
|
/// # use std::collections::HashMap;
|
||||||
|
/// let map: HashMap<u32, u32> = HashMap::new();
|
||||||
|
/// let values = map.values().collect::<Vec<_>>();
|
||||||
|
/// ```
|
||||||
|
#[clippy::version = "1.65.0"]
|
||||||
|
pub ITER_KV_MAP,
|
||||||
|
complexity,
|
||||||
|
"iterating on map using `iter` when `keys` or `values` would do"
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Methods {
|
pub struct Methods {
|
||||||
avoid_breaking_exported_api: bool,
|
avoid_breaking_exported_api: bool,
|
||||||
msrv: Option<RustcVersion>,
|
msrv: Option<RustcVersion>,
|
||||||
@@ -3159,6 +3191,7 @@ impl_lint_pass!(Methods => [
|
|||||||
UNNECESSARY_SORT_BY,
|
UNNECESSARY_SORT_BY,
|
||||||
VEC_RESIZE_TO_ZERO,
|
VEC_RESIZE_TO_ZERO,
|
||||||
VERBOSE_FILE_READS,
|
VERBOSE_FILE_READS,
|
||||||
|
ITER_KV_MAP,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/// Extracts a method call name, args, and `Span` of the method name.
|
/// Extracts a method call name, args, and `Span` of the method name.
|
||||||
@@ -3498,6 +3531,9 @@ impl Methods {
|
|||||||
(name @ ("map" | "map_err"), [m_arg]) => {
|
(name @ ("map" | "map_err"), [m_arg]) => {
|
||||||
if name == "map" {
|
if name == "map" {
|
||||||
map_clone::check(cx, expr, recv, m_arg, self.msrv);
|
map_clone::check(cx, expr, recv, m_arg, self.msrv);
|
||||||
|
if let Some((map_name @ ("iter" | "into_iter"), recv2, _, _)) = method_call(recv) {
|
||||||
|
iter_kv_map::check(cx, map_name, expr, recv2, m_arg);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
map_err_ignore::check(cx, expr, m_arg);
|
map_err_ignore::check(cx, expr, m_arg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_help;
|
use clippy_utils::diagnostics::span_lint_and_help;
|
||||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@@ -15,7 +15,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
|
|||||||
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
|
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
|
||||||
let result_type = cx.typeck_results().expr_ty(recv);
|
let result_type = cx.typeck_results().expr_ty(recv);
|
||||||
if let Some(error_type) = get_error_type(cx, result_type);
|
if let Some(error_type) = get_error_type(cx, result_type);
|
||||||
if has_debug_impl(error_type, cx);
|
if has_debug_impl(cx, error_type);
|
||||||
|
|
||||||
then {
|
then {
|
||||||
span_lint_and_help(
|
span_lint_and_help(
|
||||||
@@ -37,10 +37,3 @@ fn get_error_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option<Ty<'a>> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This checks whether a given type is known to implement Debug.
|
|
||||||
fn has_debug_impl<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool {
|
|
||||||
cx.tcx
|
|
||||||
.get_diagnostic_item(sym::Debug)
|
|
||||||
.map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use clippy_utils::visitors::find_all_ret_expressions;
|
|||||||
use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty};
|
use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty};
|
||||||
use clippy_utils::{meets_msrv, msrvs};
|
use clippy_utils::{meets_msrv, msrvs};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node};
|
use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::mir::Mutability;
|
use rustc_middle::mir::Mutability;
|
||||||
@@ -268,7 +268,7 @@ fn check_other_call_arg<'tcx>(
|
|||||||
// We can't add an `&` when the trait is `Deref` because `Target = &T` won't match
|
// We can't add an `&` when the trait is `Deref` because `Target = &T` won't match
|
||||||
// `Target = T`.
|
// `Target = T`.
|
||||||
if n_refs > 0 || is_copy(cx, receiver_ty) || trait_predicate.def_id() != deref_trait_id;
|
if n_refs > 0 || is_copy(cx, receiver_ty) || trait_predicate.def_id() != deref_trait_id;
|
||||||
let n_refs = max(n_refs, if is_copy(cx, receiver_ty) { 0 } else { 1 });
|
let n_refs = max(n_refs, usize::from(!is_copy(cx, receiver_ty)));
|
||||||
if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
|
if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
|
||||||
then {
|
then {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
@@ -379,6 +379,10 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
|
|||||||
Node::Expr(parent_expr) => {
|
Node::Expr(parent_expr) => {
|
||||||
if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
|
if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
|
||||||
{
|
{
|
||||||
|
if cx.tcx.lang_items().require(LangItem::IntoFutureIntoFuture) == Ok(callee_def_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
|
let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
|
||||||
if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id)
|
if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id)
|
||||||
&& let Some(param_ty) = fn_sig.inputs().get(arg_index)
|
&& let Some(param_ty) = fn_sig.inputs().get(arg_index)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use rustc_ast::ast;
|
|||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext};
|
use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext};
|
||||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||||
use rustc_span::{FileName, RealFileName, SourceFile, Span, SyntaxContext};
|
use rustc_span::{FileName, SourceFile, Span, SyntaxContext};
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::path::{Component, Path};
|
use std::path::{Component, Path};
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ impl EarlyLintPass for ModStyle {
|
|||||||
|
|
||||||
let files = cx.sess().source_map().files();
|
let files = cx.sess().source_map().files();
|
||||||
|
|
||||||
let RealFileName::LocalPath(trim_to_src) = &cx.sess().opts.working_dir else { return };
|
let Some(trim_to_src) = cx.sess().opts.working_dir.local_path() else { return };
|
||||||
|
|
||||||
// `folder_segments` is all unique folder path segments `path/to/foo.rs` gives
|
// `folder_segments` is all unique folder path segments `path/to/foo.rs` gives
|
||||||
// `[path, to]` but not foo
|
// `[path, to]` but not foo
|
||||||
@@ -90,7 +90,7 @@ impl EarlyLintPass for ModStyle {
|
|||||||
// `{ foo => path/to/foo.rs, .. }
|
// `{ foo => path/to/foo.rs, .. }
|
||||||
let mut file_map = FxHashMap::default();
|
let mut file_map = FxHashMap::default();
|
||||||
for file in files.iter() {
|
for file in files.iter() {
|
||||||
if let FileName::Real(RealFileName::LocalPath(lp)) = &file.name {
|
if let FileName::Real(name) = &file.name && let Some(lp) = name.local_path() {
|
||||||
let path = if lp.is_relative() {
|
let path = if lp.is_relative() {
|
||||||
lp
|
lp
|
||||||
} else if let Ok(relative) = lp.strip_prefix(trim_to_src) {
|
} else if let Ok(relative) = lp.strip_prefix(trim_to_src) {
|
||||||
|
|||||||
@@ -184,6 +184,10 @@ fn macro_braces(conf: FxHashSet<MacroMatcher>) -> FxHashMap<String, (String, Str
|
|||||||
name: "vec",
|
name: "vec",
|
||||||
braces: ("[", "]"),
|
braces: ("[", "]"),
|
||||||
),
|
),
|
||||||
|
macro_matcher!(
|
||||||
|
name: "matches",
|
||||||
|
braces: ("(", ")"),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<FxHashMap<_, _>>();
|
.collect::<FxHashMap<_, _>>();
|
||||||
|
|||||||
@@ -42,27 +42,30 @@ impl ArithmeticSideEffects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks assign operators (+=, -=, *=, /=) of integers in a non-constant environment that
|
/// Assuming that `expr` is a literal integer, checks operators (+=, -=, *, /) in a
|
||||||
/// won't overflow.
|
/// non-constant environment that won't overflow.
|
||||||
fn has_valid_assign_op(op: &Spanned<hir::BinOpKind>, rhs: &hir::Expr<'_>, rhs_refs: Ty<'_>) -> bool {
|
fn has_valid_op(op: &Spanned<hir::BinOpKind>, expr: &hir::Expr<'_>) -> bool {
|
||||||
if !Self::is_literal_integer(rhs, rhs_refs) {
|
if let hir::BinOpKind::Add | hir::BinOpKind::Sub = op.node
|
||||||
return false;
|
&& let hir::ExprKind::Lit(ref lit) = expr.kind
|
||||||
|
&& let ast::LitKind::Int(0, _) = lit.node
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if let hir::BinOpKind::Div | hir::BinOpKind::Mul = op.node
|
if let hir::BinOpKind::Div | hir::BinOpKind::Rem = op.node
|
||||||
&& let hir::ExprKind::Lit(ref lit) = rhs.kind
|
&& let hir::ExprKind::Lit(ref lit) = expr.kind
|
||||||
&& let ast::LitKind::Int(1, _) = lit.node
|
&& !matches!(lit.node, ast::LitKind::Int(0, _))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if let hir::BinOpKind::Mul = op.node
|
||||||
|
&& let hir::ExprKind::Lit(ref lit) = expr.kind
|
||||||
|
&& let ast::LitKind::Int(0 | 1, _) = lit.node
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks "raw" binary operators (+, -, *, /) of integers in a non-constant environment
|
|
||||||
/// already handled by the CTFE.
|
|
||||||
fn has_valid_bin_op(lhs: &hir::Expr<'_>, lhs_refs: Ty<'_>, rhs: &hir::Expr<'_>, rhs_refs: Ty<'_>) -> bool {
|
|
||||||
Self::is_literal_integer(lhs, lhs_refs) && Self::is_literal_integer(rhs, rhs_refs)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if the given `expr` has any of the inner `allowed` elements.
|
/// Checks if the given `expr` has any of the inner `allowed` elements.
|
||||||
fn is_allowed_ty(&self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
|
fn is_allowed_ty(&self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
|
||||||
self.allowed.contains(
|
self.allowed.contains(
|
||||||
@@ -83,7 +86,8 @@ impl ArithmeticSideEffects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn issue_lint(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
|
fn issue_lint(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
|
||||||
span_lint(cx, ARITHMETIC_SIDE_EFFECTS, expr.span, "arithmetic detected");
|
let msg = "arithmetic operation that can potentially result in unexpected side-effects";
|
||||||
|
span_lint(cx, ARITHMETIC_SIDE_EFFECTS, expr.span, msg);
|
||||||
self.expr_span = Some(expr.span);
|
self.expr_span = Some(expr.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,13 +119,18 @@ impl ArithmeticSideEffects {
|
|||||||
if self.is_allowed_ty(cx, lhs) || self.is_allowed_ty(cx, rhs) {
|
if self.is_allowed_ty(cx, lhs) || self.is_allowed_ty(cx, rhs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let lhs_refs = cx.typeck_results().expr_ty(lhs).peel_refs();
|
let has_valid_op = match (
|
||||||
let rhs_refs = cx.typeck_results().expr_ty(rhs).peel_refs();
|
Self::is_literal_integer(lhs, cx.typeck_results().expr_ty(lhs).peel_refs()),
|
||||||
let has_valid_assign_op = Self::has_valid_assign_op(op, rhs, rhs_refs);
|
Self::is_literal_integer(rhs, cx.typeck_results().expr_ty(rhs).peel_refs()),
|
||||||
if has_valid_assign_op || Self::has_valid_bin_op(lhs, lhs_refs, rhs, rhs_refs) {
|
) {
|
||||||
return;
|
(true, true) => true,
|
||||||
|
(true, false) => Self::has_valid_op(op, lhs),
|
||||||
|
(false, true) => Self::has_valid_op(op, rhs),
|
||||||
|
(false, false) => false,
|
||||||
|
};
|
||||||
|
if !has_valid_op {
|
||||||
|
self.issue_lint(cx, expr);
|
||||||
}
|
}
|
||||||
self.issue_lint(cx, expr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
|
|||||||
("clippy::invalid_ref", "invalid_value"),
|
("clippy::invalid_ref", "invalid_value"),
|
||||||
("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"),
|
("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"),
|
||||||
("clippy::panic_params", "non_fmt_panics"),
|
("clippy::panic_params", "non_fmt_panics"),
|
||||||
|
("clippy::positional_named_format_parameters", "named_arguments_used_positionally"),
|
||||||
("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"),
|
("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"),
|
||||||
("clippy::unknown_clippy_lints", "unknown_lints"),
|
("clippy::unknown_clippy_lints", "unknown_lints"),
|
||||||
("clippy::unused_label", "unused_labels"),
|
("clippy::unused_label", "unused_labels"),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor};
|
|||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
|
use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
|
||||||
@@ -109,8 +110,14 @@ impl<'a, 'tcx> PeekableVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
|
impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
|
||||||
fn visit_expr(&mut self, ex: &'_ Expr<'_>) {
|
type NestedFilter = OnlyBodies;
|
||||||
|
|
||||||
|
fn nested_visit_map(&mut self) -> Self::Map {
|
||||||
|
self.cx.tcx.hir()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
|
||||||
if self.found_peek_call {
|
if self.found_peek_call {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -136,12 +143,11 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.iter().any(|arg| {
|
if args.iter().any(|arg| arg_is_mut_peekable(self.cx, arg)) {
|
||||||
matches!(arg.kind, ExprKind::Path(_)) && arg_is_mut_peekable(self.cx, arg)
|
|
||||||
}) {
|
|
||||||
self.found_peek_call = true;
|
self.found_peek_call = true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
},
|
},
|
||||||
// Catch anything taking a Peekable mutably
|
// Catch anything taking a Peekable mutably
|
||||||
ExprKind::MethodCall(
|
ExprKind::MethodCall(
|
||||||
@@ -190,21 +196,21 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
|
|||||||
Node::Local(Local { init: Some(init), .. }) => {
|
Node::Local(Local { init: Some(init), .. }) => {
|
||||||
if arg_is_mut_peekable(self.cx, init) {
|
if arg_is_mut_peekable(self.cx, init) {
|
||||||
self.found_peek_call = true;
|
self.found_peek_call = true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
},
|
},
|
||||||
Node::Stmt(stmt) => match stmt.kind {
|
Node::Stmt(stmt) => {
|
||||||
StmtKind::Expr(_) | StmtKind::Semi(_) => {},
|
match stmt.kind {
|
||||||
_ => {
|
StmtKind::Local(_) | StmtKind::Item(_) => self.found_peek_call = true,
|
||||||
self.found_peek_call = true;
|
StmtKind::Expr(_) | StmtKind::Semi(_) => {},
|
||||||
return;
|
}
|
||||||
},
|
|
||||||
|
return;
|
||||||
},
|
},
|
||||||
Node::Block(_) | Node::ExprField(_) => {},
|
Node::Block(_) | Node::ExprField(_) => {},
|
||||||
_ => {
|
_ => {
|
||||||
break;
|
return;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::ty::same_type_and_consts;
|
use clippy_utils::ty::same_type_and_consts;
|
||||||
use clippy_utils::{meets_msrv, msrvs};
|
use clippy_utils::{is_from_proc_macro, meets_msrv, msrvs};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@@ -87,7 +87,7 @@ impl_lint_pass!(UseSelf => [USE_SELF]);
|
|||||||
const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
|
const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
||||||
fn check_item(&mut self, _cx: &LateContext<'_>, item: &Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) {
|
||||||
if matches!(item.kind, ItemKind::OpaqueTy(_)) {
|
if matches!(item.kind, ItemKind::OpaqueTy(_)) {
|
||||||
// skip over `ItemKind::OpaqueTy` in order to lint `foo() -> impl <..>`
|
// skip over `ItemKind::OpaqueTy` in order to lint `foo() -> impl <..>`
|
||||||
return;
|
return;
|
||||||
@@ -103,6 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
|||||||
if parameters.as_ref().map_or(true, |params| {
|
if parameters.as_ref().map_or(true, |params| {
|
||||||
!params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
|
!params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
|
||||||
});
|
});
|
||||||
|
if !is_from_proc_macro(cx, item); // expensive, should be last check
|
||||||
then {
|
then {
|
||||||
StackItem::Check {
|
StackItem::Check {
|
||||||
impl_id: item.def_id,
|
impl_id: item.def_id,
|
||||||
@@ -213,9 +214,6 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
|||||||
hir_ty_to_ty(cx.tcx, hir_ty)
|
hir_ty_to_ty(cx.tcx, hir_ty)
|
||||||
};
|
};
|
||||||
if same_type_and_consts(ty, cx.tcx.type_of(impl_id));
|
if same_type_and_consts(ty, cx.tcx.type_of(impl_id));
|
||||||
let hir = cx.tcx.hir();
|
|
||||||
// prevents false positive on `#[derive(serde::Deserialize)]`
|
|
||||||
if !hir.span(hir.get_parent_node(hir_ty.hir_id)).in_derive_expansion();
|
|
||||||
then {
|
then {
|
||||||
span_lint(cx, hir_ty.span);
|
span_lint(cx, hir_ty.span);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ pub fn format_error(error: Box<dyn Error>) -> String {
|
|||||||
|
|
||||||
let mut msg = String::from(prefix);
|
let mut msg = String::from(prefix);
|
||||||
for row in 0..rows {
|
for row in 0..rows {
|
||||||
write!(msg, "\n").unwrap();
|
writeln!(msg).unwrap();
|
||||||
for (column, column_width) in column_widths.iter().copied().enumerate() {
|
for (column, column_width) in column_widths.iter().copied().enumerate() {
|
||||||
let index = column * rows + row;
|
let index = column * rows + row;
|
||||||
let field = fields.get(index).copied().unwrap_or_default();
|
let field = fields.get(index).copied().unwrap_or_default();
|
||||||
|
|||||||
@@ -1,20 +1,12 @@
|
|||||||
use std::borrow::Cow;
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||||
use std::iter;
|
use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn, MacroCall};
|
||||||
use std::ops::{Deref, Range};
|
use clippy_utils::source::snippet_opt;
|
||||||
|
use rustc_ast::LitKind;
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
|
use rustc_errors::Applicability;
|
||||||
use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
|
use rustc_hir::{Expr, ExprKind, HirIdMap, Impl, Item, ItemKind};
|
||||||
use rustc_ast::ast::{Expr, ExprKind, Impl, Item, ItemKind, MacCall, Path, StrLit, StrStyle};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_ast::ptr::P;
|
|
||||||
use rustc_ast::token::{self, LitKind};
|
|
||||||
use rustc_ast::tokenstream::TokenStream;
|
|
||||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
|
||||||
use rustc_lexer::unescape::{self, EscapeError};
|
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
|
||||||
use rustc_parse::parser;
|
|
||||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||||
use rustc_span::symbol::{kw, Symbol};
|
use rustc_span::{sym, BytePos, Span};
|
||||||
use rustc_span::{sym, BytePos, InnerSpan, Span, DUMMY_SP};
|
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
@@ -74,13 +66,7 @@ declare_clippy_lint! {
|
|||||||
/// application and might forget to remove those prints afterward.
|
/// application and might forget to remove those prints afterward.
|
||||||
///
|
///
|
||||||
/// ### Known problems
|
/// ### Known problems
|
||||||
/// * Only catches `print!` and `println!` calls.
|
/// Only catches `print!` and `println!` calls.
|
||||||
/// * The lint level is unaffected by crate attributes. The level can still
|
|
||||||
/// be set for functions, modules and other items. To change the level for
|
|
||||||
/// the entire crate, please use command line flags. More information and a
|
|
||||||
/// configuration example can be found in [clippy#6610].
|
|
||||||
///
|
|
||||||
/// [clippy#6610]: https://github.com/rust-lang/rust-clippy/issues/6610#issuecomment-977120558
|
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
@@ -102,13 +88,7 @@ declare_clippy_lint! {
|
|||||||
/// application and might forget to remove those prints afterward.
|
/// application and might forget to remove those prints afterward.
|
||||||
///
|
///
|
||||||
/// ### Known problems
|
/// ### Known problems
|
||||||
/// * Only catches `eprint!` and `eprintln!` calls.
|
/// Only catches `eprint!` and `eprintln!` calls.
|
||||||
/// * The lint level is unaffected by crate attributes. The level can still
|
|
||||||
/// be set for functions, modules and other items. To change the level for
|
|
||||||
/// the entire crate, please use command line flags. More information and a
|
|
||||||
/// configuration example can be found in [clippy#6610].
|
|
||||||
///
|
|
||||||
/// [clippy#6610]: https://github.com/rust-lang/rust-clippy/issues/6610#issuecomment-977120558
|
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
@@ -149,10 +129,6 @@ declare_clippy_lint! {
|
|||||||
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
|
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
|
||||||
/// (i.e., just put the literal in the format string)
|
/// (i.e., just put the literal in the format string)
|
||||||
///
|
///
|
||||||
/// ### Known problems
|
|
||||||
/// Will also warn with macro calls as arguments that expand to literals
|
|
||||||
/// -- e.g., `println!("{}", env!("FOO"))`.
|
|
||||||
///
|
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// println!("{}", "foo");
|
/// println!("{}", "foo");
|
||||||
@@ -234,10 +210,6 @@ declare_clippy_lint! {
|
|||||||
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
|
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
|
||||||
/// (i.e., just put the literal in the format string)
|
/// (i.e., just put the literal in the format string)
|
||||||
///
|
///
|
||||||
/// ### Known problems
|
|
||||||
/// Will also warn with macro calls as arguments that expand to literals
|
|
||||||
/// -- e.g., `writeln!(buf, "{}", env!("FOO"))`.
|
|
||||||
///
|
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use std::fmt::Write;
|
/// # use std::fmt::Write;
|
||||||
@@ -257,28 +229,6 @@ declare_clippy_lint! {
|
|||||||
"writing a literal with a format string"
|
"writing a literal with a format string"
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_clippy_lint! {
|
|
||||||
/// ### What it does
|
|
||||||
/// This lint warns when a named parameter in a format string is used as a positional one.
|
|
||||||
///
|
|
||||||
/// ### Why is this bad?
|
|
||||||
/// It may be confused for an assignment and obfuscates which parameter is being used.
|
|
||||||
///
|
|
||||||
/// ### Example
|
|
||||||
/// ```rust
|
|
||||||
/// println!("{}", x = 10);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Use instead:
|
|
||||||
/// ```rust
|
|
||||||
/// println!("{x}", x = 10);
|
|
||||||
/// ```
|
|
||||||
#[clippy::version = "1.63.0"]
|
|
||||||
pub POSITIONAL_NAMED_FORMAT_PARAMETERS,
|
|
||||||
suspicious,
|
|
||||||
"named parameter in a format string is used positionally"
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Write {
|
pub struct Write {
|
||||||
in_debug_impl: bool,
|
in_debug_impl: bool,
|
||||||
@@ -294,537 +244,308 @@ impl_lint_pass!(Write => [
|
|||||||
WRITE_WITH_NEWLINE,
|
WRITE_WITH_NEWLINE,
|
||||||
WRITELN_EMPTY_STRING,
|
WRITELN_EMPTY_STRING,
|
||||||
WRITE_LITERAL,
|
WRITE_LITERAL,
|
||||||
POSITIONAL_NAMED_FORMAT_PARAMETERS,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
impl EarlyLintPass for Write {
|
impl<'tcx> LateLintPass<'tcx> for Write {
|
||||||
fn check_item(&mut self, _: &EarlyContext<'_>, item: &Item) {
|
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||||
if let ItemKind::Impl(box Impl {
|
if is_debug_impl(cx, item) {
|
||||||
of_trait: Some(trait_ref),
|
self.in_debug_impl = true;
|
||||||
..
|
|
||||||
}) = &item.kind
|
|
||||||
{
|
|
||||||
let trait_name = trait_ref
|
|
||||||
.path
|
|
||||||
.segments
|
|
||||||
.iter()
|
|
||||||
.last()
|
|
||||||
.expect("path has at least one segment")
|
|
||||||
.ident
|
|
||||||
.name;
|
|
||||||
if trait_name == sym::Debug {
|
|
||||||
self.in_debug_impl = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item_post(&mut self, _: &EarlyContext<'_>, _: &Item) {
|
fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||||
self.in_debug_impl = false;
|
if is_debug_impl(cx, item) {
|
||||||
|
self.in_debug_impl = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &MacCall) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||||
fn is_build_script(cx: &EarlyContext<'_>) -> bool {
|
let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return };
|
||||||
// Cargo sets the crate name for build scripts to `build_script_build`
|
let Some(diag_name) = cx.tcx.get_diagnostic_name(macro_call.def_id) else { return };
|
||||||
cx.sess()
|
let Some(name) = diag_name.as_str().strip_suffix("_macro") else { return };
|
||||||
.opts
|
|
||||||
.crate_name
|
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |crate_name| crate_name == "build_script_build")
|
|
||||||
}
|
|
||||||
|
|
||||||
if mac.path == sym!(print) {
|
let is_build_script = cx
|
||||||
if !is_build_script(cx) {
|
.sess()
|
||||||
span_lint(cx, PRINT_STDOUT, mac.span(), "use of `print!`");
|
.opts
|
||||||
}
|
.crate_name
|
||||||
self.lint_print_with_newline(cx, mac);
|
.as_ref()
|
||||||
} else if mac.path == sym!(println) {
|
.map_or(false, |crate_name| crate_name == "build_script_build");
|
||||||
if !is_build_script(cx) {
|
|
||||||
span_lint(cx, PRINT_STDOUT, mac.span(), "use of `println!`");
|
match diag_name {
|
||||||
}
|
sym::print_macro | sym::println_macro => {
|
||||||
self.lint_println_empty_string(cx, mac);
|
if !is_build_script {
|
||||||
} else if mac.path == sym!(eprint) {
|
span_lint(cx, PRINT_STDOUT, macro_call.span, &format!("use of `{name}!`"));
|
||||||
span_lint(cx, PRINT_STDERR, mac.span(), "use of `eprint!`");
|
|
||||||
self.lint_print_with_newline(cx, mac);
|
|
||||||
} else if mac.path == sym!(eprintln) {
|
|
||||||
span_lint(cx, PRINT_STDERR, mac.span(), "use of `eprintln!`");
|
|
||||||
self.lint_println_empty_string(cx, mac);
|
|
||||||
} else if mac.path == sym!(write) {
|
|
||||||
if let (Some(fmt_str), dest) = self.check_tts(cx, mac.args.inner_tokens(), true) {
|
|
||||||
if check_newlines(&fmt_str) {
|
|
||||||
let (nl_span, only_nl) = newline_span(&fmt_str);
|
|
||||||
let nl_span = match (dest, only_nl) {
|
|
||||||
// Special case of `write!(buf, "\n")`: Mark everything from the end of
|
|
||||||
// `buf` for removal so no trailing comma [`writeln!(buf, )`] remains.
|
|
||||||
(Some(dest_expr), true) => nl_span.with_lo(dest_expr.span.hi()),
|
|
||||||
_ => nl_span,
|
|
||||||
};
|
|
||||||
span_lint_and_then(
|
|
||||||
cx,
|
|
||||||
WRITE_WITH_NEWLINE,
|
|
||||||
mac.span(),
|
|
||||||
"using `write!()` with a format string that ends in a single newline",
|
|
||||||
|err| {
|
|
||||||
err.multipart_suggestion(
|
|
||||||
"use `writeln!()` instead",
|
|
||||||
vec![(mac.path.span, String::from("writeln")), (nl_span, String::new())],
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
} else if mac.path == sym!(writeln) {
|
sym::eprint_macro | sym::eprintln_macro => {
|
||||||
if let (Some(fmt_str), expr) = self.check_tts(cx, mac.args.inner_tokens(), true) {
|
span_lint(cx, PRINT_STDERR, macro_call.span, &format!("use of `{name}!`"));
|
||||||
if fmt_str.symbol == kw::Empty {
|
},
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
sym::write_macro | sym::writeln_macro => {},
|
||||||
let suggestion = if let Some(e) = expr {
|
_ => return,
|
||||||
snippet_with_applicability(cx, e.span, "v", &mut applicability)
|
}
|
||||||
} else {
|
|
||||||
applicability = Applicability::HasPlaceholders;
|
|
||||||
Cow::Borrowed("v")
|
|
||||||
};
|
|
||||||
|
|
||||||
span_lint_and_sugg(
|
let Some(format_args) = FormatArgsExpn::find_nested(cx, expr, macro_call.expn) else { return };
|
||||||
cx,
|
|
||||||
WRITELN_EMPTY_STRING,
|
// ignore `writeln!(w)` and `write!(v, some_macro!())`
|
||||||
mac.span(),
|
if format_args.format_string.span.from_expansion() {
|
||||||
format!("using `writeln!({}, \"\")`", suggestion).as_str(),
|
return;
|
||||||
"replace it with",
|
}
|
||||||
format!("writeln!({})", suggestion),
|
|
||||||
applicability,
|
match diag_name {
|
||||||
);
|
sym::print_macro | sym::eprint_macro | sym::write_macro => {
|
||||||
|
check_newline(cx, &format_args, ¯o_call, name);
|
||||||
|
},
|
||||||
|
sym::println_macro | sym::eprintln_macro | sym::writeln_macro => {
|
||||||
|
check_empty_string(cx, &format_args, ¯o_call, name);
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
check_literal(cx, &format_args, name);
|
||||||
|
|
||||||
|
if !self.in_debug_impl {
|
||||||
|
for arg in &format_args.args {
|
||||||
|
if arg.format.r#trait == sym::Debug {
|
||||||
|
span_lint(cx, USE_DEBUG, arg.span, "use of `Debug`-based formatting");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn is_debug_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
|
||||||
/// Given a format string that ends in a newline and its span, calculates the span of the
|
if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), .. }) = &item.kind
|
||||||
/// newline, or the format string itself if the format string consists solely of a newline.
|
&& let Some(trait_id) = trait_ref.trait_def_id()
|
||||||
/// Return this and a boolean indicating whether it only consisted of a newline.
|
{
|
||||||
fn newline_span(fmtstr: &StrLit) -> (Span, bool) {
|
cx.tcx.is_diagnostic_item(sym::Debug, trait_id)
|
||||||
let sp = fmtstr.span;
|
|
||||||
let contents = fmtstr.symbol.as_str();
|
|
||||||
|
|
||||||
if contents == r"\n" {
|
|
||||||
return (sp, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
let newline_sp_hi = sp.hi()
|
|
||||||
- match fmtstr.style {
|
|
||||||
StrStyle::Cooked => BytePos(1),
|
|
||||||
StrStyle::Raw(hashes) => BytePos((1 + hashes).into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let newline_sp_len = if contents.ends_with('\n') {
|
|
||||||
BytePos(1)
|
|
||||||
} else if contents.ends_with(r"\n") {
|
|
||||||
BytePos(2)
|
|
||||||
} else {
|
} else {
|
||||||
panic!("expected format string to contain a newline");
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_call: &MacroCall, name: &str) {
|
||||||
|
let format_string_parts = &format_args.format_string.parts;
|
||||||
|
let mut format_string_span = format_args.format_string.span;
|
||||||
|
|
||||||
|
let Some(last) = format_string_parts.last() else { return };
|
||||||
|
|
||||||
|
let count_vertical_whitespace = || {
|
||||||
|
format_string_parts
|
||||||
|
.iter()
|
||||||
|
.flat_map(|part| part.as_str().chars())
|
||||||
|
.filter(|ch| matches!(ch, '\r' | '\n'))
|
||||||
|
.count()
|
||||||
};
|
};
|
||||||
|
|
||||||
(sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi), false)
|
if last.as_str().ends_with('\n')
|
||||||
}
|
// ignore format strings with other internal vertical whitespace
|
||||||
|
&& count_vertical_whitespace() == 1
|
||||||
|
|
||||||
/// Stores a list of replacement spans for each argument, but only if all the replacements used an
|
// ignore trailing arguments: `print!("Issue\n{}", 1265);`
|
||||||
/// empty format string.
|
&& format_string_parts.len() > format_args.args.len()
|
||||||
#[derive(Default)]
|
{
|
||||||
struct SimpleFormatArgs {
|
let lint = if name == "write" {
|
||||||
unnamed: Vec<Vec<Span>>,
|
format_string_span = expand_past_previous_comma(cx, format_string_span);
|
||||||
complex_unnamed: Vec<Vec<Span>>,
|
|
||||||
named: Vec<(Symbol, Vec<Span>)>,
|
|
||||||
}
|
|
||||||
impl SimpleFormatArgs {
|
|
||||||
fn get_unnamed(&self) -> impl Iterator<Item = &[Span]> {
|
|
||||||
self.unnamed.iter().map(|x| match x.as_slice() {
|
|
||||||
// Ignore the dummy span added from out of order format arguments.
|
|
||||||
[DUMMY_SP] => &[],
|
|
||||||
x => x,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_complex_unnamed(&self) -> impl Iterator<Item = &[Span]> {
|
WRITE_WITH_NEWLINE
|
||||||
self.complex_unnamed.iter().map(Vec::as_slice)
|
} else {
|
||||||
}
|
PRINT_WITH_NEWLINE
|
||||||
|
|
||||||
fn get_named(&self, n: &Path) -> &[Span] {
|
|
||||||
self.named.iter().find(|x| *n == x.0).map_or(&[], |x| x.1.as_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push(&mut self, arg: rustc_parse_format::Argument<'_>, span: Span) {
|
|
||||||
use rustc_parse_format::{
|
|
||||||
AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, FormatSpec,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const SIMPLE: FormatSpec<'_> = FormatSpec {
|
span_lint_and_then(
|
||||||
fill: None,
|
cx,
|
||||||
align: AlignUnknown,
|
lint,
|
||||||
flags: 0,
|
macro_call.span,
|
||||||
precision: CountImplied,
|
&format!("using `{name}!()` with a format string that ends in a single newline"),
|
||||||
precision_span: None,
|
|diag| {
|
||||||
width: CountImplied,
|
let name_span = cx.sess().source_map().span_until_char(macro_call.span, '!');
|
||||||
width_span: None,
|
let Some(format_snippet) = snippet_opt(cx, format_string_span) else { return };
|
||||||
ty: "",
|
|
||||||
ty_span: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
match arg.position {
|
if format_string_parts.len() == 1 && last.as_str() == "\n" {
|
||||||
ArgumentIs(n) | ArgumentImplicitlyIs(n) => {
|
// print!("\n"), write!(f, "\n")
|
||||||
if self.unnamed.len() <= n {
|
|
||||||
// Use a dummy span to mark all unseen arguments.
|
diag.multipart_suggestion(
|
||||||
self.unnamed.resize_with(n, || vec![DUMMY_SP]);
|
&format!("use `{name}ln!` instead"),
|
||||||
if arg.format == SIMPLE {
|
vec![(name_span, format!("{name}ln")), (format_string_span, String::new())],
|
||||||
self.unnamed.push(vec![span]);
|
Applicability::MachineApplicable,
|
||||||
} else {
|
);
|
||||||
self.unnamed.push(Vec::new());
|
} else if format_snippet.ends_with("\\n\"") {
|
||||||
}
|
// print!("...\n"), write!(f, "...\n")
|
||||||
} else {
|
|
||||||
let args = &mut self.unnamed[n];
|
let hi = format_string_span.hi();
|
||||||
match (args.as_mut_slice(), arg.format == SIMPLE) {
|
let newline_span = format_string_span.with_lo(hi - BytePos(3)).with_hi(hi - BytePos(1));
|
||||||
// A non-empty format string has been seen already.
|
|
||||||
([], _) => (),
|
diag.multipart_suggestion(
|
||||||
// Replace the dummy span, if it exists.
|
&format!("use `{name}ln!` instead"),
|
||||||
([dummy @ DUMMY_SP], true) => *dummy = span,
|
vec![(name_span, format!("{name}ln")), (newline_span, String::new())],
|
||||||
([_, ..], true) => args.push(span),
|
Applicability::MachineApplicable,
|
||||||
([_, ..], false) => *args = Vec::new(),
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ArgumentNamed(n) => {
|
);
|
||||||
let n = Symbol::intern(n);
|
|
||||||
if let Some(x) = self.named.iter_mut().find(|x| x.0 == n) {
|
|
||||||
match x.1.as_slice() {
|
|
||||||
// A non-empty format string has been seen already.
|
|
||||||
[] => (),
|
|
||||||
[_, ..] if arg.format == SIMPLE => x.1.push(span),
|
|
||||||
[_, ..] => x.1 = Vec::new(),
|
|
||||||
}
|
|
||||||
} else if arg.format == SIMPLE {
|
|
||||||
self.named.push((n, vec![span]));
|
|
||||||
} else {
|
|
||||||
self.named.push((n, Vec::new()));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_to_complex(&mut self, span: Span, position: usize) {
|
|
||||||
if self.complex_unnamed.len() <= position {
|
|
||||||
self.complex_unnamed.resize_with(position, Vec::new);
|
|
||||||
self.complex_unnamed.push(vec![span]);
|
|
||||||
} else {
|
|
||||||
let args: &mut Vec<Span> = &mut self.complex_unnamed[position];
|
|
||||||
args.push(span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_complex(
|
|
||||||
&mut self,
|
|
||||||
cx: &EarlyContext<'_>,
|
|
||||||
arg: rustc_parse_format::Argument<'_>,
|
|
||||||
str_lit_span: Span,
|
|
||||||
fmt_span: Span,
|
|
||||||
) {
|
|
||||||
use rustc_parse_format::{ArgumentImplicitlyIs, ArgumentIs, CountIsParam, CountIsStar};
|
|
||||||
|
|
||||||
let snippet = snippet_opt(cx, fmt_span);
|
|
||||||
|
|
||||||
let end = snippet
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|s| s.find(':'))
|
|
||||||
.or_else(|| fmt_span.hi().0.checked_sub(fmt_span.lo().0 + 1).map(|u| u as usize));
|
|
||||||
|
|
||||||
if let (ArgumentIs(n) | ArgumentImplicitlyIs(n), Some(end)) = (arg.position, end) {
|
|
||||||
let span = fmt_span.from_inner(InnerSpan::new(1, end));
|
|
||||||
self.push_to_complex(span, n);
|
|
||||||
};
|
|
||||||
|
|
||||||
if let (CountIsParam(n) | CountIsStar(n), Some(span)) = (arg.format.precision, arg.format.precision_span) {
|
|
||||||
// We need to do this hack as precision spans should be converted from .* to .foo$
|
|
||||||
let hack = if snippet.as_ref().and_then(|s| s.find('*')).is_some() {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
};
|
|
||||||
|
|
||||||
let span = str_lit_span.from_inner(InnerSpan {
|
|
||||||
start: span.start + 1,
|
|
||||||
end: span.end - hack,
|
|
||||||
});
|
|
||||||
self.push_to_complex(span, n);
|
|
||||||
};
|
|
||||||
|
|
||||||
if let (CountIsParam(n), Some(span)) = (arg.format.width, arg.format.width_span) {
|
|
||||||
let span = str_lit_span.from_inner(InnerSpan {
|
|
||||||
start: span.start,
|
|
||||||
end: span.end - 1,
|
|
||||||
});
|
|
||||||
self.push_to_complex(span, n);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Write {
|
fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_call: &MacroCall, name: &str) {
|
||||||
/// Parses a format string into a collection of spans for each argument. This only keeps track
|
if let [part] = &format_args.format_string.parts[..]
|
||||||
/// of empty format arguments. Will also lint usages of debug format strings outside of debug
|
&& let mut span = format_args.format_string.span
|
||||||
/// impls.
|
&& part.as_str() == "\n"
|
||||||
fn parse_fmt_string(&self, cx: &EarlyContext<'_>, str_lit: &StrLit) -> Option<SimpleFormatArgs> {
|
{
|
||||||
use rustc_parse_format::{ParseMode, Parser, Piece};
|
let lint = if name == "writeln" {
|
||||||
|
span = expand_past_previous_comma(cx, span);
|
||||||
|
|
||||||
let str_sym = str_lit.symbol_unescaped.as_str();
|
WRITELN_EMPTY_STRING
|
||||||
let style = match str_lit.style {
|
|
||||||
StrStyle::Cooked => None,
|
|
||||||
StrStyle::Raw(n) => Some(n as usize),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut parser = Parser::new(str_sym, style, snippet_opt(cx, str_lit.span), false, ParseMode::Format);
|
|
||||||
let mut args = SimpleFormatArgs::default();
|
|
||||||
|
|
||||||
while let Some(arg) = parser.next() {
|
|
||||||
let arg = match arg {
|
|
||||||
Piece::String(_) => continue,
|
|
||||||
Piece::NextArgument(arg) => arg,
|
|
||||||
};
|
|
||||||
let span = parser
|
|
||||||
.arg_places
|
|
||||||
.last()
|
|
||||||
.map_or(DUMMY_SP, |&x| str_lit.span.from_inner(InnerSpan::new(x.start, x.end)));
|
|
||||||
|
|
||||||
if !self.in_debug_impl && arg.format.ty == "?" {
|
|
||||||
// FIXME: modify rustc's fmt string parser to give us the current span
|
|
||||||
span_lint(cx, USE_DEBUG, span, "use of `Debug`-based formatting");
|
|
||||||
}
|
|
||||||
args.push(arg, span);
|
|
||||||
args.push_complex(cx, arg, str_lit.span, span);
|
|
||||||
}
|
|
||||||
|
|
||||||
parser.errors.is_empty().then_some(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
|
|
||||||
/// `Option`s. The first `Option` of the tuple is the macro's format string. It includes
|
|
||||||
/// the contents of the string, whether it's a raw string, and the span of the literal in the
|
|
||||||
/// source. The second `Option` in the tuple is, in the `write[ln]!` case, the expression the
|
|
||||||
/// `format_str` should be written to.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
///
|
|
||||||
/// Calling this function on
|
|
||||||
/// ```rust
|
|
||||||
/// # use std::fmt::Write;
|
|
||||||
/// # let mut buf = String::new();
|
|
||||||
/// # let something = "something";
|
|
||||||
/// writeln!(buf, "string to write: {}", something);
|
|
||||||
/// ```
|
|
||||||
/// will return
|
|
||||||
/// ```rust,ignore
|
|
||||||
/// (Some("string to write: {}"), Some(buf))
|
|
||||||
/// ```
|
|
||||||
fn check_tts<'a>(&self, cx: &EarlyContext<'a>, tts: TokenStream, is_write: bool) -> (Option<StrLit>, Option<Expr>) {
|
|
||||||
let mut parser = parser::Parser::new(&cx.sess().parse_sess, tts, false, None);
|
|
||||||
let expr = if is_write {
|
|
||||||
match parser
|
|
||||||
.parse_expr()
|
|
||||||
.map(rustc_ast::ptr::P::into_inner)
|
|
||||||
.map_err(DiagnosticBuilder::cancel)
|
|
||||||
{
|
|
||||||
// write!(e, ...)
|
|
||||||
Ok(p) if parser.eat(&token::Comma) => Some(p),
|
|
||||||
// write!(e) or error
|
|
||||||
e => return (None, e.ok()),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
PRINTLN_EMPTY_STRING
|
||||||
};
|
};
|
||||||
|
|
||||||
let fmtstr = match parser.parse_str_lit() {
|
span_lint_and_then(
|
||||||
Ok(fmtstr) => fmtstr,
|
cx,
|
||||||
Err(_) => return (None, expr),
|
lint,
|
||||||
};
|
macro_call.span,
|
||||||
|
&format!("empty string literal in `{name}!`"),
|
||||||
let args = match self.parse_fmt_string(cx, &fmtstr) {
|
|diag| {
|
||||||
Some(args) => args,
|
diag.span_suggestion(
|
||||||
None => return (Some(fmtstr), expr),
|
span,
|
||||||
};
|
"remove the empty string",
|
||||||
|
String::new(),
|
||||||
let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL };
|
|
||||||
let mut unnamed_args = args.get_unnamed();
|
|
||||||
let mut complex_unnamed_args = args.get_complex_unnamed();
|
|
||||||
loop {
|
|
||||||
if !parser.eat(&token::Comma) {
|
|
||||||
return (Some(fmtstr), expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
let comma_span = parser.prev_token.span;
|
|
||||||
let token_expr = if let Ok(expr) = parser.parse_expr().map_err(DiagnosticBuilder::cancel) {
|
|
||||||
expr
|
|
||||||
} else {
|
|
||||||
return (Some(fmtstr), None);
|
|
||||||
};
|
|
||||||
let complex_unnamed_arg = complex_unnamed_args.next();
|
|
||||||
|
|
||||||
let (fmt_spans, lit) = match &token_expr.kind {
|
|
||||||
ExprKind::Lit(lit) => (unnamed_args.next().unwrap_or(&[]), lit),
|
|
||||||
ExprKind::Assign(lhs, rhs, _) => {
|
|
||||||
if let Some(span) = complex_unnamed_arg {
|
|
||||||
for x in span {
|
|
||||||
Self::report_positional_named_param(cx, *x, lhs, rhs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match (&lhs.kind, &rhs.kind) {
|
|
||||||
(ExprKind::Path(_, p), ExprKind::Lit(lit)) => (args.get_named(p), lit),
|
|
||||||
_ => continue,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
unnamed_args.next();
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let replacement: String = match lit.token_lit.kind {
|
|
||||||
LitKind::StrRaw(_) | LitKind::ByteStrRaw(_) if matches!(fmtstr.style, StrStyle::Raw(_)) => {
|
|
||||||
lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}")
|
|
||||||
},
|
|
||||||
LitKind::Str | LitKind::ByteStr if matches!(fmtstr.style, StrStyle::Cooked) => {
|
|
||||||
lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}")
|
|
||||||
},
|
|
||||||
LitKind::StrRaw(_)
|
|
||||||
| LitKind::Str
|
|
||||||
| LitKind::ByteStrRaw(_)
|
|
||||||
| LitKind::ByteStr
|
|
||||||
| LitKind::Integer
|
|
||||||
| LitKind::Float
|
|
||||||
| LitKind::Err => continue,
|
|
||||||
LitKind::Byte | LitKind::Char => match lit.token_lit.symbol.as_str() {
|
|
||||||
"\"" if matches!(fmtstr.style, StrStyle::Cooked) => "\\\"",
|
|
||||||
"\"" if matches!(fmtstr.style, StrStyle::Raw(0)) => continue,
|
|
||||||
"\\\\" if matches!(fmtstr.style, StrStyle::Raw(_)) => "\\",
|
|
||||||
"\\'" => "'",
|
|
||||||
"{" => "{{",
|
|
||||||
"}" => "}}",
|
|
||||||
x if matches!(fmtstr.style, StrStyle::Raw(_)) && x.starts_with('\\') => continue,
|
|
||||||
x => x,
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
LitKind::Bool => lit.token_lit.symbol.as_str().deref().into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if !fmt_spans.is_empty() {
|
|
||||||
span_lint_and_then(
|
|
||||||
cx,
|
|
||||||
lint,
|
|
||||||
token_expr.span,
|
|
||||||
"literal with an empty format string",
|
|
||||||
|diag| {
|
|
||||||
diag.multipart_suggestion(
|
|
||||||
"try this",
|
|
||||||
iter::once((comma_span.to(token_expr.span), String::new()))
|
|
||||||
.chain(fmt_spans.iter().copied().zip(iter::repeat(replacement)))
|
|
||||||
.collect(),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn report_positional_named_param(cx: &EarlyContext<'_>, span: Span, lhs: &P<Expr>, _rhs: &P<Expr>) {
|
|
||||||
if let ExprKind::Path(_, _p) = &lhs.kind {
|
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
|
||||||
let name = snippet_with_applicability(cx, lhs.span, "name", &mut applicability);
|
|
||||||
// We need to do this hack as precision spans should be converted from .* to .foo$
|
|
||||||
let hack = snippet(cx, span, "").contains('*');
|
|
||||||
|
|
||||||
span_lint_and_sugg(
|
|
||||||
cx,
|
|
||||||
POSITIONAL_NAMED_FORMAT_PARAMETERS,
|
|
||||||
span,
|
|
||||||
&format!("named parameter {} is used as a positional parameter", name),
|
|
||||||
"replace it with",
|
|
||||||
if hack {
|
|
||||||
format!("{}$", name)
|
|
||||||
} else {
|
|
||||||
format!("{}", name)
|
|
||||||
},
|
|
||||||
applicability,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lint_println_empty_string(&self, cx: &EarlyContext<'_>, mac: &MacCall) {
|
|
||||||
if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) {
|
|
||||||
if fmt_str.symbol == kw::Empty {
|
|
||||||
let name = mac.path.segments[0].ident.name;
|
|
||||||
span_lint_and_sugg(
|
|
||||||
cx,
|
|
||||||
PRINTLN_EMPTY_STRING,
|
|
||||||
mac.span(),
|
|
||||||
&format!("using `{}!(\"\")`", name),
|
|
||||||
"replace it with",
|
|
||||||
format!("{}!()", name),
|
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, name: &str) {
|
||||||
|
let mut counts = HirIdMap::<usize>::default();
|
||||||
|
for param in format_args.params() {
|
||||||
|
*counts.entry(param.value.hir_id).or_default() += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lint_print_with_newline(&self, cx: &EarlyContext<'_>, mac: &MacCall) {
|
for arg in &format_args.args {
|
||||||
if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) {
|
let value = arg.param.value;
|
||||||
if check_newlines(&fmt_str) {
|
|
||||||
let name = mac.path.segments[0].ident.name;
|
if counts[&value.hir_id] == 1
|
||||||
let suggested = format!("{}ln", name);
|
&& arg.format.is_default()
|
||||||
span_lint_and_then(
|
&& let ExprKind::Lit(lit) = &value.kind
|
||||||
cx,
|
&& !value.span.from_expansion()
|
||||||
PRINT_WITH_NEWLINE,
|
&& let Some(value_string) = snippet_opt(cx, value.span)
|
||||||
mac.span(),
|
{
|
||||||
&format!("using `{}!()` with a format string that ends in a single newline", name),
|
let (replacement, replace_raw) = match lit.node {
|
||||||
|err| {
|
LitKind::Str(..) => extract_str_literal(&value_string),
|
||||||
err.multipart_suggestion(
|
LitKind::Char(ch) => (
|
||||||
&format!("use `{}!` instead", suggested),
|
match ch {
|
||||||
vec![(mac.path.span, suggested), (newline_span(&fmt_str).0, String::new())],
|
'"' => "\\\"",
|
||||||
|
'\'' => "'",
|
||||||
|
_ => &value_string[1..value_string.len() - 1],
|
||||||
|
}
|
||||||
|
.to_string(),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
LitKind::Bool(b) => (b.to_string(), false),
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
let lint = if name.starts_with("write") {
|
||||||
|
WRITE_LITERAL
|
||||||
|
} else {
|
||||||
|
PRINT_LITERAL
|
||||||
|
};
|
||||||
|
|
||||||
|
let format_string_is_raw = format_args.format_string.style.is_some();
|
||||||
|
let replacement = match (format_string_is_raw, replace_raw) {
|
||||||
|
(false, false) => Some(replacement),
|
||||||
|
(false, true) => Some(replacement.replace('"', "\\\"").replace('\\', "\\\\")),
|
||||||
|
(true, false) => match conservative_unescape(&replacement) {
|
||||||
|
Ok(unescaped) => Some(unescaped),
|
||||||
|
Err(UnescapeErr::Lint) => None,
|
||||||
|
Err(UnescapeErr::Ignore) => continue,
|
||||||
|
},
|
||||||
|
(true, true) => {
|
||||||
|
if replacement.contains(['#', '"']) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(replacement)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
span_lint_and_then(
|
||||||
|
cx,
|
||||||
|
lint,
|
||||||
|
value.span,
|
||||||
|
"literal with an empty format string",
|
||||||
|
|diag| {
|
||||||
|
if let Some(replacement) = replacement {
|
||||||
|
// `format!("{}", "a")`, `format!("{named}", named = "b")
|
||||||
|
// ~~~~~ ~~~~~~~~~~~~~
|
||||||
|
let value_span = expand_past_previous_comma(cx, value.span);
|
||||||
|
|
||||||
|
let replacement = replacement.replace('{', "{{").replace('}', "}}");
|
||||||
|
diag.multipart_suggestion(
|
||||||
|
"try this",
|
||||||
|
vec![(arg.span, replacement), (value_span, String::new())],
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
);
|
},
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the format string contains a single newline that terminates it.
|
/// Removes the raw marker, `#`s and quotes from a str, and returns if the literal is raw
|
||||||
///
|
///
|
||||||
/// Literal and escaped newlines are both checked (only literal for raw strings).
|
/// `r#"a"#` -> (`a`, true)
|
||||||
fn check_newlines(fmtstr: &StrLit) -> bool {
|
///
|
||||||
let mut has_internal_newline = false;
|
/// `"b"` -> (`b`, false)
|
||||||
let mut last_was_cr = false;
|
fn extract_str_literal(literal: &str) -> (String, bool) {
|
||||||
let mut should_lint = false;
|
let (literal, raw) = match literal.strip_prefix('r') {
|
||||||
|
Some(stripped) => (stripped.trim_matches('#'), true),
|
||||||
let contents = fmtstr.symbol.as_str();
|
None => (literal, false),
|
||||||
|
|
||||||
let mut cb = |r: Range<usize>, c: Result<char, EscapeError>| {
|
|
||||||
let c = match c {
|
|
||||||
Ok(c) => c,
|
|
||||||
Err(e) if !e.is_fatal() => return,
|
|
||||||
Err(e) => panic!("{:?}", e),
|
|
||||||
};
|
|
||||||
|
|
||||||
if r.end == contents.len() && c == '\n' && !last_was_cr && !has_internal_newline {
|
|
||||||
should_lint = true;
|
|
||||||
} else {
|
|
||||||
last_was_cr = c == '\r';
|
|
||||||
if c == '\n' {
|
|
||||||
has_internal_newline = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match fmtstr.style {
|
(literal[1..literal.len() - 1].to_string(), raw)
|
||||||
StrStyle::Cooked => unescape::unescape_literal(contents, unescape::Mode::Str, &mut cb),
|
}
|
||||||
StrStyle::Raw(_) => unescape::unescape_literal(contents, unescape::Mode::RawStr, &mut cb),
|
|
||||||
|
enum UnescapeErr {
|
||||||
|
/// Should still be linted, can be manually resolved by author, e.g.
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// print!(r"{}", '"');
|
||||||
|
/// ```
|
||||||
|
Lint,
|
||||||
|
/// Should not be linted, e.g.
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// print!(r"{}", '\r');
|
||||||
|
/// ```
|
||||||
|
Ignore,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unescape a normal string into a raw string
|
||||||
|
fn conservative_unescape(literal: &str) -> Result<String, UnescapeErr> {
|
||||||
|
let mut unescaped = String::with_capacity(literal.len());
|
||||||
|
let mut chars = literal.chars();
|
||||||
|
let mut err = false;
|
||||||
|
|
||||||
|
while let Some(ch) = chars.next() {
|
||||||
|
match ch {
|
||||||
|
'#' => err = true,
|
||||||
|
'\\' => match chars.next() {
|
||||||
|
Some('\\') => unescaped.push('\\'),
|
||||||
|
Some('"') => err = true,
|
||||||
|
_ => return Err(UnescapeErr::Ignore),
|
||||||
|
},
|
||||||
|
_ => unescaped.push(ch),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
should_lint
|
if err { Err(UnescapeErr::Lint) } else { Ok(unescaped) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand from `writeln!(o, "")` to `writeln!(o, "")`
|
||||||
|
// ^^ ^^^^
|
||||||
|
fn expand_past_previous_comma(cx: &LateContext<'_>, span: Span) -> Span {
|
||||||
|
let extended = cx.sess().source_map().span_extend_to_prev_char(span, ',', true);
|
||||||
|
extended.with_lo(extended.lo() - BytePos(1))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -501,8 +501,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
|||||||
BinOpKind::Mul => l.checked_mul(r).map(zext),
|
BinOpKind::Mul => l.checked_mul(r).map(zext),
|
||||||
BinOpKind::Div if r != 0 => l.checked_div(r).map(zext),
|
BinOpKind::Div if r != 0 => l.checked_div(r).map(zext),
|
||||||
BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext),
|
BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext),
|
||||||
BinOpKind::Shr => l.checked_shr(r.try_into().expect("invalid shift")).map(zext),
|
BinOpKind::Shr => l.checked_shr(r.try_into().ok()?).map(zext),
|
||||||
BinOpKind::Shl => l.checked_shl(r.try_into().expect("invalid shift")).map(zext),
|
BinOpKind::Shl => l.checked_shl(r.try_into().ok()?).map(zext),
|
||||||
BinOpKind::BitXor => Some(zext(l ^ r)),
|
BinOpKind::BitXor => Some(zext(l ^ r)),
|
||||||
BinOpKind::BitOr => Some(zext(l | r)),
|
BinOpKind::BitOr => Some(zext(l | r)),
|
||||||
BinOpKind::BitAnd => Some(zext(l & r)),
|
BinOpKind::BitAnd => Some(zext(l & r)),
|
||||||
@@ -521,8 +521,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
|||||||
BinOpKind::Mul => l.checked_mul(r).map(Constant::Int),
|
BinOpKind::Mul => l.checked_mul(r).map(Constant::Int),
|
||||||
BinOpKind::Div => l.checked_div(r).map(Constant::Int),
|
BinOpKind::Div => l.checked_div(r).map(Constant::Int),
|
||||||
BinOpKind::Rem => l.checked_rem(r).map(Constant::Int),
|
BinOpKind::Rem => l.checked_rem(r).map(Constant::Int),
|
||||||
BinOpKind::Shr => l.checked_shr(r.try_into().expect("shift too large")).map(Constant::Int),
|
BinOpKind::Shr => l.checked_shr(r.try_into().ok()?).map(Constant::Int),
|
||||||
BinOpKind::Shl => l.checked_shl(r.try_into().expect("shift too large")).map(Constant::Int),
|
BinOpKind::Shl => l.checked_shl(r.try_into().ok()?).map(Constant::Int),
|
||||||
BinOpKind::BitXor => Some(Constant::Int(l ^ r)),
|
BinOpKind::BitXor => Some(Constant::Int(l ^ r)),
|
||||||
BinOpKind::BitOr => Some(Constant::Int(l | r)),
|
BinOpKind::BitOr => Some(Constant::Int(l | r)),
|
||||||
BinOpKind::BitAnd => Some(Constant::Int(l & r)),
|
BinOpKind::BitAnd => Some(Constant::Int(l & r)),
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use crate::visitors::expr_visitor_no_bodies;
|
|||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use itertools::{izip, Either, Itertools};
|
use itertools::{izip, Either, Itertools};
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||||
use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
|
use rustc_hir::{self as hir, Expr, ExprField, ExprKind, HirId, Node, QPath};
|
||||||
use rustc_lexer::unescape::unescape_literal;
|
use rustc_lexer::unescape::unescape_literal;
|
||||||
use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
|
use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@@ -485,64 +485,49 @@ struct ParamPosition {
|
|||||||
precision: Option<usize>,
|
precision: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the `fmt` arg of `Arguments::new_v1_formatted(pieces, args, fmt, _)`
|
impl<'tcx> Visitor<'tcx> for ParamPosition {
|
||||||
fn parse_rt_fmt<'tcx>(fmt_arg: &'tcx Expr<'tcx>) -> Option<impl Iterator<Item = ParamPosition> + 'tcx> {
|
fn visit_expr_field(&mut self, field: &'tcx ExprField<'tcx>) {
|
||||||
fn parse_count(expr: &Expr<'_>) -> Option<usize> {
|
fn parse_count(expr: &Expr<'_>) -> Option<usize> {
|
||||||
// ::core::fmt::rt::v1::Count::Param(1usize),
|
// ::core::fmt::rt::v1::Count::Param(1usize),
|
||||||
if let ExprKind::Call(ctor, [val]) = expr.kind
|
if let ExprKind::Call(ctor, [val]) = expr.kind
|
||||||
&& let ExprKind::Path(QPath::Resolved(_, path)) = ctor.kind
|
&& let ExprKind::Path(QPath::Resolved(_, path)) = ctor.kind
|
||||||
&& path.segments.last()?.ident.name == sym::Param
|
&& path.segments.last()?.ident.name == sym::Param
|
||||||
&& let ExprKind::Lit(lit) = &val.kind
|
&& let ExprKind::Lit(lit) = &val.kind
|
||||||
&& let LitKind::Int(pos, _) = lit.node
|
&& let LitKind::Int(pos, _) = lit.node
|
||||||
{
|
{
|
||||||
Some(pos as usize)
|
Some(pos as usize)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match field.ident.name {
|
||||||
|
sym::position => {
|
||||||
|
if let ExprKind::Lit(lit) = &field.expr.kind
|
||||||
|
&& let LitKind::Int(pos, _) = lit.node
|
||||||
|
{
|
||||||
|
self.value = pos as usize;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sym::precision => {
|
||||||
|
self.precision = parse_count(field.expr);
|
||||||
|
},
|
||||||
|
sym::width => {
|
||||||
|
self.width = parse_count(field.expr);
|
||||||
|
},
|
||||||
|
_ => walk_expr(self, field.expr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses the `fmt` arg of `Arguments::new_v1_formatted(pieces, args, fmt, _)`
|
||||||
|
fn parse_rt_fmt<'tcx>(fmt_arg: &'tcx Expr<'tcx>) -> Option<impl Iterator<Item = ParamPosition> + 'tcx> {
|
||||||
if let ExprKind::AddrOf(.., array) = fmt_arg.kind
|
if let ExprKind::AddrOf(.., array) = fmt_arg.kind
|
||||||
&& let ExprKind::Array(specs) = array.kind
|
&& let ExprKind::Array(specs) = array.kind
|
||||||
{
|
{
|
||||||
Some(specs.iter().map(|spec| {
|
Some(specs.iter().map(|spec| {
|
||||||
let mut position = ParamPosition::default();
|
let mut position = ParamPosition::default();
|
||||||
|
position.visit_expr(spec);
|
||||||
// ::core::fmt::rt::v1::Argument {
|
|
||||||
// position: 0usize,
|
|
||||||
// format: ::core::fmt::rt::v1::FormatSpec {
|
|
||||||
// ..
|
|
||||||
// precision: ::core::fmt::rt::v1::Count::Implied,
|
|
||||||
// width: ::core::fmt::rt::v1::Count::Implied,
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO: this can be made much nicer next sync with `Visitor::visit_expr_field`
|
|
||||||
if let ExprKind::Struct(_, fields, _) = spec.kind {
|
|
||||||
for field in fields {
|
|
||||||
match (field.ident.name, &field.expr.kind) {
|
|
||||||
(sym::position, ExprKind::Lit(lit)) => {
|
|
||||||
if let LitKind::Int(pos, _) = lit.node {
|
|
||||||
position.value = pos as usize;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(sym::format, &ExprKind::Struct(_, spec_fields, _)) => {
|
|
||||||
for spec_field in spec_fields {
|
|
||||||
match spec_field.ident.name {
|
|
||||||
sym::precision => {
|
|
||||||
position.precision = parse_count(spec_field.expr);
|
|
||||||
},
|
|
||||||
sym::width => {
|
|
||||||
position.width = parse_count(spec_field.expr);
|
|
||||||
},
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
position
|
position
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
@@ -711,9 +696,14 @@ impl<'tcx> FormatSpec<'tcx> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this format spec would change the contents of a string when formatted
|
/// Returns true if this format spec is unchanged from the default. e.g. returns true for `{}`,
|
||||||
pub fn has_string_formatting(&self) -> bool {
|
/// `{foo}` and `{2}`, but false for `{:?}`, `{foo:5}` and `{3:.5}`
|
||||||
self.r#trait != sym::Display || !self.width.is_implied() || !self.precision.is_implied()
|
pub fn is_default(&self) -> bool {
|
||||||
|
self.r#trait == sym::Display
|
||||||
|
&& self.width.is_implied()
|
||||||
|
&& self.precision.is_implied()
|
||||||
|
&& self.align == Alignment::AlignUnknown
|
||||||
|
&& self.flags == 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use std::fmt::{Display, Write as _};
|
|||||||
use std::ops::{Add, Neg, Not, Sub};
|
use std::ops::{Add, Neg, Not, Sub};
|
||||||
|
|
||||||
/// A helper type to build suggestion correctly handling parentheses.
|
/// A helper type to build suggestion correctly handling parentheses.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Sugg<'a> {
|
pub enum Sugg<'a> {
|
||||||
/// An expression that never needs parentheses such as `1337` or `[0; 42]`.
|
/// An expression that never needs parentheses such as `1337` or `[0; 42]`.
|
||||||
NonParen(Cow<'a, str>),
|
NonParen(Cow<'a, str>),
|
||||||
@@ -155,8 +155,8 @@ impl<'a> Sugg<'a> {
|
|||||||
| hir::ExprKind::Ret(..)
|
| hir::ExprKind::Ret(..)
|
||||||
| hir::ExprKind::Struct(..)
|
| hir::ExprKind::Struct(..)
|
||||||
| hir::ExprKind::Tup(..)
|
| hir::ExprKind::Tup(..)
|
||||||
| hir::ExprKind::DropTemps(_)
|
|
||||||
| hir::ExprKind::Err => Sugg::NonParen(get_snippet(expr.span)),
|
| hir::ExprKind::Err => Sugg::NonParen(get_snippet(expr.span)),
|
||||||
|
hir::ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
|
||||||
hir::ExprKind::Assign(lhs, rhs, _) => {
|
hir::ExprKind::Assign(lhs, rhs, _) => {
|
||||||
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
|
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
|
||||||
},
|
},
|
||||||
@@ -177,11 +177,11 @@ impl<'a> Sugg<'a> {
|
|||||||
pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self {
|
pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self {
|
||||||
use rustc_ast::ast::RangeLimits;
|
use rustc_ast::ast::RangeLimits;
|
||||||
|
|
||||||
let get_whole_snippet = || {
|
let snippet_without_expansion = |cx, span: Span, default| {
|
||||||
if expr.span.from_expansion() {
|
if span.from_expansion() {
|
||||||
snippet_with_macro_callsite(cx, expr.span, default)
|
snippet_with_macro_callsite(cx, span, default)
|
||||||
} else {
|
} else {
|
||||||
snippet(cx, expr.span, default)
|
snippet(cx, span, default)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ impl<'a> Sugg<'a> {
|
|||||||
| ast::ExprKind::If(..)
|
| ast::ExprKind::If(..)
|
||||||
| ast::ExprKind::Let(..)
|
| ast::ExprKind::Let(..)
|
||||||
| ast::ExprKind::Unary(..)
|
| ast::ExprKind::Unary(..)
|
||||||
| ast::ExprKind::Match(..) => Sugg::MaybeParen(get_whole_snippet()),
|
| ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet_without_expansion(cx, expr.span, default)),
|
||||||
ast::ExprKind::Async(..)
|
ast::ExprKind::Async(..)
|
||||||
| ast::ExprKind::Block(..)
|
| ast::ExprKind::Block(..)
|
||||||
| ast::ExprKind::Break(..)
|
| ast::ExprKind::Break(..)
|
||||||
@@ -221,41 +221,45 @@ impl<'a> Sugg<'a> {
|
|||||||
| ast::ExprKind::Array(..)
|
| ast::ExprKind::Array(..)
|
||||||
| ast::ExprKind::While(..)
|
| ast::ExprKind::While(..)
|
||||||
| ast::ExprKind::Await(..)
|
| ast::ExprKind::Await(..)
|
||||||
| ast::ExprKind::Err => Sugg::NonParen(get_whole_snippet()),
|
| ast::ExprKind::Err => Sugg::NonParen(snippet_without_expansion(cx, expr.span, default)),
|
||||||
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
|
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
|
||||||
AssocOp::DotDot,
|
AssocOp::DotDot,
|
||||||
lhs.as_ref().map_or("".into(), |lhs| snippet(cx, lhs.span, default)),
|
lhs.as_ref()
|
||||||
rhs.as_ref().map_or("".into(), |rhs| snippet(cx, rhs.span, default)),
|
.map_or("".into(), |lhs| snippet_without_expansion(cx, lhs.span, default)),
|
||||||
|
rhs.as_ref()
|
||||||
|
.map_or("".into(), |rhs| snippet_without_expansion(cx, rhs.span, default)),
|
||||||
),
|
),
|
||||||
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
|
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
|
||||||
AssocOp::DotDotEq,
|
AssocOp::DotDotEq,
|
||||||
lhs.as_ref().map_or("".into(), |lhs| snippet(cx, lhs.span, default)),
|
lhs.as_ref()
|
||||||
rhs.as_ref().map_or("".into(), |rhs| snippet(cx, rhs.span, default)),
|
.map_or("".into(), |lhs| snippet_without_expansion(cx, lhs.span, default)),
|
||||||
|
rhs.as_ref()
|
||||||
|
.map_or("".into(), |rhs| snippet_without_expansion(cx, rhs.span, default)),
|
||||||
),
|
),
|
||||||
ast::ExprKind::Assign(ref lhs, ref rhs, _) => Sugg::BinOp(
|
ast::ExprKind::Assign(ref lhs, ref rhs, _) => Sugg::BinOp(
|
||||||
AssocOp::Assign,
|
AssocOp::Assign,
|
||||||
snippet(cx, lhs.span, default),
|
snippet_without_expansion(cx, lhs.span, default),
|
||||||
snippet(cx, rhs.span, default),
|
snippet_without_expansion(cx, rhs.span, default),
|
||||||
),
|
),
|
||||||
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
|
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
|
||||||
astbinop2assignop(op),
|
astbinop2assignop(op),
|
||||||
snippet(cx, lhs.span, default),
|
snippet_without_expansion(cx, lhs.span, default),
|
||||||
snippet(cx, rhs.span, default),
|
snippet_without_expansion(cx, rhs.span, default),
|
||||||
),
|
),
|
||||||
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
|
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
|
||||||
AssocOp::from_ast_binop(op.node),
|
AssocOp::from_ast_binop(op.node),
|
||||||
snippet(cx, lhs.span, default),
|
snippet_without_expansion(cx, lhs.span, default),
|
||||||
snippet(cx, rhs.span, default),
|
snippet_without_expansion(cx, rhs.span, default),
|
||||||
),
|
),
|
||||||
ast::ExprKind::Cast(ref lhs, ref ty) => Sugg::BinOp(
|
ast::ExprKind::Cast(ref lhs, ref ty) => Sugg::BinOp(
|
||||||
AssocOp::As,
|
AssocOp::As,
|
||||||
snippet(cx, lhs.span, default),
|
snippet_without_expansion(cx, lhs.span, default),
|
||||||
snippet(cx, ty.span, default),
|
snippet_without_expansion(cx, ty.span, default),
|
||||||
),
|
),
|
||||||
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
|
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
|
||||||
AssocOp::Colon,
|
AssocOp::Colon,
|
||||||
snippet(cx, lhs.span, default),
|
snippet_without_expansion(cx, lhs.span, default),
|
||||||
snippet(cx, ty.span, default),
|
snippet_without_expansion(cx, ty.span, default),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,13 @@ pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
|||||||
ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env)
|
ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This checks whether a given type is known to implement Debug.
|
||||||
|
pub fn has_debug_impl<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
|
cx.tcx
|
||||||
|
.get_diagnostic_item(sym::Debug)
|
||||||
|
.map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks whether a type can be partially moved.
|
/// Checks whether a type can be partially moved.
|
||||||
pub fn can_partially_move_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
pub fn can_partially_move_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
if has_drop(cx, ty) || is_copy(cx, ty) {
|
if has_drop(cx, ty) || is_copy(cx, ty) {
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ docs! {
|
|||||||
"items_after_statements",
|
"items_after_statements",
|
||||||
"iter_cloned_collect",
|
"iter_cloned_collect",
|
||||||
"iter_count",
|
"iter_count",
|
||||||
|
"iter_kv_map",
|
||||||
"iter_next_loop",
|
"iter_next_loop",
|
||||||
"iter_next_slice",
|
"iter_next_slice",
|
||||||
"iter_not_returning_iterator",
|
"iter_not_returning_iterator",
|
||||||
@@ -391,7 +392,6 @@ docs! {
|
|||||||
"partialeq_to_none",
|
"partialeq_to_none",
|
||||||
"path_buf_push_overwrite",
|
"path_buf_push_overwrite",
|
||||||
"pattern_type_mismatch",
|
"pattern_type_mismatch",
|
||||||
"positional_named_format_parameters",
|
|
||||||
"possible_missing_comma",
|
"possible_missing_comma",
|
||||||
"precedence",
|
"precedence",
|
||||||
"print_in_format_impl",
|
"print_in_format_impl",
|
||||||
|
|||||||
22
src/docs/iter_kv_map.txt
Normal file
22
src/docs/iter_kv_map.txt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
### What it does
|
||||||
|
|
||||||
|
Checks for iterating a map (`HashMap` or `BTreeMap`) and
|
||||||
|
ignoring either the keys or values.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
|
||||||
|
Readability. There are `keys` and `values` methods that
|
||||||
|
can be used to express that we only need the keys or the values.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```
|
||||||
|
let map: HashMap<u32, u32> = HashMap::new();
|
||||||
|
let values = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```
|
||||||
|
let map: HashMap<u32, u32> = HashMap::new();
|
||||||
|
let values = map.values().collect::<Vec<_>>();
|
||||||
|
```
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
### What it does
|
|
||||||
This lint warns when a named parameter in a format string is used as a positional one.
|
|
||||||
|
|
||||||
### Why is this bad?
|
|
||||||
It may be confused for an assignment and obfuscates which parameter is being used.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
```
|
|
||||||
println!("{}", x = 10);
|
|
||||||
```
|
|
||||||
|
|
||||||
Use instead:
|
|
||||||
```
|
|
||||||
println!("{x}", x = 10);
|
|
||||||
```
|
|
||||||
@@ -6,10 +6,6 @@ Using literals as `println!` args is inefficient
|
|||||||
(c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
|
(c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
|
||||||
(i.e., just put the literal in the format string)
|
(i.e., just put the literal in the format string)
|
||||||
|
|
||||||
### Known problems
|
|
||||||
Will also warn with macro calls as arguments that expand to literals
|
|
||||||
-- e.g., `println!("{}", env!("FOO"))`.
|
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
```
|
```
|
||||||
println!("{}", "foo");
|
println!("{}", "foo");
|
||||||
|
|||||||
@@ -7,13 +7,7 @@ People often print on *stderr* while debugging an
|
|||||||
application and might forget to remove those prints afterward.
|
application and might forget to remove those prints afterward.
|
||||||
|
|
||||||
### Known problems
|
### Known problems
|
||||||
* Only catches `eprint!` and `eprintln!` calls.
|
Only catches `eprint!` and `eprintln!` calls.
|
||||||
* The lint level is unaffected by crate attributes. The level can still
|
|
||||||
be set for functions, modules and other items. To change the level for
|
|
||||||
the entire crate, please use command line flags. More information and a
|
|
||||||
configuration example can be found in [clippy#6610].
|
|
||||||
|
|
||||||
[clippy#6610]: https://github.com/rust-lang/rust-clippy/issues/6610#issuecomment-977120558
|
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -7,13 +7,7 @@ People often print on *stdout* while debugging an
|
|||||||
application and might forget to remove those prints afterward.
|
application and might forget to remove those prints afterward.
|
||||||
|
|
||||||
### Known problems
|
### Known problems
|
||||||
* Only catches `print!` and `println!` calls.
|
Only catches `print!` and `println!` calls.
|
||||||
* The lint level is unaffected by crate attributes. The level can still
|
|
||||||
be set for functions, modules and other items. To change the level for
|
|
||||||
the entire crate, please use command line flags. More information and a
|
|
||||||
configuration example can be found in [clippy#6610].
|
|
||||||
|
|
||||||
[clippy#6610]: https://github.com/rust-lang/rust-clippy/issues/6610#issuecomment-977120558
|
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -6,10 +6,6 @@ Using literals as `writeln!` args is inefficient
|
|||||||
(c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
|
(c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
|
||||||
(i.e., just put the literal in the format string)
|
(i.e., just put the literal in the format string)
|
||||||
|
|
||||||
### Known problems
|
|
||||||
Will also warn with macro calls as arguments that expand to literals
|
|
||||||
-- e.g., `writeln!(buf, "{}", env!("FOO"))`.
|
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
```
|
```
|
||||||
writeln!(buf, "{}", "foo");
|
writeln!(buf, "{}", "foo");
|
||||||
|
|||||||
9
tests/ui-cargo/module_style/fail_mod_remap/Cargo.toml
Normal file
9
tests/ui-cargo/module_style/fail_mod_remap/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "fail-mod-remap"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
1
tests/ui-cargo/module_style/fail_mod_remap/src/bad.rs
Normal file
1
tests/ui-cargo/module_style/fail_mod_remap/src/bad.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod inner;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
7
tests/ui-cargo/module_style/fail_mod_remap/src/main.rs
Normal file
7
tests/ui-cargo/module_style/fail_mod_remap/src/main.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// compile-flags: --remap-path-prefix {{src-base}}=/remapped
|
||||||
|
|
||||||
|
#![warn(clippy::self_named_module_files)]
|
||||||
|
|
||||||
|
mod bad;
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
11
tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr
Normal file
11
tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
error: `mod.rs` files are required, found `bad.rs`
|
||||||
|
--> /remapped/module_style/fail_mod_remap/src/bad.rs:1:1
|
||||||
|
|
|
||||||
|
LL | pub mod inner;
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: `-D clippy::self-named-module-files` implied by `-D warnings`
|
||||||
|
= help: move `bad.rs` to `bad/mod.rs`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
@@ -42,6 +42,7 @@ macro_rules! printlnfoo {
|
|||||||
fn main() {
|
fn main() {
|
||||||
let _ = vec! {1, 2, 3};
|
let _ = vec! {1, 2, 3};
|
||||||
let _ = format!["ugh {} stop being such a good compiler", "hello"];
|
let _ = format!["ugh {} stop being such a good compiler", "hello"];
|
||||||
|
let _ = matches!{{}, ()};
|
||||||
let _ = quote!(let x = 1;);
|
let _ = quote!(let x = 1;);
|
||||||
let _ = quote::quote!(match match match);
|
let _ = quote::quote!(match match match);
|
||||||
let _ = test!(); // trigger when macro def is inside our own crate
|
let _ = test!(); // trigger when macro def is inside our own crate
|
||||||
|
|||||||
@@ -23,26 +23,38 @@ help: consider writing `format!("ugh () stop being such a good compiler", "hello
|
|||||||
LL | let _ = format!["ugh {} stop being such a good compiler", "hello"];
|
LL | let _ = format!["ugh {} stop being such a good compiler", "hello"];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: use of irregular braces for `quote!` macro
|
error: use of irregular braces for `matches!` macro
|
||||||
--> $DIR/conf_nonstandard_macro_braces.rs:45:13
|
--> $DIR/conf_nonstandard_macro_braces.rs:45:13
|
||||||
|
|
|
|
||||||
|
LL | let _ = matches!{{}, ()};
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: consider writing `matches!((), ())`
|
||||||
|
--> $DIR/conf_nonstandard_macro_braces.rs:45:13
|
||||||
|
|
|
||||||
|
LL | let _ = matches!{{}, ()};
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: use of irregular braces for `quote!` macro
|
||||||
|
--> $DIR/conf_nonstandard_macro_braces.rs:46:13
|
||||||
|
|
|
||||||
LL | let _ = quote!(let x = 1;);
|
LL | let _ = quote!(let x = 1;);
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider writing `quote! {let x = 1;}`
|
help: consider writing `quote! {let x = 1;}`
|
||||||
--> $DIR/conf_nonstandard_macro_braces.rs:45:13
|
--> $DIR/conf_nonstandard_macro_braces.rs:46:13
|
||||||
|
|
|
|
||||||
LL | let _ = quote!(let x = 1;);
|
LL | let _ = quote!(let x = 1;);
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: use of irregular braces for `quote::quote!` macro
|
error: use of irregular braces for `quote::quote!` macro
|
||||||
--> $DIR/conf_nonstandard_macro_braces.rs:46:13
|
--> $DIR/conf_nonstandard_macro_braces.rs:47:13
|
||||||
|
|
|
|
||||||
LL | let _ = quote::quote!(match match match);
|
LL | let _ = quote::quote!(match match match);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider writing `quote::quote! {match match match}`
|
help: consider writing `quote::quote! {match match match}`
|
||||||
--> $DIR/conf_nonstandard_macro_braces.rs:46:13
|
--> $DIR/conf_nonstandard_macro_braces.rs:47:13
|
||||||
|
|
|
|
||||||
LL | let _ = quote::quote!(match match match);
|
LL | let _ = quote::quote!(match match match);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@@ -67,28 +79,28 @@ LL | let _ = test!(); // trigger when macro def is inside our own crate
|
|||||||
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: use of irregular braces for `type_pos!` macro
|
error: use of irregular braces for `type_pos!` macro
|
||||||
--> $DIR/conf_nonstandard_macro_braces.rs:55:12
|
--> $DIR/conf_nonstandard_macro_braces.rs:56:12
|
||||||
|
|
|
|
||||||
LL | let _: type_pos!(usize) = vec![];
|
LL | let _: type_pos!(usize) = vec![];
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider writing `type_pos![usize]`
|
help: consider writing `type_pos![usize]`
|
||||||
--> $DIR/conf_nonstandard_macro_braces.rs:55:12
|
--> $DIR/conf_nonstandard_macro_braces.rs:56:12
|
||||||
|
|
|
|
||||||
LL | let _: type_pos!(usize) = vec![];
|
LL | let _: type_pos!(usize) = vec![];
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: use of irregular braces for `eprint!` macro
|
error: use of irregular braces for `eprint!` macro
|
||||||
--> $DIR/conf_nonstandard_macro_braces.rs:57:5
|
--> $DIR/conf_nonstandard_macro_braces.rs:58:5
|
||||||
|
|
|
|
||||||
LL | eprint!("test if user config overrides defaults");
|
LL | eprint!("test if user config overrides defaults");
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider writing `eprint!["test if user config overrides defaults"]`
|
help: consider writing `eprint!["test if user config overrides defaults"]`
|
||||||
--> $DIR/conf_nonstandard_macro_braces.rs:57:5
|
--> $DIR/conf_nonstandard_macro_braces.rs:58:5
|
||||||
|
|
|
|
||||||
LL | eprint!("test if user config overrides defaults");
|
LL | eprint!("test if user config overrides defaults");
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// run-rustfix
|
// run-rustfix
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
// aux-build:macro_rules.rs
|
||||||
|
|
||||||
#![feature(custom_inner_attributes)]
|
#![feature(custom_inner_attributes)]
|
||||||
#![feature(exclusive_range_pattern)]
|
#![feature(exclusive_range_pattern)]
|
||||||
@@ -8,12 +9,21 @@
|
|||||||
#![allow(ellipsis_inclusive_range_patterns)]
|
#![allow(ellipsis_inclusive_range_patterns)]
|
||||||
#![allow(clippy::needless_parens_on_range_literals)]
|
#![allow(clippy::needless_parens_on_range_literals)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate macro_rules;
|
||||||
|
|
||||||
macro_rules! a {
|
macro_rules! a {
|
||||||
() => {
|
() => {
|
||||||
'a'
|
'a'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! b {
|
||||||
|
() => {
|
||||||
|
let _ = 'a'..='z';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
{
|
{
|
||||||
@@ -47,6 +57,9 @@ fn main() {
|
|||||||
'B'..'Z' => 4,
|
'B'..'Z' => 4,
|
||||||
_ => 5,
|
_ => 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
almost_complete_letter_range!();
|
||||||
|
b!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _under_msrv() {
|
fn _under_msrv() {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// run-rustfix
|
// run-rustfix
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
// aux-build:macro_rules.rs
|
||||||
|
|
||||||
#![feature(custom_inner_attributes)]
|
#![feature(custom_inner_attributes)]
|
||||||
#![feature(exclusive_range_pattern)]
|
#![feature(exclusive_range_pattern)]
|
||||||
@@ -8,12 +9,21 @@
|
|||||||
#![allow(ellipsis_inclusive_range_patterns)]
|
#![allow(ellipsis_inclusive_range_patterns)]
|
||||||
#![allow(clippy::needless_parens_on_range_literals)]
|
#![allow(clippy::needless_parens_on_range_literals)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate macro_rules;
|
||||||
|
|
||||||
macro_rules! a {
|
macro_rules! a {
|
||||||
() => {
|
() => {
|
||||||
'a'
|
'a'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! b {
|
||||||
|
() => {
|
||||||
|
let _ = 'a'..'z';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
{
|
{
|
||||||
@@ -47,6 +57,9 @@ fn main() {
|
|||||||
'B'..'Z' => 4,
|
'B'..'Z' => 4,
|
||||||
_ => 5,
|
_ => 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
almost_complete_letter_range!();
|
||||||
|
b!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _under_msrv() {
|
fn _under_msrv() {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:20:17
|
--> $DIR/almost_complete_letter_range.rs:30:17
|
||||||
|
|
|
|
||||||
LL | let _ = ('a') ..'z';
|
LL | let _ = ('a') ..'z';
|
||||||
| ^^^^^^--^^^
|
| ^^^^^^--^^^
|
||||||
@@ -9,7 +9,7 @@ LL | let _ = ('a') ..'z';
|
|||||||
= note: `-D clippy::almost-complete-letter-range` implied by `-D warnings`
|
= note: `-D clippy::almost-complete-letter-range` implied by `-D warnings`
|
||||||
|
|
||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:21:17
|
--> $DIR/almost_complete_letter_range.rs:31:17
|
||||||
|
|
|
|
||||||
LL | let _ = 'A' .. ('Z');
|
LL | let _ = 'A' .. ('Z');
|
||||||
| ^^^^--^^^^^^
|
| ^^^^--^^^^^^
|
||||||
@@ -17,7 +17,7 @@ LL | let _ = 'A' .. ('Z');
|
|||||||
| help: use an inclusive range: `..=`
|
| help: use an inclusive range: `..=`
|
||||||
|
|
||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:27:13
|
--> $DIR/almost_complete_letter_range.rs:37:13
|
||||||
|
|
|
|
||||||
LL | let _ = (b'a')..(b'z');
|
LL | let _ = (b'a')..(b'z');
|
||||||
| ^^^^^^--^^^^^^
|
| ^^^^^^--^^^^^^
|
||||||
@@ -25,7 +25,7 @@ LL | let _ = (b'a')..(b'z');
|
|||||||
| help: use an inclusive range: `..=`
|
| help: use an inclusive range: `..=`
|
||||||
|
|
||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:28:13
|
--> $DIR/almost_complete_letter_range.rs:38:13
|
||||||
|
|
|
|
||||||
LL | let _ = b'A'..b'Z';
|
LL | let _ = b'A'..b'Z';
|
||||||
| ^^^^--^^^^
|
| ^^^^--^^^^
|
||||||
@@ -33,7 +33,7 @@ LL | let _ = b'A'..b'Z';
|
|||||||
| help: use an inclusive range: `..=`
|
| help: use an inclusive range: `..=`
|
||||||
|
|
||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:33:13
|
--> $DIR/almost_complete_letter_range.rs:43:13
|
||||||
|
|
|
|
||||||
LL | let _ = a!()..'z';
|
LL | let _ = a!()..'z';
|
||||||
| ^^^^--^^^
|
| ^^^^--^^^
|
||||||
@@ -41,7 +41,7 @@ LL | let _ = a!()..'z';
|
|||||||
| help: use an inclusive range: `..=`
|
| help: use an inclusive range: `..=`
|
||||||
|
|
||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:36:9
|
--> $DIR/almost_complete_letter_range.rs:46:9
|
||||||
|
|
|
|
||||||
LL | b'a'..b'z' if true => 1,
|
LL | b'a'..b'z' if true => 1,
|
||||||
| ^^^^--^^^^
|
| ^^^^--^^^^
|
||||||
@@ -49,7 +49,7 @@ LL | b'a'..b'z' if true => 1,
|
|||||||
| help: use an inclusive range: `..=`
|
| help: use an inclusive range: `..=`
|
||||||
|
|
||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:37:9
|
--> $DIR/almost_complete_letter_range.rs:47:9
|
||||||
|
|
|
|
||||||
LL | b'A'..b'Z' if true => 2,
|
LL | b'A'..b'Z' if true => 2,
|
||||||
| ^^^^--^^^^
|
| ^^^^--^^^^
|
||||||
@@ -57,7 +57,7 @@ LL | b'A'..b'Z' if true => 2,
|
|||||||
| help: use an inclusive range: `..=`
|
| help: use an inclusive range: `..=`
|
||||||
|
|
||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:44:9
|
--> $DIR/almost_complete_letter_range.rs:54:9
|
||||||
|
|
|
|
||||||
LL | 'a'..'z' if true => 1,
|
LL | 'a'..'z' if true => 1,
|
||||||
| ^^^--^^^
|
| ^^^--^^^
|
||||||
@@ -65,7 +65,7 @@ LL | 'a'..'z' if true => 1,
|
|||||||
| help: use an inclusive range: `..=`
|
| help: use an inclusive range: `..=`
|
||||||
|
|
||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:45:9
|
--> $DIR/almost_complete_letter_range.rs:55:9
|
||||||
|
|
|
|
||||||
LL | 'A'..'Z' if true => 2,
|
LL | 'A'..'Z' if true => 2,
|
||||||
| ^^^--^^^
|
| ^^^--^^^
|
||||||
@@ -73,7 +73,20 @@ LL | 'A'..'Z' if true => 2,
|
|||||||
| help: use an inclusive range: `..=`
|
| help: use an inclusive range: `..=`
|
||||||
|
|
||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:55:9
|
--> $DIR/almost_complete_letter_range.rs:23:17
|
||||||
|
|
|
||||||
|
LL | let _ = 'a'..'z';
|
||||||
|
| ^^^--^^^
|
||||||
|
| |
|
||||||
|
| help: use an inclusive range: `..=`
|
||||||
|
...
|
||||||
|
LL | b!();
|
||||||
|
| ---- in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: almost complete ascii letter range
|
||||||
|
--> $DIR/almost_complete_letter_range.rs:68:9
|
||||||
|
|
|
|
||||||
LL | 'a'..'z' => 1,
|
LL | 'a'..'z' => 1,
|
||||||
| ^^^--^^^
|
| ^^^--^^^
|
||||||
@@ -81,7 +94,7 @@ LL | 'a'..'z' => 1,
|
|||||||
| help: use an inclusive range: `...`
|
| help: use an inclusive range: `...`
|
||||||
|
|
||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:62:13
|
--> $DIR/almost_complete_letter_range.rs:75:13
|
||||||
|
|
|
|
||||||
LL | let _ = 'a'..'z';
|
LL | let _ = 'a'..'z';
|
||||||
| ^^^--^^^
|
| ^^^--^^^
|
||||||
@@ -89,12 +102,12 @@ LL | let _ = 'a'..'z';
|
|||||||
| help: use an inclusive range: `..=`
|
| help: use an inclusive range: `..=`
|
||||||
|
|
||||||
error: almost complete ascii letter range
|
error: almost complete ascii letter range
|
||||||
--> $DIR/almost_complete_letter_range.rs:64:9
|
--> $DIR/almost_complete_letter_range.rs:77:9
|
||||||
|
|
|
|
||||||
LL | 'a'..'z' => 1,
|
LL | 'a'..'z' => 1,
|
||||||
| ^^^--^^^
|
| ^^^--^^^
|
||||||
| |
|
| |
|
||||||
| help: use an inclusive range: `..=`
|
| help: use an inclusive range: `..=`
|
||||||
|
|
||||||
error: aborting due to 12 previous errors
|
error: aborting due to 13 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,49 @@
|
|||||||
#![allow(clippy::assign_op_pattern, clippy::unnecessary_owned_empty_strings)]
|
#![allow(
|
||||||
|
clippy::assign_op_pattern,
|
||||||
|
clippy::erasing_op,
|
||||||
|
clippy::identity_op,
|
||||||
|
clippy::unnecessary_owned_empty_strings,
|
||||||
|
arithmetic_overflow,
|
||||||
|
unconditional_panic
|
||||||
|
)]
|
||||||
#![feature(inline_const, saturating_int_impl)]
|
#![feature(inline_const, saturating_int_impl)]
|
||||||
#![warn(clippy::arithmetic_side_effects)]
|
#![warn(clippy::arithmetic_side_effects)]
|
||||||
|
|
||||||
use core::num::{Saturating, Wrapping};
|
use core::num::{Saturating, Wrapping};
|
||||||
|
|
||||||
|
pub fn association_with_structures_should_not_trigger_the_lint() {
|
||||||
|
enum Foo {
|
||||||
|
Bar = -2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for Foo {
|
||||||
|
const ASSOC: i32 = {
|
||||||
|
let _: [i32; 1 + 1];
|
||||||
|
fn foo() {}
|
||||||
|
1 + 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Baz([i32; 1 + 1]);
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
const ASSOC: i32 = 1 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Alias = [i32; 1 + 1];
|
||||||
|
|
||||||
|
union Qux {
|
||||||
|
field: [i32; 1 + 1],
|
||||||
|
}
|
||||||
|
|
||||||
|
let _: [i32; 1 + 1] = [0, 0];
|
||||||
|
|
||||||
|
let _: [i32; 1 + 1] = {
|
||||||
|
let a: [i32; 1 + 1] = [0, 0];
|
||||||
|
a
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn hard_coded_allowed() {
|
pub fn hard_coded_allowed() {
|
||||||
let _ = 1f32 + 1f32;
|
let _ = 1f32 + 1f32;
|
||||||
let _ = 1f64 + 1f64;
|
let _ = 1f64 + 1f64;
|
||||||
@@ -26,7 +66,7 @@ pub fn hard_coded_allowed() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub fn non_overflowing_ops() {
|
pub fn const_ops_should_not_trigger_the_lint() {
|
||||||
const _: i32 = { let mut n = 1; n += 1; n };
|
const _: i32 = { let mut n = 1; n += 1; n };
|
||||||
let _ = const { let mut n = 1; n += 1; n };
|
let _ = const { let mut n = 1; n += 1; n };
|
||||||
|
|
||||||
@@ -37,21 +77,63 @@ pub fn non_overflowing_ops() {
|
|||||||
let _ = const { let mut n = 1; n = 1 + n; n };
|
let _ = const { let mut n = 1; n = 1 + n; n };
|
||||||
|
|
||||||
const _: i32 = 1 + 1;
|
const _: i32 = 1 + 1;
|
||||||
let _ = 1 + 1;
|
|
||||||
let _ = const { 1 + 1 };
|
let _ = const { 1 + 1 };
|
||||||
|
|
||||||
let mut _a = 1;
|
const _: i32 = { let mut n = -1; n = -(-1); n = -n; n };
|
||||||
_a *= 1;
|
let _ = const { let mut n = -1; n = -(-1); n = -n; n };
|
||||||
_a /= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
pub fn non_overflowing_runtime_ops_or_ops_already_handled_by_the_compiler() {
|
||||||
pub fn overflowing_ops() {
|
let mut _n = i32::MAX;
|
||||||
let mut _a = 1; _a += 1;
|
|
||||||
|
|
||||||
let mut _b = 1; _b = _b + 1;
|
// Assign
|
||||||
|
_n += 0;
|
||||||
|
_n -= 0;
|
||||||
|
_n /= 99;
|
||||||
|
_n %= 99;
|
||||||
|
_n *= 0;
|
||||||
|
_n *= 1;
|
||||||
|
|
||||||
let mut _c = 1; _c = 1 + _c;
|
// Binary
|
||||||
|
_n = _n + 0;
|
||||||
|
_n = 0 + _n;
|
||||||
|
_n = _n - 0;
|
||||||
|
_n = 0 - _n;
|
||||||
|
_n = _n / 99;
|
||||||
|
_n = _n % 99;
|
||||||
|
_n = _n * 0;
|
||||||
|
_n = 0 * _n;
|
||||||
|
_n = _n * 1;
|
||||||
|
_n = 1 * _n;
|
||||||
|
_n = 23 + 85;
|
||||||
|
|
||||||
|
// Unary
|
||||||
|
_n = -1;
|
||||||
|
_n = -(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn overflowing_runtime_ops() {
|
||||||
|
let mut _n = i32::MAX;
|
||||||
|
|
||||||
|
// Assign
|
||||||
|
_n += 1;
|
||||||
|
_n -= 1;
|
||||||
|
_n /= 0;
|
||||||
|
_n %= 0;
|
||||||
|
_n *= 2;
|
||||||
|
|
||||||
|
// Binary
|
||||||
|
_n = _n + 1;
|
||||||
|
_n = 1 + _n;
|
||||||
|
_n = _n - 1;
|
||||||
|
_n = 1 - _n;
|
||||||
|
_n = _n / 0;
|
||||||
|
_n = _n % 0;
|
||||||
|
_n = _n * 2;
|
||||||
|
_n = 2 * _n;
|
||||||
|
|
||||||
|
// Unary
|
||||||
|
_n = -_n;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -1,22 +1,88 @@
|
|||||||
error: arithmetic detected
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
--> $DIR/arithmetic_side_effects.rs:50:21
|
--> $DIR/arithmetic_side_effects.rs:119:5
|
||||||
|
|
|
|
||||||
LL | let mut _a = 1; _a += 1;
|
LL | _n += 1;
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
|
= note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
|
||||||
|
|
||||||
error: arithmetic detected
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
--> $DIR/arithmetic_side_effects.rs:52:26
|
--> $DIR/arithmetic_side_effects.rs:120:5
|
||||||
|
|
|
|
||||||
LL | let mut _b = 1; _b = _b + 1;
|
LL | _n -= 1;
|
||||||
| ^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: arithmetic detected
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
--> $DIR/arithmetic_side_effects.rs:54:26
|
--> $DIR/arithmetic_side_effects.rs:121:5
|
||||||
|
|
|
|
||||||
LL | let mut _c = 1; _c = 1 + _c;
|
LL | _n /= 0;
|
||||||
| ^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
|
--> $DIR/arithmetic_side_effects.rs:122:5
|
||||||
|
|
|
||||||
|
LL | _n %= 0;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
|
--> $DIR/arithmetic_side_effects.rs:123:5
|
||||||
|
|
|
||||||
|
LL | _n *= 2;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
|
--> $DIR/arithmetic_side_effects.rs:126:10
|
||||||
|
|
|
||||||
|
LL | _n = _n + 1;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
|
--> $DIR/arithmetic_side_effects.rs:127:10
|
||||||
|
|
|
||||||
|
LL | _n = 1 + _n;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
|
--> $DIR/arithmetic_side_effects.rs:128:10
|
||||||
|
|
|
||||||
|
LL | _n = _n - 1;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
|
--> $DIR/arithmetic_side_effects.rs:129:10
|
||||||
|
|
|
||||||
|
LL | _n = 1 - _n;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
|
--> $DIR/arithmetic_side_effects.rs:130:10
|
||||||
|
|
|
||||||
|
LL | _n = _n / 0;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
|
--> $DIR/arithmetic_side_effects.rs:131:10
|
||||||
|
|
|
||||||
|
LL | _n = _n % 0;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
|
--> $DIR/arithmetic_side_effects.rs:132:10
|
||||||
|
|
|
||||||
|
LL | _n = _n * 2;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
|
--> $DIR/arithmetic_side_effects.rs:133:10
|
||||||
|
|
|
||||||
|
LL | _n = 2 * _n;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||||
|
--> $DIR/arithmetic_side_effects.rs:136:10
|
||||||
|
|
|
||||||
|
LL | _n = -_n;
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 14 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -75,3 +75,9 @@ fn main() {
|
|||||||
let r: Result<Foo, Foo> = Err(Foo);
|
let r: Result<Foo, Foo> = Err(Foo);
|
||||||
assert!(r.is_err());
|
assert!(r.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn issue9450() {
|
||||||
|
let res: Result<i32, i32> = Ok(1);
|
||||||
|
res.unwrap_err();
|
||||||
|
}
|
||||||
|
|||||||
@@ -75,3 +75,9 @@ fn main() {
|
|||||||
let r: Result<Foo, Foo> = Err(Foo);
|
let r: Result<Foo, Foo> = Err(Foo);
|
||||||
assert!(r.is_err());
|
assert!(r.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn issue9450() {
|
||||||
|
let res: Result<i32, i32> = Ok(1);
|
||||||
|
assert!(res.is_err())
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,5 +36,11 @@ error: called `assert!` with `Result::is_err`
|
|||||||
LL | assert!(r.is_err());
|
LL | assert!(r.is_err());
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap_err()`
|
| ^^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap_err()`
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: called `assert!` with `Result::is_err`
|
||||||
|
--> $DIR/assertions_on_result_states.rs:82:5
|
||||||
|
|
|
||||||
|
LL | assert!(res.is_err())
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ help: replace with: `res.unwrap_err();`
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -140,3 +140,10 @@ macro_rules! manual_rem_euclid {
|
|||||||
macro_rules! equatable_if_let {
|
macro_rules! equatable_if_let {
|
||||||
($a:ident) => {{ if let 2 = $a {} }};
|
($a:ident) => {{ if let 2 = $a {} }};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! almost_complete_letter_range {
|
||||||
|
() => {
|
||||||
|
let _ = 'a'..'z';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ fn main() {
|
|||||||
// precedence
|
// precedence
|
||||||
i32::from(a);
|
i32::from(a);
|
||||||
i32::from(!a);
|
i32::from(!a);
|
||||||
|
i32::from(!a);
|
||||||
i32::from(a || b);
|
i32::from(a || b);
|
||||||
i32::from(cond(a, b));
|
i32::from(cond(a, b));
|
||||||
i32::from(x + y < 4);
|
i32::from(x + y < 4);
|
||||||
@@ -21,7 +22,12 @@ fn main() {
|
|||||||
// if else if
|
// if else if
|
||||||
if a {
|
if a {
|
||||||
123
|
123
|
||||||
} else {i32::from(b)};
|
} else { i32::from(b) };
|
||||||
|
|
||||||
|
// if else if inverted
|
||||||
|
if a {
|
||||||
|
123
|
||||||
|
} else { i32::from(!b) };
|
||||||
|
|
||||||
// Shouldn't lint
|
// Shouldn't lint
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ fn main() {
|
|||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
if a {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
if !a {
|
if !a {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
@@ -47,6 +52,15 @@ fn main() {
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// if else if inverted
|
||||||
|
if a {
|
||||||
|
123
|
||||||
|
} else if b {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
// Shouldn't lint
|
// Shouldn't lint
|
||||||
|
|
||||||
if a {
|
if a {
|
||||||
|
|||||||
@@ -14,6 +14,18 @@ LL | | };
|
|||||||
error: boolean to int conversion using if
|
error: boolean to int conversion using if
|
||||||
--> $DIR/bool_to_int_with_if.rs:20:5
|
--> $DIR/bool_to_int_with_if.rs:20:5
|
||||||
|
|
|
|
||||||
|
LL | / if a {
|
||||||
|
LL | | 0
|
||||||
|
LL | | } else {
|
||||||
|
LL | | 1
|
||||||
|
LL | | };
|
||||||
|
| |_____^ help: replace with from: `i32::from(!a)`
|
||||||
|
|
|
||||||
|
= note: `!a as i32` or `(!a).into()` can also be valid options
|
||||||
|
|
||||||
|
error: boolean to int conversion using if
|
||||||
|
--> $DIR/bool_to_int_with_if.rs:25:5
|
||||||
|
|
|
||||||
LL | / if !a {
|
LL | / if !a {
|
||||||
LL | | 1
|
LL | | 1
|
||||||
LL | | } else {
|
LL | | } else {
|
||||||
@@ -21,10 +33,10 @@ LL | | 0
|
|||||||
LL | | };
|
LL | | };
|
||||||
| |_____^ help: replace with from: `i32::from(!a)`
|
| |_____^ help: replace with from: `i32::from(!a)`
|
||||||
|
|
|
|
||||||
= note: `!a as i32` or `!a.into()` can also be valid options
|
= note: `!a as i32` or `(!a).into()` can also be valid options
|
||||||
|
|
||||||
error: boolean to int conversion using if
|
error: boolean to int conversion using if
|
||||||
--> $DIR/bool_to_int_with_if.rs:25:5
|
--> $DIR/bool_to_int_with_if.rs:30:5
|
||||||
|
|
|
|
||||||
LL | / if a || b {
|
LL | / if a || b {
|
||||||
LL | | 1
|
LL | | 1
|
||||||
@@ -36,7 +48,7 @@ LL | | };
|
|||||||
= note: `(a || b) as i32` or `(a || b).into()` can also be valid options
|
= note: `(a || b) as i32` or `(a || b).into()` can also be valid options
|
||||||
|
|
||||||
error: boolean to int conversion using if
|
error: boolean to int conversion using if
|
||||||
--> $DIR/bool_to_int_with_if.rs:30:5
|
--> $DIR/bool_to_int_with_if.rs:35:5
|
||||||
|
|
|
|
||||||
LL | / if cond(a, b) {
|
LL | / if cond(a, b) {
|
||||||
LL | | 1
|
LL | | 1
|
||||||
@@ -48,7 +60,7 @@ LL | | };
|
|||||||
= note: `cond(a, b) as i32` or `cond(a, b).into()` can also be valid options
|
= note: `cond(a, b) as i32` or `cond(a, b).into()` can also be valid options
|
||||||
|
|
||||||
error: boolean to int conversion using if
|
error: boolean to int conversion using if
|
||||||
--> $DIR/bool_to_int_with_if.rs:35:5
|
--> $DIR/bool_to_int_with_if.rs:40:5
|
||||||
|
|
|
|
||||||
LL | / if x + y < 4 {
|
LL | / if x + y < 4 {
|
||||||
LL | | 1
|
LL | | 1
|
||||||
@@ -60,7 +72,7 @@ LL | | };
|
|||||||
= note: `(x + y < 4) as i32` or `(x + y < 4).into()` can also be valid options
|
= note: `(x + y < 4) as i32` or `(x + y < 4).into()` can also be valid options
|
||||||
|
|
||||||
error: boolean to int conversion using if
|
error: boolean to int conversion using if
|
||||||
--> $DIR/bool_to_int_with_if.rs:44:12
|
--> $DIR/bool_to_int_with_if.rs:49:12
|
||||||
|
|
|
|
||||||
LL | } else if b {
|
LL | } else if b {
|
||||||
| ____________^
|
| ____________^
|
||||||
@@ -68,17 +80,30 @@ LL | | 1
|
|||||||
LL | | } else {
|
LL | | } else {
|
||||||
LL | | 0
|
LL | | 0
|
||||||
LL | | };
|
LL | | };
|
||||||
| |_____^ help: replace with from: `{i32::from(b)}`
|
| |_____^ help: replace with from: `{ i32::from(b) }`
|
||||||
|
|
|
|
||||||
= note: `b as i32` or `b.into()` can also be valid options
|
= note: `b as i32` or `b.into()` can also be valid options
|
||||||
|
|
||||||
error: boolean to int conversion using if
|
error: boolean to int conversion using if
|
||||||
--> $DIR/bool_to_int_with_if.rs:102:5
|
--> $DIR/bool_to_int_with_if.rs:58:12
|
||||||
|
|
|
||||||
|
LL | } else if b {
|
||||||
|
| ____________^
|
||||||
|
LL | | 0
|
||||||
|
LL | | } else {
|
||||||
|
LL | | 1
|
||||||
|
LL | | };
|
||||||
|
| |_____^ help: replace with from: `{ i32::from(!b) }`
|
||||||
|
|
|
||||||
|
= note: `!b as i32` or `(!b).into()` can also be valid options
|
||||||
|
|
||||||
|
error: boolean to int conversion using if
|
||||||
|
--> $DIR/bool_to_int_with_if.rs:116:5
|
||||||
|
|
|
|
||||||
LL | if a { 1 } else { 0 }
|
LL | if a { 1 } else { 0 }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `u8::from(a)`
|
| ^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `u8::from(a)`
|
||||||
|
|
|
|
||||||
= note: `a as u8` or `a.into()` can also be valid options
|
= note: `a as u8` or `a.into()` can also be valid options
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,9 @@ fn main() {
|
|||||||
// Fix #5962
|
// Fix #5962
|
||||||
if matches!(true, true) && matches!(true, true) {}
|
if matches!(true, true) && matches!(true, true) {}
|
||||||
|
|
||||||
|
// Issue #9375
|
||||||
|
if matches!(true, true) && truth() && matches!(true, true) {}
|
||||||
|
|
||||||
if true {
|
if true {
|
||||||
#[cfg(not(teehee))]
|
#[cfg(not(teehee))]
|
||||||
if true {
|
if true {
|
||||||
|
|||||||
@@ -155,6 +155,11 @@ fn main() {
|
|||||||
if matches!(true, true) {}
|
if matches!(true, true) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #9375
|
||||||
|
if matches!(true, true) && truth() {
|
||||||
|
if matches!(true, true) {}
|
||||||
|
}
|
||||||
|
|
||||||
if true {
|
if true {
|
||||||
#[cfg(not(teehee))]
|
#[cfg(not(teehee))]
|
||||||
if true {
|
if true {
|
||||||
|
|||||||
@@ -126,5 +126,13 @@ LL | | if matches!(true, true) {}
|
|||||||
LL | | }
|
LL | | }
|
||||||
| |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}`
|
| |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}`
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: this `if` statement can be collapsed
|
||||||
|
--> $DIR/collapsible_if.rs:159:5
|
||||||
|
|
|
||||||
|
LL | / if matches!(true, true) && truth() {
|
||||||
|
LL | | if matches!(true, true) {}
|
||||||
|
LL | | }
|
||||||
|
| |_____^ help: collapse nested if block: `if matches!(true, true) && truth() && matches!(true, true) {}`
|
||||||
|
|
||||||
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
|
|||||||
5
tests/ui/crashes/ice-9463.rs
Normal file
5
tests/ui/crashes/ice-9463.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#![deny(arithmetic_overflow, const_err)]
|
||||||
|
fn main() {
|
||||||
|
let _x = -1_i32 >> -1;
|
||||||
|
let _y = 1u32 >> 10000000000000u32;
|
||||||
|
}
|
||||||
29
tests/ui/crashes/ice-9463.stderr
Normal file
29
tests/ui/crashes/ice-9463.stderr
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
error: this arithmetic operation will overflow
|
||||||
|
--> $DIR/ice-9463.rs:3:14
|
||||||
|
|
|
||||||
|
LL | let _x = -1_i32 >> -1;
|
||||||
|
| ^^^^^^^^^^^^ attempt to shift right by `-1_i32`, which would overflow
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/ice-9463.rs:1:9
|
||||||
|
|
|
||||||
|
LL | #![deny(arithmetic_overflow, const_err)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: this arithmetic operation will overflow
|
||||||
|
--> $DIR/ice-9463.rs:4:14
|
||||||
|
|
|
||||||
|
LL | let _y = 1u32 >> 10000000000000u32;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift right by `1316134912_u32`, which would overflow
|
||||||
|
|
||||||
|
error: literal out of range for `u32`
|
||||||
|
--> $DIR/ice-9463.rs:4:22
|
||||||
|
|
|
||||||
|
LL | let _y = 1u32 >> 10000000000000u32;
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[deny(overflowing_literals)]` on by default
|
||||||
|
= note: the literal `10000000000000u32` does not fit into the type `u32` whose range is `0..=4294967295`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
213
tests/ui/derivable_impls.fixed
Normal file
213
tests/ui/derivable_impls.fixed
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct FooDefault<'a> {
|
||||||
|
a: bool,
|
||||||
|
b: i32,
|
||||||
|
c: u64,
|
||||||
|
d: Vec<i32>,
|
||||||
|
e: FooND1,
|
||||||
|
f: FooND2,
|
||||||
|
g: HashMap<i32, i32>,
|
||||||
|
h: (i32, Vec<i32>),
|
||||||
|
i: [Vec<i32>; 3],
|
||||||
|
j: [i32; 5],
|
||||||
|
k: Option<i32>,
|
||||||
|
l: &'a [i32],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct TupleDefault(bool, i32, u64);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct FooND1 {
|
||||||
|
a: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::default::Default for FooND1 {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { a: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FooND2 {
|
||||||
|
a: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::default::Default for FooND2 {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { a: 5 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FooNDNew {
|
||||||
|
a: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FooNDNew {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self { a: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FooNDNew {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FooNDVec(Vec<i32>);
|
||||||
|
|
||||||
|
impl Default for FooNDVec {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(vec![5, 12])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct StrDefault<'a>(&'a str);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct AlreadyDerived(i32, bool);
|
||||||
|
|
||||||
|
macro_rules! mac {
|
||||||
|
() => {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
($e:expr) => {
|
||||||
|
struct X(u32);
|
||||||
|
impl Default for X {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self($e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
mac!(0);
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Y(u32);
|
||||||
|
|
||||||
|
|
||||||
|
struct RustIssue26925<T> {
|
||||||
|
a: Option<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should watch out for cases where a manual impl is needed because a
|
||||||
|
// derive adds different type bounds (https://github.com/rust-lang/rust/issues/26925).
|
||||||
|
// For example, a struct with Option<T> does not require T: Default, but a derive adds
|
||||||
|
// that type bound anyways. So until #26925 get fixed we should disable lint
|
||||||
|
// for the following case
|
||||||
|
impl<T> Default for RustIssue26925<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { a: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SpecializedImpl<A, B> {
|
||||||
|
a: A,
|
||||||
|
b: B,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Default> Default for SpecializedImpl<T, T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
a: T::default(),
|
||||||
|
b: T::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct WithoutSelfCurly {
|
||||||
|
a: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct WithoutSelfParan(bool);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust-clippy/issues/7655
|
||||||
|
|
||||||
|
pub struct SpecializedImpl2<T> {
|
||||||
|
v: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SpecializedImpl2<String> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { v: Vec::new() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust-clippy/issues/7654
|
||||||
|
|
||||||
|
pub struct Color {
|
||||||
|
pub r: u8,
|
||||||
|
pub g: u8,
|
||||||
|
pub b: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `#000000`
|
||||||
|
impl Default for Color {
|
||||||
|
fn default() -> Self {
|
||||||
|
Color { r: 0, g: 0, b: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Color2 {
|
||||||
|
pub r: u8,
|
||||||
|
pub g: u8,
|
||||||
|
pub b: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Color2 {
|
||||||
|
/// `#000000`
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { r: 0, g: 0, b: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct RepeatDefault1 {
|
||||||
|
a: [i8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub struct RepeatDefault2 {
|
||||||
|
a: [i8; 33],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RepeatDefault2 {
|
||||||
|
fn default() -> Self {
|
||||||
|
RepeatDefault2 { a: [0; 33] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust-clippy/issues/7753
|
||||||
|
|
||||||
|
pub enum IntOrString {
|
||||||
|
Int(i32),
|
||||||
|
String(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for IntOrString {
|
||||||
|
fn default() -> Self {
|
||||||
|
IntOrString::Int(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
struct FooDefault<'a> {
|
struct FooDefault<'a> {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error: this `impl` can be derived
|
error: this `impl` can be derived
|
||||||
--> $DIR/derivable_impls.rs:18:1
|
--> $DIR/derivable_impls.rs:22:1
|
||||||
|
|
|
|
||||||
LL | / impl std::default::Default for FooDefault<'_> {
|
LL | / impl std::default::Default for FooDefault<'_> {
|
||||||
LL | | fn default() -> Self {
|
LL | | fn default() -> Self {
|
||||||
@@ -11,10 +11,14 @@ LL | | }
|
|||||||
| |_^
|
| |_^
|
||||||
|
|
|
|
||||||
= note: `-D clippy::derivable-impls` implied by `-D warnings`
|
= note: `-D clippy::derivable-impls` implied by `-D warnings`
|
||||||
= help: try annotating `FooDefault` with `#[derive(Default)]`
|
= help: remove the manual implementation...
|
||||||
|
help: ...and instead derive it
|
||||||
|
|
|
||||||
|
LL | #[derive(Default)]
|
||||||
|
|
|
||||||
|
|
||||||
error: this `impl` can be derived
|
error: this `impl` can be derived
|
||||||
--> $DIR/derivable_impls.rs:39:1
|
--> $DIR/derivable_impls.rs:43:1
|
||||||
|
|
|
|
||||||
LL | / impl std::default::Default for TupleDefault {
|
LL | / impl std::default::Default for TupleDefault {
|
||||||
LL | | fn default() -> Self {
|
LL | | fn default() -> Self {
|
||||||
@@ -23,10 +27,14 @@ LL | | }
|
|||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
|
|
||||||
= help: try annotating `TupleDefault` with `#[derive(Default)]`
|
= help: remove the manual implementation...
|
||||||
|
help: ...and instead derive it
|
||||||
|
|
|
||||||
|
LL | #[derive(Default)]
|
||||||
|
|
|
||||||
|
|
||||||
error: this `impl` can be derived
|
error: this `impl` can be derived
|
||||||
--> $DIR/derivable_impls.rs:91:1
|
--> $DIR/derivable_impls.rs:95:1
|
||||||
|
|
|
|
||||||
LL | / impl Default for StrDefault<'_> {
|
LL | / impl Default for StrDefault<'_> {
|
||||||
LL | | fn default() -> Self {
|
LL | | fn default() -> Self {
|
||||||
@@ -35,10 +43,14 @@ LL | | }
|
|||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
|
|
||||||
= help: try annotating `StrDefault` with `#[derive(Default)]`
|
= help: remove the manual implementation...
|
||||||
|
help: ...and instead derive it
|
||||||
|
|
|
||||||
|
LL | #[derive(Default)]
|
||||||
|
|
|
||||||
|
|
||||||
error: this `impl` can be derived
|
error: this `impl` can be derived
|
||||||
--> $DIR/derivable_impls.rs:117:1
|
--> $DIR/derivable_impls.rs:121:1
|
||||||
|
|
|
|
||||||
LL | / impl Default for Y {
|
LL | / impl Default for Y {
|
||||||
LL | | fn default() -> Self {
|
LL | | fn default() -> Self {
|
||||||
@@ -47,10 +59,14 @@ LL | | }
|
|||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
|
|
||||||
= help: try annotating `Y` with `#[derive(Default)]`
|
= help: remove the manual implementation...
|
||||||
|
help: ...and instead derive it
|
||||||
|
|
|
||||||
|
LL | #[derive(Default)]
|
||||||
|
|
|
||||||
|
|
||||||
error: this `impl` can be derived
|
error: this `impl` can be derived
|
||||||
--> $DIR/derivable_impls.rs:156:1
|
--> $DIR/derivable_impls.rs:160:1
|
||||||
|
|
|
|
||||||
LL | / impl Default for WithoutSelfCurly {
|
LL | / impl Default for WithoutSelfCurly {
|
||||||
LL | | fn default() -> Self {
|
LL | | fn default() -> Self {
|
||||||
@@ -59,10 +75,14 @@ LL | | }
|
|||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
|
|
||||||
= help: try annotating `WithoutSelfCurly` with `#[derive(Default)]`
|
= help: remove the manual implementation...
|
||||||
|
help: ...and instead derive it
|
||||||
|
|
|
||||||
|
LL | #[derive(Default)]
|
||||||
|
|
|
||||||
|
|
||||||
error: this `impl` can be derived
|
error: this `impl` can be derived
|
||||||
--> $DIR/derivable_impls.rs:164:1
|
--> $DIR/derivable_impls.rs:168:1
|
||||||
|
|
|
|
||||||
LL | / impl Default for WithoutSelfParan {
|
LL | / impl Default for WithoutSelfParan {
|
||||||
LL | | fn default() -> Self {
|
LL | | fn default() -> Self {
|
||||||
@@ -71,10 +91,14 @@ LL | | }
|
|||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
|
|
||||||
= help: try annotating `WithoutSelfParan` with `#[derive(Default)]`
|
= help: remove the manual implementation...
|
||||||
|
help: ...and instead derive it
|
||||||
|
|
|
||||||
|
LL | #[derive(Default)]
|
||||||
|
|
|
||||||
|
|
||||||
error: this `impl` can be derived
|
error: this `impl` can be derived
|
||||||
--> $DIR/derivable_impls.rs:214:1
|
--> $DIR/derivable_impls.rs:218:1
|
||||||
|
|
|
|
||||||
LL | / impl Default for RepeatDefault1 {
|
LL | / impl Default for RepeatDefault1 {
|
||||||
LL | | fn default() -> Self {
|
LL | | fn default() -> Self {
|
||||||
@@ -83,7 +107,11 @@ LL | | }
|
|||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
|
|
||||||
= help: try annotating `RepeatDefault1` with `#[derive(Default)]`
|
= help: remove the manual implementation...
|
||||||
|
help: ...and instead derive it
|
||||||
|
|
|
||||||
|
LL | #[derive(Default)]
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -45,5 +45,13 @@ fn main() {
|
|||||||
eprint!("\r\n");
|
eprint!("\r\n");
|
||||||
eprint!("foo\r\n");
|
eprint!("foo\r\n");
|
||||||
eprint!("\\r\n"); //~ ERROR
|
eprint!("\\r\n"); //~ ERROR
|
||||||
eprint!("foo\rbar\n") // ~ ERROR
|
eprint!("foo\rbar\n");
|
||||||
|
|
||||||
|
// Ignore expanded format strings
|
||||||
|
macro_rules! newline {
|
||||||
|
() => {
|
||||||
|
"\n"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
eprint!(newline!());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ LL | | );
|
|||||||
help: use `eprintln!` instead
|
help: use `eprintln!` instead
|
||||||
|
|
|
|
||||||
LL ~ eprintln!(
|
LL ~ eprintln!(
|
||||||
LL ~ ""
|
LL ~
|
||||||
|
|
|
|
||||||
|
|
||||||
error: using `eprint!()` with a format string that ends in a single newline
|
error: using `eprint!()` with a format string that ends in a single newline
|
||||||
@@ -98,7 +98,7 @@ LL | | );
|
|||||||
help: use `eprintln!` instead
|
help: use `eprintln!` instead
|
||||||
|
|
|
|
||||||
LL ~ eprintln!(
|
LL ~ eprintln!(
|
||||||
LL ~ r""
|
LL ~
|
||||||
|
|
|
|
||||||
|
|
||||||
error: using `eprint!()` with a format string that ends in a single newline
|
error: using `eprint!()` with a format string that ends in a single newline
|
||||||
@@ -113,17 +113,5 @@ LL - eprint!("/r/n"); //~ ERROR
|
|||||||
LL + eprintln!("/r"); //~ ERROR
|
LL + eprintln!("/r"); //~ ERROR
|
||||||
|
|
|
|
||||||
|
|
||||||
error: using `eprint!()` with a format string that ends in a single newline
|
error: aborting due to 9 previous errors
|
||||||
--> $DIR/eprint_with_newline.rs:48:5
|
|
||||||
|
|
|
||||||
LL | eprint!("foo/rbar/n") // ~ ERROR
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
help: use `eprintln!` instead
|
|
||||||
|
|
|
||||||
LL - eprint!("foo/rbar/n") // ~ ERROR
|
|
||||||
LL + eprintln!("foo/rbar") // ~ ERROR
|
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ fn main() {
|
|||||||
eprintln!("with {} {}", 2, value);
|
eprintln!("with {} {}", 2, value);
|
||||||
eprintln!("with {value}");
|
eprintln!("with {value}");
|
||||||
eprintln!("macro arg {}", one!());
|
eprintln!("macro arg {}", one!());
|
||||||
|
let width = 2;
|
||||||
|
eprintln!("{:w$}", value, w = width);
|
||||||
}
|
}
|
||||||
// these should not warn, different destination
|
// these should not warn, different destination
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ fn main() {
|
|||||||
writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap();
|
writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap();
|
||||||
writeln!(std::io::stderr(), "with {value}").unwrap();
|
writeln!(std::io::stderr(), "with {value}").unwrap();
|
||||||
writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
|
writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
|
||||||
|
let width = 2;
|
||||||
|
writeln!(std::io::stderr(), "{:w$}", value, w = width).unwrap();
|
||||||
}
|
}
|
||||||
// these should not warn, different destination
|
// these should not warn, different destination
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,5 +72,11 @@ error: use of `writeln!(stderr(), ...).unwrap()`
|
|||||||
LL | writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
|
LL | writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("macro arg {}", one!())`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("macro arg {}", one!())`
|
||||||
|
|
||||||
error: aborting due to 12 previous errors
|
error: use of `writeln!(stderr(), ...).unwrap()`
|
||||||
|
--> $DIR/explicit_write.rs:40:9
|
||||||
|
|
|
||||||
|
LL | writeln!(std::io::stderr(), "{:w$}", value, w = width).unwrap();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("{:w$}", value, w = width)`
|
||||||
|
|
||||||
|
error: aborting due to 13 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ fn main() {
|
|||||||
format!("{:?}", "foo"); // Don't warn about `Debug`.
|
format!("{:?}", "foo"); // Don't warn about `Debug`.
|
||||||
format!("{:8}", "foo");
|
format!("{:8}", "foo");
|
||||||
format!("{:width$}", "foo", width = 8);
|
format!("{:width$}", "foo", width = 8);
|
||||||
"foo".to_string(); // Warn when the format makes no difference.
|
|
||||||
"foo".to_string(); // Warn when the format makes no difference.
|
|
||||||
format!("foo {}", "bar");
|
format!("foo {}", "bar");
|
||||||
format!("{} bar", "foo");
|
format!("{} bar", "foo");
|
||||||
|
|
||||||
@@ -38,8 +36,6 @@ fn main() {
|
|||||||
format!("{:?}", arg); // Don't warn about debug.
|
format!("{:?}", arg); // Don't warn about debug.
|
||||||
format!("{:8}", arg);
|
format!("{:8}", arg);
|
||||||
format!("{:width$}", arg, width = 8);
|
format!("{:width$}", arg, width = 8);
|
||||||
arg.to_string(); // Warn when the format makes no difference.
|
|
||||||
arg.to_string(); // Warn when the format makes no difference.
|
|
||||||
format!("foo {}", arg);
|
format!("foo {}", arg);
|
||||||
format!("{} bar", arg);
|
format!("{} bar", arg);
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ fn main() {
|
|||||||
format!("{:?}", "foo"); // Don't warn about `Debug`.
|
format!("{:?}", "foo"); // Don't warn about `Debug`.
|
||||||
format!("{:8}", "foo");
|
format!("{:8}", "foo");
|
||||||
format!("{:width$}", "foo", width = 8);
|
format!("{:width$}", "foo", width = 8);
|
||||||
format!("{:+}", "foo"); // Warn when the format makes no difference.
|
|
||||||
format!("{:<}", "foo"); // Warn when the format makes no difference.
|
|
||||||
format!("foo {}", "bar");
|
format!("foo {}", "bar");
|
||||||
format!("{} bar", "foo");
|
format!("{} bar", "foo");
|
||||||
|
|
||||||
@@ -40,8 +38,6 @@ fn main() {
|
|||||||
format!("{:?}", arg); // Don't warn about debug.
|
format!("{:?}", arg); // Don't warn about debug.
|
||||||
format!("{:8}", arg);
|
format!("{:8}", arg);
|
||||||
format!("{:width$}", arg, width = 8);
|
format!("{:width$}", arg, width = 8);
|
||||||
format!("{:+}", arg); // Warn when the format makes no difference.
|
|
||||||
format!("{:<}", arg); // Warn when the format makes no difference.
|
|
||||||
format!("foo {}", arg);
|
format!("foo {}", arg);
|
||||||
format!("{} bar", arg);
|
format!("{} bar", arg);
|
||||||
|
|
||||||
|
|||||||
@@ -46,82 +46,58 @@ LL | format!("{}", "foo");
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
|
| ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
|
||||||
|
|
||||||
error: useless use of `format!`
|
error: useless use of `format!`
|
||||||
--> $DIR/format.rs:33:5
|
--> $DIR/format.rs:37:5
|
||||||
|
|
|
||||||
LL | format!("{:+}", "foo"); // Warn when the format makes no difference.
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
|
|
||||||
|
|
||||||
error: useless use of `format!`
|
|
||||||
--> $DIR/format.rs:34:5
|
|
||||||
|
|
|
||||||
LL | format!("{:<}", "foo"); // Warn when the format makes no difference.
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
|
|
||||||
|
|
||||||
error: useless use of `format!`
|
|
||||||
--> $DIR/format.rs:39:5
|
|
||||||
|
|
|
|
||||||
LL | format!("{}", arg);
|
LL | format!("{}", arg);
|
||||||
| ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
|
| ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
|
||||||
|
|
||||||
error: useless use of `format!`
|
error: useless use of `format!`
|
||||||
--> $DIR/format.rs:43:5
|
--> $DIR/format.rs:67:5
|
||||||
|
|
|
||||||
LL | format!("{:+}", arg); // Warn when the format makes no difference.
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
|
|
||||||
|
|
||||||
error: useless use of `format!`
|
|
||||||
--> $DIR/format.rs:44:5
|
|
||||||
|
|
|
||||||
LL | format!("{:<}", arg); // Warn when the format makes no difference.
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
|
|
||||||
|
|
||||||
error: useless use of `format!`
|
|
||||||
--> $DIR/format.rs:71:5
|
|
||||||
|
|
|
|
||||||
LL | format!("{}", 42.to_string());
|
LL | format!("{}", 42.to_string());
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()`
|
||||||
|
|
||||||
error: useless use of `format!`
|
error: useless use of `format!`
|
||||||
--> $DIR/format.rs:73:5
|
--> $DIR/format.rs:69:5
|
||||||
|
|
|
|
||||||
LL | format!("{}", x.display().to_string());
|
LL | format!("{}", x.display().to_string());
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()`
|
||||||
|
|
||||||
error: useless use of `format!`
|
error: useless use of `format!`
|
||||||
--> $DIR/format.rs:77:18
|
--> $DIR/format.rs:73:18
|
||||||
|
|
|
|
||||||
LL | let _ = Some(format!("{}", a + "bar"));
|
LL | let _ = Some(format!("{}", a + "bar"));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"`
|
||||||
|
|
||||||
error: useless use of `format!`
|
error: useless use of `format!`
|
||||||
--> $DIR/format.rs:81:22
|
--> $DIR/format.rs:77:22
|
||||||
|
|
|
|
||||||
LL | let _s: String = format!("{}", &*v.join("/n"));
|
LL | let _s: String = format!("{}", &*v.join("/n"));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()`
|
||||||
|
|
||||||
error: useless use of `format!`
|
error: useless use of `format!`
|
||||||
--> $DIR/format.rs:87:13
|
--> $DIR/format.rs:83:13
|
||||||
|
|
|
|
||||||
LL | let _ = format!("{x}");
|
LL | let _ = format!("{x}");
|
||||||
| ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
|
| ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
|
||||||
|
|
||||||
error: useless use of `format!`
|
error: useless use of `format!`
|
||||||
--> $DIR/format.rs:89:13
|
--> $DIR/format.rs:85:13
|
||||||
|
|
|
|
||||||
LL | let _ = format!("{y}", y = x);
|
LL | let _ = format!("{y}", y = x);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
|
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
|
||||||
|
|
||||||
error: useless use of `format!`
|
error: useless use of `format!`
|
||||||
--> $DIR/format.rs:93:13
|
--> $DIR/format.rs:89:13
|
||||||
|
|
|
|
||||||
LL | let _ = format!("{abc}");
|
LL | let _ = format!("{abc}");
|
||||||
| ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()`
|
| ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()`
|
||||||
|
|
||||||
error: useless use of `format!`
|
error: useless use of `format!`
|
||||||
--> $DIR/format.rs:95:13
|
--> $DIR/format.rs:91:13
|
||||||
|
|
|
|
||||||
LL | let _ = format!("{xx}");
|
LL | let _ = format!("{xx}");
|
||||||
| ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()`
|
| ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()`
|
||||||
|
|
||||||
error: aborting due to 19 previous errors
|
error: aborting due to 15 previous errors
|
||||||
|
|
||||||
|
|||||||
64
tests/ui/iter_kv_map.fixed
Normal file
64
tests/ui/iter_kv_map.fixed
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![warn(clippy::iter_kv_map)]
|
||||||
|
#![allow(clippy::redundant_clone)]
|
||||||
|
#![allow(clippy::suspicious_map)]
|
||||||
|
#![allow(clippy::map_identity)]
|
||||||
|
|
||||||
|
use std::collections::{BTreeMap, HashMap};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let get_key = |(key, _val)| key;
|
||||||
|
|
||||||
|
let map: HashMap<u32, u32> = HashMap::new();
|
||||||
|
|
||||||
|
let _ = map.keys().collect::<Vec<_>>();
|
||||||
|
let _ = map.values().collect::<Vec<_>>();
|
||||||
|
let _ = map.values().map(|v| v + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().into_keys().collect::<Vec<_>>();
|
||||||
|
let _ = map.clone().into_keys().map(|key| key + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().into_values().collect::<Vec<_>>();
|
||||||
|
let _ = map.clone().into_values().map(|val| val + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().values().collect::<Vec<_>>();
|
||||||
|
let _ = map.keys().filter(|x| *x % 2 == 0).count();
|
||||||
|
|
||||||
|
// Don't lint
|
||||||
|
let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
|
||||||
|
let _ = map.iter().map(get_key).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Linting the following could be an improvement to the lint
|
||||||
|
// map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
|
||||||
|
|
||||||
|
// Lint
|
||||||
|
let _ = map.keys().map(|key| key * 9).count();
|
||||||
|
let _ = map.values().map(|value| value * 17).count();
|
||||||
|
|
||||||
|
let map: BTreeMap<u32, u32> = BTreeMap::new();
|
||||||
|
|
||||||
|
let _ = map.keys().collect::<Vec<_>>();
|
||||||
|
let _ = map.values().collect::<Vec<_>>();
|
||||||
|
let _ = map.values().map(|v| v + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().into_keys().collect::<Vec<_>>();
|
||||||
|
let _ = map.clone().into_keys().map(|key| key + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().into_values().collect::<Vec<_>>();
|
||||||
|
let _ = map.clone().into_values().map(|val| val + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().values().collect::<Vec<_>>();
|
||||||
|
let _ = map.keys().filter(|x| *x % 2 == 0).count();
|
||||||
|
|
||||||
|
// Don't lint
|
||||||
|
let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
|
||||||
|
let _ = map.iter().map(get_key).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Linting the following could be an improvement to the lint
|
||||||
|
// map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
|
||||||
|
|
||||||
|
// Lint
|
||||||
|
let _ = map.keys().map(|key| key * 9).count();
|
||||||
|
let _ = map.values().map(|value| value * 17).count();
|
||||||
|
}
|
||||||
64
tests/ui/iter_kv_map.rs
Normal file
64
tests/ui/iter_kv_map.rs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![warn(clippy::iter_kv_map)]
|
||||||
|
#![allow(clippy::redundant_clone)]
|
||||||
|
#![allow(clippy::suspicious_map)]
|
||||||
|
#![allow(clippy::map_identity)]
|
||||||
|
|
||||||
|
use std::collections::{BTreeMap, HashMap};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let get_key = |(key, _val)| key;
|
||||||
|
|
||||||
|
let map: HashMap<u32, u32> = HashMap::new();
|
||||||
|
|
||||||
|
let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||||
|
let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
|
||||||
|
let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||||
|
let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||||
|
let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||||
|
let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
|
||||||
|
|
||||||
|
// Don't lint
|
||||||
|
let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
|
||||||
|
let _ = map.iter().map(get_key).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Linting the following could be an improvement to the lint
|
||||||
|
// map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
|
||||||
|
|
||||||
|
// Lint
|
||||||
|
let _ = map.iter().map(|(key, _value)| key * 9).count();
|
||||||
|
let _ = map.iter().map(|(_key, value)| value * 17).count();
|
||||||
|
|
||||||
|
let map: BTreeMap<u32, u32> = BTreeMap::new();
|
||||||
|
|
||||||
|
let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||||
|
let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
|
||||||
|
let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||||
|
let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||||
|
let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||||
|
let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
|
||||||
|
|
||||||
|
// Don't lint
|
||||||
|
let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
|
||||||
|
let _ = map.iter().map(get_key).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Linting the following could be an improvement to the lint
|
||||||
|
// map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
|
||||||
|
|
||||||
|
// Lint
|
||||||
|
let _ = map.iter().map(|(key, _value)| key * 9).count();
|
||||||
|
let _ = map.iter().map(|(_key, value)| value * 17).count();
|
||||||
|
}
|
||||||
136
tests/ui/iter_kv_map.stderr
Normal file
136
tests/ui/iter_kv_map.stderr
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
error: iterating on a map's keys
|
||||||
|
--> $DIR/iter_kv_map.rs:15:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
|
||||||
|
|
|
||||||
|
= note: `-D clippy::iter-kv-map` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:16:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:17:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
|
||||||
|
|
||||||
|
error: iterating on a map's keys
|
||||||
|
--> $DIR/iter_kv_map.rs:19:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
|
||||||
|
|
||||||
|
error: iterating on a map's keys
|
||||||
|
--> $DIR/iter_kv_map.rs:20:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:22:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:23:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:25:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
|
||||||
|
|
||||||
|
error: iterating on a map's keys
|
||||||
|
--> $DIR/iter_kv_map.rs:26:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
|
||||||
|
|
||||||
|
error: iterating on a map's keys
|
||||||
|
--> $DIR/iter_kv_map.rs:36:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(key, _value)| key * 9).count();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:37:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(_key, value)| value * 17).count();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
|
||||||
|
|
||||||
|
error: iterating on a map's keys
|
||||||
|
--> $DIR/iter_kv_map.rs:41:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:42:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:43:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
|
||||||
|
|
||||||
|
error: iterating on a map's keys
|
||||||
|
--> $DIR/iter_kv_map.rs:45:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
|
||||||
|
|
||||||
|
error: iterating on a map's keys
|
||||||
|
--> $DIR/iter_kv_map.rs:46:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:48:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:49:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:51:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
|
||||||
|
|
||||||
|
error: iterating on a map's keys
|
||||||
|
--> $DIR/iter_kv_map.rs:52:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
|
||||||
|
|
||||||
|
error: iterating on a map's keys
|
||||||
|
--> $DIR/iter_kv_map.rs:62:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(key, _value)| key * 9).count();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
|
||||||
|
|
||||||
|
error: iterating on a map's values
|
||||||
|
--> $DIR/iter_kv_map.rs:63:13
|
||||||
|
|
|
||||||
|
LL | let _ = map.iter().map(|(_key, value)| value * 17).count();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
|
||||||
|
|
||||||
|
error: aborting due to 22 previous errors
|
||||||
|
|
||||||
@@ -101,12 +101,12 @@ struct Struct2 {
|
|||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum CopyableLargeEnum {
|
enum CopyableLargeEnum {
|
||||||
A(bool),
|
A(bool),
|
||||||
B([u128; 4000]),
|
B([u64; 8000]),
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ManuallyCopyLargeEnum {
|
enum ManuallyCopyLargeEnum {
|
||||||
A(bool),
|
A(bool),
|
||||||
B([u128; 4000]),
|
B([u64; 8000]),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for ManuallyCopyLargeEnum {
|
impl Clone for ManuallyCopyLargeEnum {
|
||||||
|
|||||||
@@ -167,8 +167,8 @@ error: large size difference between variants
|
|||||||
LL | / enum CopyableLargeEnum {
|
LL | / enum CopyableLargeEnum {
|
||||||
LL | | A(bool),
|
LL | | A(bool),
|
||||||
| | ------- the second-largest variant contains at least 1 bytes
|
| | ------- the second-largest variant contains at least 1 bytes
|
||||||
LL | | B([u128; 4000]),
|
LL | | B([u64; 8000]),
|
||||||
| | --------------- the largest variant contains at least 64000 bytes
|
| | -------------- the largest variant contains at least 64000 bytes
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_^ the entire enum is at least 64008 bytes
|
| |_^ the entire enum is at least 64008 bytes
|
||||||
|
|
|
|
||||||
@@ -180,8 +180,8 @@ LL | enum CopyableLargeEnum {
|
|||||||
help: consider boxing the large fields to reduce the total size of the enum
|
help: consider boxing the large fields to reduce the total size of the enum
|
||||||
--> $DIR/large_enum_variant.rs:104:5
|
--> $DIR/large_enum_variant.rs:104:5
|
||||||
|
|
|
|
||||||
LL | B([u128; 4000]),
|
LL | B([u64; 8000]),
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: large size difference between variants
|
error: large size difference between variants
|
||||||
--> $DIR/large_enum_variant.rs:107:1
|
--> $DIR/large_enum_variant.rs:107:1
|
||||||
@@ -189,8 +189,8 @@ error: large size difference between variants
|
|||||||
LL | / enum ManuallyCopyLargeEnum {
|
LL | / enum ManuallyCopyLargeEnum {
|
||||||
LL | | A(bool),
|
LL | | A(bool),
|
||||||
| | ------- the second-largest variant contains at least 1 bytes
|
| | ------- the second-largest variant contains at least 1 bytes
|
||||||
LL | | B([u128; 4000]),
|
LL | | B([u64; 8000]),
|
||||||
| | --------------- the largest variant contains at least 64000 bytes
|
| | -------------- the largest variant contains at least 64000 bytes
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_^ the entire enum is at least 64008 bytes
|
| |_^ the entire enum is at least 64008 bytes
|
||||||
|
|
|
|
||||||
@@ -202,8 +202,8 @@ LL | enum ManuallyCopyLargeEnum {
|
|||||||
help: consider boxing the large fields to reduce the total size of the enum
|
help: consider boxing the large fields to reduce the total size of the enum
|
||||||
--> $DIR/large_enum_variant.rs:109:5
|
--> $DIR/large_enum_variant.rs:109:5
|
||||||
|
|
|
|
||||||
LL | B([u128; 4000]),
|
LL | B([u64; 8000]),
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: large size difference between variants
|
error: large size difference between variants
|
||||||
--> $DIR/large_enum_variant.rs:120:1
|
--> $DIR/large_enum_variant.rs:120:1
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ enum E {
|
|||||||
T(u32),
|
T(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub static DOESNOTLINT: [u8; 512_001] = [0; 512_001];
|
||||||
|
pub static DOESNOTLINT2: [u8; 512_001] = {
|
||||||
|
let x = 0;
|
||||||
|
[x; 512_001]
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let bad = (
|
let bad = (
|
||||||
[0u32; 20_000_000],
|
[0u32; 20_000_000],
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error: allocating a local array larger than 512000 bytes
|
error: allocating a local array larger than 512000 bytes
|
||||||
--> $DIR/large_stack_arrays.rs:17:9
|
--> $DIR/large_stack_arrays.rs:23:9
|
||||||
|
|
|
|
||||||
LL | [0u32; 20_000_000],
|
LL | [0u32; 20_000_000],
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
@@ -8,7 +8,7 @@ LL | [0u32; 20_000_000],
|
|||||||
= help: consider allocating on the heap with `vec![0u32; 20_000_000].into_boxed_slice()`
|
= help: consider allocating on the heap with `vec![0u32; 20_000_000].into_boxed_slice()`
|
||||||
|
|
||||||
error: allocating a local array larger than 512000 bytes
|
error: allocating a local array larger than 512000 bytes
|
||||||
--> $DIR/large_stack_arrays.rs:18:9
|
--> $DIR/large_stack_arrays.rs:24:9
|
||||||
|
|
|
|
||||||
LL | [S { data: [0; 32] }; 5000],
|
LL | [S { data: [0; 32] }; 5000],
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@@ -16,7 +16,7 @@ LL | [S { data: [0; 32] }; 5000],
|
|||||||
= help: consider allocating on the heap with `vec![S { data: [0; 32] }; 5000].into_boxed_slice()`
|
= help: consider allocating on the heap with `vec![S { data: [0; 32] }; 5000].into_boxed_slice()`
|
||||||
|
|
||||||
error: allocating a local array larger than 512000 bytes
|
error: allocating a local array larger than 512000 bytes
|
||||||
--> $DIR/large_stack_arrays.rs:19:9
|
--> $DIR/large_stack_arrays.rs:25:9
|
||||||
|
|
|
|
||||||
LL | [Some(""); 20_000_000],
|
LL | [Some(""); 20_000_000],
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@@ -24,7 +24,7 @@ LL | [Some(""); 20_000_000],
|
|||||||
= help: consider allocating on the heap with `vec![Some(""); 20_000_000].into_boxed_slice()`
|
= help: consider allocating on the heap with `vec![Some(""); 20_000_000].into_boxed_slice()`
|
||||||
|
|
||||||
error: allocating a local array larger than 512000 bytes
|
error: allocating a local array larger than 512000 bytes
|
||||||
--> $DIR/large_stack_arrays.rs:20:9
|
--> $DIR/large_stack_arrays.rs:26:9
|
||||||
|
|
|
|
||||||
LL | [E::T(0); 5000],
|
LL | [E::T(0); 5000],
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ impl AsyncLen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn len(&self) -> usize {
|
pub async fn len(&self) -> usize {
|
||||||
if self.async_task().await { 0 } else { 1 }
|
usize::from(!self.async_task().await)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_empty(&self) -> bool {
|
pub async fn is_empty(&self) -> bool {
|
||||||
|
|||||||
@@ -57,3 +57,9 @@ fn check_expect() {
|
|||||||
#[expect(clippy::nonminimal_bool)]
|
#[expect(clippy::nonminimal_bool)]
|
||||||
let _ = !!a;
|
let _ = !!a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn issue9428() {
|
||||||
|
if matches!(true, true) && true {
|
||||||
|
println!("foo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -107,5 +107,11 @@ LL | let _ = !(a == b || c == d);
|
|||||||
LL | let _ = a != b && c != d;
|
LL | let _ = a != b && c != d;
|
||||||
| ~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: aborting due to 12 previous errors
|
error: this boolean expression can be simplified
|
||||||
|
--> $DIR/nonminimal_bool.rs:62:8
|
||||||
|
|
|
||||||
|
LL | if matches!(true, true) && true {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(true, true)`
|
||||||
|
|
||||||
|
error: aborting due to 13 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
// run-rustfix
|
|
||||||
#![allow(unused_must_use)]
|
|
||||||
#![allow(named_arguments_used_positionally)] // Unstable at time of writing.
|
|
||||||
#![warn(clippy::positional_named_format_parameters)]
|
|
||||||
|
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut v = Vec::new();
|
|
||||||
let hello = "Hello";
|
|
||||||
|
|
||||||
println!("{hello:.foo$}", foo = 2);
|
|
||||||
writeln!(v, "{hello:.foo$}", foo = 2);
|
|
||||||
|
|
||||||
// Warnings
|
|
||||||
println!("{zero} {one:?}", zero = 0, one = 1);
|
|
||||||
println!("This is a test {zero} {one:?}", zero = 0, one = 1);
|
|
||||||
println!("Hello {one} is {two:.zero$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
println!("Hello {one:zero$}!", zero = 5, one = 1);
|
|
||||||
println!("Hello {zero:one$}!", zero = 4, one = 1);
|
|
||||||
println!("Hello {zero:0one$}!", zero = 4, one = 1);
|
|
||||||
println!("Hello is {one:.zero$}", zero = 5, one = 0.01);
|
|
||||||
println!("Hello is {one:<6.zero$}", zero = 5, one = 0.01);
|
|
||||||
println!("{zero}, `{two:>8.one$}` has 3", zero = hello, one = 3, two = hello);
|
|
||||||
println!("Hello {one} is {two:.zero$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
println!("Hello {world} {world}!", world = 5);
|
|
||||||
|
|
||||||
writeln!(v, "{zero} {one:?}", zero = 0, one = 1);
|
|
||||||
writeln!(v, "This is a test {zero} {one:?}", zero = 0, one = 1);
|
|
||||||
writeln!(v, "Hello {one} is {two:.zero$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
writeln!(v, "Hello {one:zero$}!", zero = 4, one = 1);
|
|
||||||
writeln!(v, "Hello {zero:one$}!", zero = 4, one = 1);
|
|
||||||
writeln!(v, "Hello {zero:0one$}!", zero = 4, one = 1);
|
|
||||||
writeln!(v, "Hello is {one:.zero$}", zero = 3, one = 0.01);
|
|
||||||
writeln!(v, "Hello is {one:<6.zero$}", zero = 2, one = 0.01);
|
|
||||||
writeln!(v, "{zero}, `{two:>8.one$}` has 3", zero = hello, one = 3, two = hello);
|
|
||||||
writeln!(v, "Hello {one} is {two:.zero$}", zero = 1, one = hello, two = 0.01);
|
|
||||||
writeln!(v, "Hello {world} {world}!", world = 0);
|
|
||||||
|
|
||||||
// Tests from other files
|
|
||||||
println!("{w:w$}", w = 1);
|
|
||||||
println!("{p:.p$}", p = 1);
|
|
||||||
println!("{v}", v = 1);
|
|
||||||
println!("{v:v$}", v = 1);
|
|
||||||
println!("{v:v$}", v = 1);
|
|
||||||
println!("{v:v$.v$}", v = 1);
|
|
||||||
println!("{v:v$.v$}", v = 1);
|
|
||||||
println!("{v:v$.v$}", v = 1);
|
|
||||||
println!("{v:v$.v$}", v = 1);
|
|
||||||
println!("{v:v$.v$}", v = 1);
|
|
||||||
println!("{v:v$.v$}", v = 1);
|
|
||||||
println!("{v:v$.v$}", v = 1);
|
|
||||||
println!("{w:w$}", w = 1);
|
|
||||||
println!("{p:.p$}", p = 1);
|
|
||||||
println!("{:p$.w$}", 1, w = 1, p = 1);
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
// run-rustfix
|
|
||||||
#![allow(unused_must_use)]
|
|
||||||
#![allow(named_arguments_used_positionally)] // Unstable at time of writing.
|
|
||||||
#![warn(clippy::positional_named_format_parameters)]
|
|
||||||
|
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut v = Vec::new();
|
|
||||||
let hello = "Hello";
|
|
||||||
|
|
||||||
println!("{hello:.foo$}", foo = 2);
|
|
||||||
writeln!(v, "{hello:.foo$}", foo = 2);
|
|
||||||
|
|
||||||
// Warnings
|
|
||||||
println!("{} {1:?}", zero = 0, one = 1);
|
|
||||||
println!("This is a test { } {000001:?}", zero = 0, one = 1);
|
|
||||||
println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
println!("Hello {1:0$}!", zero = 5, one = 1);
|
|
||||||
println!("Hello {0:1$}!", zero = 4, one = 1);
|
|
||||||
println!("Hello {0:01$}!", zero = 4, one = 1);
|
|
||||||
println!("Hello is {1:.*}", zero = 5, one = 0.01);
|
|
||||||
println!("Hello is {:<6.*}", zero = 5, one = 0.01);
|
|
||||||
println!("{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
|
|
||||||
println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
println!("Hello {world} {}!", world = 5);
|
|
||||||
|
|
||||||
writeln!(v, "{} {1:?}", zero = 0, one = 1);
|
|
||||||
writeln!(v, "This is a test { } {000001:?}", zero = 0, one = 1);
|
|
||||||
writeln!(v, "Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
writeln!(v, "Hello {1:0$}!", zero = 4, one = 1);
|
|
||||||
writeln!(v, "Hello {0:1$}!", zero = 4, one = 1);
|
|
||||||
writeln!(v, "Hello {0:01$}!", zero = 4, one = 1);
|
|
||||||
writeln!(v, "Hello is {1:.*}", zero = 3, one = 0.01);
|
|
||||||
writeln!(v, "Hello is {:<6.*}", zero = 2, one = 0.01);
|
|
||||||
writeln!(v, "{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
|
|
||||||
writeln!(v, "Hello {1} is {2:.0$}", zero = 1, one = hello, two = 0.01);
|
|
||||||
writeln!(v, "Hello {world} {}!", world = 0);
|
|
||||||
|
|
||||||
// Tests from other files
|
|
||||||
println!("{:w$}", w = 1);
|
|
||||||
println!("{:.p$}", p = 1);
|
|
||||||
println!("{}", v = 1);
|
|
||||||
println!("{:0$}", v = 1);
|
|
||||||
println!("{0:0$}", v = 1);
|
|
||||||
println!("{:0$.0$}", v = 1);
|
|
||||||
println!("{0:0$.0$}", v = 1);
|
|
||||||
println!("{0:0$.v$}", v = 1);
|
|
||||||
println!("{0:v$.0$}", v = 1);
|
|
||||||
println!("{v:0$.0$}", v = 1);
|
|
||||||
println!("{v:v$.0$}", v = 1);
|
|
||||||
println!("{v:0$.v$}", v = 1);
|
|
||||||
println!("{:w$}", w = 1);
|
|
||||||
println!("{:.p$}", p = 1);
|
|
||||||
println!("{:p$.w$}", 1, w = 1, p = 1);
|
|
||||||
}
|
|
||||||
@@ -1,418 +0,0 @@
|
|||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:16:16
|
|
||||||
|
|
|
||||||
LL | println!("{} {1:?}", zero = 0, one = 1);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
|
||||||
= note: `-D clippy::positional-named-format-parameters` implied by `-D warnings`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:16:19
|
|
||||||
|
|
|
||||||
LL | println!("{} {1:?}", zero = 0, one = 1);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:17:31
|
|
||||||
|
|
|
||||||
LL | println!("This is a test { } {000001:?}", zero = 0, one = 1);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:17:35
|
|
||||||
|
|
|
||||||
LL | println!("This is a test { } {000001:?}", zero = 0, one = 1);
|
|
||||||
| ^^^^^^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:18:32
|
|
||||||
|
|
|
||||||
LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:18:22
|
|
||||||
|
|
|
||||||
LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter two is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:18:29
|
|
||||||
|
|
|
||||||
LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `two`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:19:24
|
|
||||||
|
|
|
||||||
LL | println!("Hello {1:0$}!", zero = 5, one = 1);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:19:22
|
|
||||||
|
|
|
||||||
LL | println!("Hello {1:0$}!", zero = 5, one = 1);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:20:22
|
|
||||||
|
|
|
||||||
LL | println!("Hello {0:1$}!", zero = 4, one = 1);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:20:24
|
|
||||||
|
|
|
||||||
LL | println!("Hello {0:1$}!", zero = 4, one = 1);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:21:22
|
|
||||||
|
|
|
||||||
LL | println!("Hello {0:01$}!", zero = 4, one = 1);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:21:25
|
|
||||||
|
|
|
||||||
LL | println!("Hello {0:01$}!", zero = 4, one = 1);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:22:28
|
|
||||||
|
|
|
||||||
LL | println!("Hello is {1:.*}", zero = 5, one = 0.01);
|
|
||||||
| ^ help: replace it with: `zero$`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:22:25
|
|
||||||
|
|
|
||||||
LL | println!("Hello is {1:.*}", zero = 5, one = 0.01);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:23:29
|
|
||||||
|
|
|
||||||
LL | println!("Hello is {:<6.*}", zero = 5, one = 0.01);
|
|
||||||
| ^ help: replace it with: `zero$`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:23:25
|
|
||||||
|
|
|
||||||
LL | println!("Hello is {:<6.*}", zero = 5, one = 0.01);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:24:16
|
|
||||||
|
|
|
||||||
LL | println!("{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:24:28
|
|
||||||
|
|
|
||||||
LL | println!("{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
|
|
||||||
| ^ help: replace it with: `one$`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:25:32
|
|
||||||
|
|
|
||||||
LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:25:22
|
|
||||||
|
|
|
||||||
LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter two is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:25:29
|
|
||||||
|
|
|
||||||
LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `two`
|
|
||||||
|
|
||||||
error: named parameter world is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:26:30
|
|
||||||
|
|
|
||||||
LL | println!("Hello {world} {}!", world = 5);
|
|
||||||
| ^ help: replace it with: `world`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:28:19
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "{} {1:?}", zero = 0, one = 1);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:28:22
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "{} {1:?}", zero = 0, one = 1);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:29:34
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "This is a test { } {000001:?}", zero = 0, one = 1);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:29:38
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "This is a test { } {000001:?}", zero = 0, one = 1);
|
|
||||||
| ^^^^^^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:30:35
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:30:25
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter two is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:30:32
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `two`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:31:27
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {1:0$}!", zero = 4, one = 1);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:31:25
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {1:0$}!", zero = 4, one = 1);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:32:25
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {0:1$}!", zero = 4, one = 1);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:32:27
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {0:1$}!", zero = 4, one = 1);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:33:25
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {0:01$}!", zero = 4, one = 1);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:33:28
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {0:01$}!", zero = 4, one = 1);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:34:31
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello is {1:.*}", zero = 3, one = 0.01);
|
|
||||||
| ^ help: replace it with: `zero$`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:34:28
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello is {1:.*}", zero = 3, one = 0.01);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:35:32
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello is {:<6.*}", zero = 2, one = 0.01);
|
|
||||||
| ^ help: replace it with: `zero$`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:35:28
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello is {:<6.*}", zero = 2, one = 0.01);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:36:19
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:36:31
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
|
|
||||||
| ^ help: replace it with: `one$`
|
|
||||||
|
|
||||||
error: named parameter zero is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:37:35
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 1, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `zero`
|
|
||||||
|
|
||||||
error: named parameter one is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:37:25
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 1, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `one`
|
|
||||||
|
|
||||||
error: named parameter two is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:37:32
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 1, one = hello, two = 0.01);
|
|
||||||
| ^ help: replace it with: `two`
|
|
||||||
|
|
||||||
error: named parameter world is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:38:33
|
|
||||||
|
|
|
||||||
LL | writeln!(v, "Hello {world} {}!", world = 0);
|
|
||||||
| ^ help: replace it with: `world`
|
|
||||||
|
|
||||||
error: named parameter w is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:41:16
|
|
||||||
|
|
|
||||||
LL | println!("{:w$}", w = 1);
|
|
||||||
| ^ help: replace it with: `w`
|
|
||||||
|
|
||||||
error: named parameter p is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:42:16
|
|
||||||
|
|
|
||||||
LL | println!("{:.p$}", p = 1);
|
|
||||||
| ^ help: replace it with: `p`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:43:16
|
|
||||||
|
|
|
||||||
LL | println!("{}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:44:16
|
|
||||||
|
|
|
||||||
LL | println!("{:0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:44:17
|
|
||||||
|
|
|
||||||
LL | println!("{:0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:45:16
|
|
||||||
|
|
|
||||||
LL | println!("{0:0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:45:18
|
|
||||||
|
|
|
||||||
LL | println!("{0:0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:46:16
|
|
||||||
|
|
|
||||||
LL | println!("{:0$.0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:46:20
|
|
||||||
|
|
|
||||||
LL | println!("{:0$.0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:46:17
|
|
||||||
|
|
|
||||||
LL | println!("{:0$.0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:47:16
|
|
||||||
|
|
|
||||||
LL | println!("{0:0$.0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:47:21
|
|
||||||
|
|
|
||||||
LL | println!("{0:0$.0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:47:18
|
|
||||||
|
|
|
||||||
LL | println!("{0:0$.0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:48:16
|
|
||||||
|
|
|
||||||
LL | println!("{0:0$.v$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:48:18
|
|
||||||
|
|
|
||||||
LL | println!("{0:0$.v$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:49:16
|
|
||||||
|
|
|
||||||
LL | println!("{0:v$.0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:49:21
|
|
||||||
|
|
|
||||||
LL | println!("{0:v$.0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:50:21
|
|
||||||
|
|
|
||||||
LL | println!("{v:0$.0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:50:18
|
|
||||||
|
|
|
||||||
LL | println!("{v:0$.0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:51:21
|
|
||||||
|
|
|
||||||
LL | println!("{v:v$.0$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter v is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:52:18
|
|
||||||
|
|
|
||||||
LL | println!("{v:0$.v$}", v = 1);
|
|
||||||
| ^ help: replace it with: `v`
|
|
||||||
|
|
||||||
error: named parameter w is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:53:16
|
|
||||||
|
|
|
||||||
LL | println!("{:w$}", w = 1);
|
|
||||||
| ^ help: replace it with: `w`
|
|
||||||
|
|
||||||
error: named parameter p is used as a positional parameter
|
|
||||||
--> $DIR/positional_named_format_parameters.rs:54:16
|
|
||||||
|
|
|
||||||
LL | println!("{:.p$}", p = 1);
|
|
||||||
| ^ help: replace it with: `p`
|
|
||||||
|
|
||||||
error: aborting due to 69 previous errors
|
|
||||||
|
|
||||||
@@ -20,11 +20,13 @@ fn main() {
|
|||||||
println!("{} of {:b} people know binary, the other half doesn't", 1, 2);
|
println!("{} of {:b} people know binary, the other half doesn't", 1, 2);
|
||||||
println!("10 / 4 is {}", 2.5);
|
println!("10 / 4 is {}", 2.5);
|
||||||
println!("2 + 1 = {}", 3);
|
println!("2 + 1 = {}", 3);
|
||||||
|
println!("From expansion {}", stringify!(not a string literal));
|
||||||
|
|
||||||
// these should throw warnings
|
// these should throw warnings
|
||||||
print!("Hello {}", "world");
|
print!("Hello {}", "world");
|
||||||
println!("Hello {} {}", world, "world");
|
println!("Hello {} {}", world, "world");
|
||||||
println!("Hello {}", "world");
|
println!("Hello {}", "world");
|
||||||
|
println!("{} {:.4}", "a literal", 5);
|
||||||
|
|
||||||
// positional args don't change the fact
|
// positional args don't change the fact
|
||||||
// that we're using a literal -- this should
|
// that we're using a literal -- this should
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error: literal with an empty format string
|
error: literal with an empty format string
|
||||||
--> $DIR/print_literal.rs:25:24
|
--> $DIR/print_literal.rs:26:24
|
||||||
|
|
|
|
||||||
LL | print!("Hello {}", "world");
|
LL | print!("Hello {}", "world");
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@@ -12,7 +12,7 @@ LL + print!("Hello world");
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: literal with an empty format string
|
error: literal with an empty format string
|
||||||
--> $DIR/print_literal.rs:26:36
|
--> $DIR/print_literal.rs:27:36
|
||||||
|
|
|
|
||||||
LL | println!("Hello {} {}", world, "world");
|
LL | println!("Hello {} {}", world, "world");
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@@ -24,7 +24,7 @@ LL + println!("Hello {} world", world);
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: literal with an empty format string
|
error: literal with an empty format string
|
||||||
--> $DIR/print_literal.rs:27:26
|
--> $DIR/print_literal.rs:28:26
|
||||||
|
|
|
|
||||||
LL | println!("Hello {}", "world");
|
LL | println!("Hello {}", "world");
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@@ -36,7 +36,19 @@ LL + println!("Hello world");
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: literal with an empty format string
|
error: literal with an empty format string
|
||||||
--> $DIR/print_literal.rs:32:25
|
--> $DIR/print_literal.rs:29:26
|
||||||
|
|
|
||||||
|
LL | println!("{} {:.4}", "a literal", 5);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: try this
|
||||||
|
|
|
||||||
|
LL - println!("{} {:.4}", "a literal", 5);
|
||||||
|
LL + println!("a literal {:.4}", 5);
|
||||||
|
|
|
||||||
|
|
||||||
|
error: literal with an empty format string
|
||||||
|
--> $DIR/print_literal.rs:34:25
|
||||||
|
|
|
|
||||||
LL | println!("{0} {1}", "hello", "world");
|
LL | println!("{0} {1}", "hello", "world");
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@@ -48,7 +60,7 @@ LL + println!("hello {1}", "world");
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: literal with an empty format string
|
error: literal with an empty format string
|
||||||
--> $DIR/print_literal.rs:32:34
|
--> $DIR/print_literal.rs:34:34
|
||||||
|
|
|
|
||||||
LL | println!("{0} {1}", "hello", "world");
|
LL | println!("{0} {1}", "hello", "world");
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@@ -60,19 +72,7 @@ LL + println!("{0} world", "hello");
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: literal with an empty format string
|
error: literal with an empty format string
|
||||||
--> $DIR/print_literal.rs:33:25
|
--> $DIR/print_literal.rs:35:34
|
||||||
|
|
|
||||||
LL | println!("{1} {0}", "hello", "world");
|
|
||||||
| ^^^^^^^
|
|
||||||
|
|
|
||||||
help: try this
|
|
||||||
|
|
|
||||||
LL - println!("{1} {0}", "hello", "world");
|
|
||||||
LL + println!("{1} hello", "world");
|
|
||||||
|
|
|
||||||
|
|
||||||
error: literal with an empty format string
|
|
||||||
--> $DIR/print_literal.rs:33:34
|
|
||||||
|
|
|
|
||||||
LL | println!("{1} {0}", "hello", "world");
|
LL | println!("{1} {0}", "hello", "world");
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@@ -84,10 +84,22 @@ LL + println!("world {0}", "hello");
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: literal with an empty format string
|
error: literal with an empty format string
|
||||||
--> $DIR/print_literal.rs:36:29
|
--> $DIR/print_literal.rs:35:25
|
||||||
|
|
|
||||||
|
LL | println!("{1} {0}", "hello", "world");
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
help: try this
|
||||||
|
|
|
||||||
|
LL - println!("{1} {0}", "hello", "world");
|
||||||
|
LL + println!("{1} hello", "world");
|
||||||
|
|
|
||||||
|
|
||||||
|
error: literal with an empty format string
|
||||||
|
--> $DIR/print_literal.rs:38:35
|
||||||
|
|
|
|
||||||
LL | println!("{foo} {bar}", foo = "hello", bar = "world");
|
LL | println!("{foo} {bar}", foo = "hello", bar = "world");
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
help: try this
|
help: try this
|
||||||
|
|
|
|
||||||
@@ -96,10 +108,10 @@ LL + println!("hello {bar}", bar = "world");
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: literal with an empty format string
|
error: literal with an empty format string
|
||||||
--> $DIR/print_literal.rs:36:44
|
--> $DIR/print_literal.rs:38:50
|
||||||
|
|
|
|
||||||
LL | println!("{foo} {bar}", foo = "hello", bar = "world");
|
LL | println!("{foo} {bar}", foo = "hello", bar = "world");
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
help: try this
|
help: try this
|
||||||
|
|
|
|
||||||
@@ -108,22 +120,10 @@ LL + println!("{foo} world", foo = "hello");
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: literal with an empty format string
|
error: literal with an empty format string
|
||||||
--> $DIR/print_literal.rs:37:29
|
--> $DIR/print_literal.rs:39:50
|
||||||
|
|
|
|
||||||
LL | println!("{bar} {foo}", foo = "hello", bar = "world");
|
LL | println!("{bar} {foo}", foo = "hello", bar = "world");
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
||||||
help: try this
|
|
||||||
|
|
|
||||||
LL - println!("{bar} {foo}", foo = "hello", bar = "world");
|
|
||||||
LL + println!("{bar} hello", bar = "world");
|
|
||||||
|
|
|
||||||
|
|
||||||
error: literal with an empty format string
|
|
||||||
--> $DIR/print_literal.rs:37:44
|
|
||||||
|
|
|
||||||
LL | println!("{bar} {foo}", foo = "hello", bar = "world");
|
|
||||||
| ^^^^^^^^^^^^^
|
|
||||||
|
|
|
|
||||||
help: try this
|
help: try this
|
||||||
|
|
|
|
||||||
@@ -131,5 +131,17 @@ LL - println!("{bar} {foo}", foo = "hello", bar = "world");
|
|||||||
LL + println!("world {foo}", foo = "hello");
|
LL + println!("world {foo}", foo = "hello");
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 11 previous errors
|
error: literal with an empty format string
|
||||||
|
--> $DIR/print_literal.rs:39:35
|
||||||
|
|
|
||||||
|
LL | println!("{bar} {foo}", foo = "hello", bar = "world");
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
help: try this
|
||||||
|
|
|
||||||
|
LL - println!("{bar} {foo}", foo = "hello", bar = "world");
|
||||||
|
LL + println!("{bar} hello", bar = "world");
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 12 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -48,5 +48,13 @@ fn main() {
|
|||||||
print!("\r\n");
|
print!("\r\n");
|
||||||
print!("foo\r\n");
|
print!("foo\r\n");
|
||||||
print!("\\r\n"); //~ ERROR
|
print!("\\r\n"); //~ ERROR
|
||||||
print!("foo\rbar\n") // ~ ERROR
|
print!("foo\rbar\n");
|
||||||
|
|
||||||
|
// Ignore expanded format strings
|
||||||
|
macro_rules! newline {
|
||||||
|
() => {
|
||||||
|
"\n"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
print!(newline!());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ LL | | );
|
|||||||
help: use `println!` instead
|
help: use `println!` instead
|
||||||
|
|
|
|
||||||
LL ~ println!(
|
LL ~ println!(
|
||||||
LL ~ ""
|
LL ~
|
||||||
|
|
|
|
||||||
|
|
||||||
error: using `print!()` with a format string that ends in a single newline
|
error: using `print!()` with a format string that ends in a single newline
|
||||||
@@ -98,7 +98,7 @@ LL | | );
|
|||||||
help: use `println!` instead
|
help: use `println!` instead
|
||||||
|
|
|
|
||||||
LL ~ println!(
|
LL ~ println!(
|
||||||
LL ~ r""
|
LL ~
|
||||||
|
|
|
|
||||||
|
|
||||||
error: using `print!()` with a format string that ends in a single newline
|
error: using `print!()` with a format string that ends in a single newline
|
||||||
@@ -113,17 +113,5 @@ LL - print!("/r/n"); //~ ERROR
|
|||||||
LL + println!("/r"); //~ ERROR
|
LL + println!("/r"); //~ ERROR
|
||||||
|
|
|
|
||||||
|
|
||||||
error: using `print!()` with a format string that ends in a single newline
|
error: aborting due to 9 previous errors
|
||||||
--> $DIR/print_with_newline.rs:51:5
|
|
||||||
|
|
|
||||||
LL | print!("foo/rbar/n") // ~ ERROR
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
help: use `println!` instead
|
|
||||||
|
|
|
||||||
LL - print!("foo/rbar/n") // ~ ERROR
|
|
||||||
LL + println!("foo/rbar") // ~ ERROR
|
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,36 @@
|
|||||||
error: using `println!("")`
|
error: empty string literal in `println!`
|
||||||
--> $DIR/println_empty_string.rs:6:5
|
--> $DIR/println_empty_string.rs:6:5
|
||||||
|
|
|
|
||||||
LL | println!("");
|
LL | println!("");
|
||||||
| ^^^^^^^^^^^^ help: replace it with: `println!()`
|
| ^^^^^^^^^--^
|
||||||
|
| |
|
||||||
|
| help: remove the empty string
|
||||||
|
|
|
|
||||||
= note: `-D clippy::println-empty-string` implied by `-D warnings`
|
= note: `-D clippy::println-empty-string` implied by `-D warnings`
|
||||||
|
|
||||||
error: using `println!("")`
|
error: empty string literal in `println!`
|
||||||
--> $DIR/println_empty_string.rs:9:14
|
--> $DIR/println_empty_string.rs:9:14
|
||||||
|
|
|
|
||||||
LL | _ => println!(""),
|
LL | _ => println!(""),
|
||||||
| ^^^^^^^^^^^^ help: replace it with: `println!()`
|
| ^^^^^^^^^--^
|
||||||
|
| |
|
||||||
|
| help: remove the empty string
|
||||||
|
|
||||||
error: using `eprintln!("")`
|
error: empty string literal in `eprintln!`
|
||||||
--> $DIR/println_empty_string.rs:13:5
|
--> $DIR/println_empty_string.rs:13:5
|
||||||
|
|
|
|
||||||
LL | eprintln!("");
|
LL | eprintln!("");
|
||||||
| ^^^^^^^^^^^^^ help: replace it with: `eprintln!()`
|
| ^^^^^^^^^^--^
|
||||||
|
| |
|
||||||
|
| help: remove the empty string
|
||||||
|
|
||||||
error: using `eprintln!("")`
|
error: empty string literal in `eprintln!`
|
||||||
--> $DIR/println_empty_string.rs:16:14
|
--> $DIR/println_empty_string.rs:16:14
|
||||||
|
|
|
|
||||||
LL | _ => eprintln!(""),
|
LL | _ => eprintln!(""),
|
||||||
| ^^^^^^^^^^^^^ help: replace it with: `eprintln!()`
|
| ^^^^^^^^^^--^
|
||||||
|
| |
|
||||||
|
| help: remove the empty string
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#![allow(invalid_value)]
|
#![allow(invalid_value)]
|
||||||
#![allow(enum_intrinsics_non_enums)]
|
#![allow(enum_intrinsics_non_enums)]
|
||||||
#![allow(non_fmt_panics)]
|
#![allow(non_fmt_panics)]
|
||||||
|
#![allow(named_arguments_used_positionally)]
|
||||||
#![allow(temporary_cstring_as_ptr)]
|
#![allow(temporary_cstring_as_ptr)]
|
||||||
#![allow(unknown_lints)]
|
#![allow(unknown_lints)]
|
||||||
#![allow(unused_labels)]
|
#![allow(unused_labels)]
|
||||||
@@ -69,6 +70,7 @@
|
|||||||
#![warn(invalid_value)]
|
#![warn(invalid_value)]
|
||||||
#![warn(enum_intrinsics_non_enums)]
|
#![warn(enum_intrinsics_non_enums)]
|
||||||
#![warn(non_fmt_panics)]
|
#![warn(non_fmt_panics)]
|
||||||
|
#![warn(named_arguments_used_positionally)]
|
||||||
#![warn(temporary_cstring_as_ptr)]
|
#![warn(temporary_cstring_as_ptr)]
|
||||||
#![warn(unknown_lints)]
|
#![warn(unknown_lints)]
|
||||||
#![warn(unused_labels)]
|
#![warn(unused_labels)]
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#![allow(invalid_value)]
|
#![allow(invalid_value)]
|
||||||
#![allow(enum_intrinsics_non_enums)]
|
#![allow(enum_intrinsics_non_enums)]
|
||||||
#![allow(non_fmt_panics)]
|
#![allow(non_fmt_panics)]
|
||||||
|
#![allow(named_arguments_used_positionally)]
|
||||||
#![allow(temporary_cstring_as_ptr)]
|
#![allow(temporary_cstring_as_ptr)]
|
||||||
#![allow(unknown_lints)]
|
#![allow(unknown_lints)]
|
||||||
#![allow(unused_labels)]
|
#![allow(unused_labels)]
|
||||||
@@ -69,6 +70,7 @@
|
|||||||
#![warn(clippy::invalid_ref)]
|
#![warn(clippy::invalid_ref)]
|
||||||
#![warn(clippy::mem_discriminant_non_enum)]
|
#![warn(clippy::mem_discriminant_non_enum)]
|
||||||
#![warn(clippy::panic_params)]
|
#![warn(clippy::panic_params)]
|
||||||
|
#![warn(clippy::positional_named_format_parameters)]
|
||||||
#![warn(clippy::temporary_cstring_as_ptr)]
|
#![warn(clippy::temporary_cstring_as_ptr)]
|
||||||
#![warn(clippy::unknown_clippy_lints)]
|
#![warn(clippy::unknown_clippy_lints)]
|
||||||
#![warn(clippy::unused_label)]
|
#![warn(clippy::unused_label)]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
|
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
|
||||||
--> $DIR/rename.rs:38:9
|
--> $DIR/rename.rs:39:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::blacklisted_name)]
|
LL | #![warn(clippy::blacklisted_name)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
|
||||||
@@ -7,220 +7,226 @@ LL | #![warn(clippy::blacklisted_name)]
|
|||||||
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
|
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
|
||||||
|
|
||||||
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
|
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
|
||||||
--> $DIR/rename.rs:39:9
|
--> $DIR/rename.rs:40:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::block_in_if_condition_expr)]
|
LL | #![warn(clippy::block_in_if_condition_expr)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
||||||
|
|
||||||
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
|
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
|
||||||
--> $DIR/rename.rs:40:9
|
--> $DIR/rename.rs:41:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::block_in_if_condition_stmt)]
|
LL | #![warn(clippy::block_in_if_condition_stmt)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
||||||
|
|
||||||
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
|
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
|
||||||
--> $DIR/rename.rs:41:9
|
--> $DIR/rename.rs:42:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::box_vec)]
|
LL | #![warn(clippy::box_vec)]
|
||||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
|
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
|
||||||
|
|
||||||
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
|
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
|
||||||
--> $DIR/rename.rs:42:9
|
--> $DIR/rename.rs:43:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::const_static_lifetime)]
|
LL | #![warn(clippy::const_static_lifetime)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
|
||||||
|
|
||||||
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
|
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
|
||||||
--> $DIR/rename.rs:43:9
|
--> $DIR/rename.rs:44:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::cyclomatic_complexity)]
|
LL | #![warn(clippy::cyclomatic_complexity)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
|
||||||
|
|
||||||
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
|
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
|
||||||
--> $DIR/rename.rs:44:9
|
--> $DIR/rename.rs:45:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::disallowed_method)]
|
LL | #![warn(clippy::disallowed_method)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
|
||||||
|
|
||||||
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
|
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
|
||||||
--> $DIR/rename.rs:45:9
|
--> $DIR/rename.rs:46:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::disallowed_type)]
|
LL | #![warn(clippy::disallowed_type)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
|
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
|
||||||
|
|
||||||
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
|
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
|
||||||
--> $DIR/rename.rs:46:9
|
--> $DIR/rename.rs:47:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::eval_order_dependence)]
|
LL | #![warn(clippy::eval_order_dependence)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
|
||||||
|
|
||||||
error: lint `clippy::for_loop_over_option` has been renamed to `clippy::for_loops_over_fallibles`
|
error: lint `clippy::for_loop_over_option` has been renamed to `clippy::for_loops_over_fallibles`
|
||||||
--> $DIR/rename.rs:47:9
|
--> $DIR/rename.rs:48:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::for_loop_over_option)]
|
LL | #![warn(clippy::for_loop_over_option)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
|
||||||
|
|
||||||
error: lint `clippy::for_loop_over_result` has been renamed to `clippy::for_loops_over_fallibles`
|
error: lint `clippy::for_loop_over_result` has been renamed to `clippy::for_loops_over_fallibles`
|
||||||
--> $DIR/rename.rs:48:9
|
--> $DIR/rename.rs:49:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::for_loop_over_result)]
|
LL | #![warn(clippy::for_loop_over_result)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
|
||||||
|
|
||||||
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
|
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
|
||||||
--> $DIR/rename.rs:49:9
|
--> $DIR/rename.rs:50:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::identity_conversion)]
|
LL | #![warn(clippy::identity_conversion)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
|
||||||
|
|
||||||
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
|
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
|
||||||
--> $DIR/rename.rs:50:9
|
--> $DIR/rename.rs:51:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::if_let_some_result)]
|
LL | #![warn(clippy::if_let_some_result)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
|
||||||
|
|
||||||
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
|
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
|
||||||
--> $DIR/rename.rs:51:9
|
--> $DIR/rename.rs:52:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::logic_bug)]
|
LL | #![warn(clippy::logic_bug)]
|
||||||
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
|
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
|
||||||
|
|
||||||
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
|
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
|
||||||
--> $DIR/rename.rs:52:9
|
--> $DIR/rename.rs:53:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::new_without_default_derive)]
|
LL | #![warn(clippy::new_without_default_derive)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
|
||||||
|
|
||||||
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
|
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
|
||||||
--> $DIR/rename.rs:53:9
|
--> $DIR/rename.rs:54:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::option_and_then_some)]
|
LL | #![warn(clippy::option_and_then_some)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
|
||||||
|
|
||||||
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
|
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
|
||||||
--> $DIR/rename.rs:54:9
|
--> $DIR/rename.rs:55:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::option_expect_used)]
|
LL | #![warn(clippy::option_expect_used)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||||
|
|
||||||
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
|
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
|
||||||
--> $DIR/rename.rs:55:9
|
--> $DIR/rename.rs:56:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::option_map_unwrap_or)]
|
LL | #![warn(clippy::option_map_unwrap_or)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||||
|
|
||||||
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
||||||
--> $DIR/rename.rs:56:9
|
--> $DIR/rename.rs:57:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::option_map_unwrap_or_else)]
|
LL | #![warn(clippy::option_map_unwrap_or_else)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||||
|
|
||||||
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
|
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
|
||||||
--> $DIR/rename.rs:57:9
|
--> $DIR/rename.rs:58:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::option_unwrap_used)]
|
LL | #![warn(clippy::option_unwrap_used)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||||
|
|
||||||
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
|
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
|
||||||
--> $DIR/rename.rs:58:9
|
--> $DIR/rename.rs:59:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::ref_in_deref)]
|
LL | #![warn(clippy::ref_in_deref)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
|
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
|
||||||
|
|
||||||
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
|
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
|
||||||
--> $DIR/rename.rs:59:9
|
--> $DIR/rename.rs:60:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::result_expect_used)]
|
LL | #![warn(clippy::result_expect_used)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||||
|
|
||||||
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
||||||
--> $DIR/rename.rs:60:9
|
--> $DIR/rename.rs:61:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::result_map_unwrap_or_else)]
|
LL | #![warn(clippy::result_map_unwrap_or_else)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||||
|
|
||||||
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
|
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
|
||||||
--> $DIR/rename.rs:61:9
|
--> $DIR/rename.rs:62:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::result_unwrap_used)]
|
LL | #![warn(clippy::result_unwrap_used)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||||
|
|
||||||
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
|
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
|
||||||
--> $DIR/rename.rs:62:9
|
--> $DIR/rename.rs:63:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::single_char_push_str)]
|
LL | #![warn(clippy::single_char_push_str)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
|
||||||
|
|
||||||
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
|
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
|
||||||
--> $DIR/rename.rs:63:9
|
--> $DIR/rename.rs:64:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::stutter)]
|
LL | #![warn(clippy::stutter)]
|
||||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
|
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
|
||||||
|
|
||||||
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
|
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
|
||||||
--> $DIR/rename.rs:64:9
|
--> $DIR/rename.rs:65:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::to_string_in_display)]
|
LL | #![warn(clippy::to_string_in_display)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
|
||||||
|
|
||||||
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
|
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
|
||||||
--> $DIR/rename.rs:65:9
|
--> $DIR/rename.rs:66:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::zero_width_space)]
|
LL | #![warn(clippy::zero_width_space)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
|
||||||
|
|
||||||
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
|
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
|
||||||
--> $DIR/rename.rs:66:9
|
--> $DIR/rename.rs:67:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::drop_bounds)]
|
LL | #![warn(clippy::drop_bounds)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
|
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
|
||||||
|
|
||||||
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
|
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
|
||||||
--> $DIR/rename.rs:67:9
|
--> $DIR/rename.rs:68:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::into_iter_on_array)]
|
LL | #![warn(clippy::into_iter_on_array)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
|
||||||
|
|
||||||
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
|
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
|
||||||
--> $DIR/rename.rs:68:9
|
--> $DIR/rename.rs:69:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::invalid_atomic_ordering)]
|
LL | #![warn(clippy::invalid_atomic_ordering)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
|
||||||
|
|
||||||
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
|
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
|
||||||
--> $DIR/rename.rs:69:9
|
--> $DIR/rename.rs:70:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::invalid_ref)]
|
LL | #![warn(clippy::invalid_ref)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
|
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
|
||||||
|
|
||||||
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
|
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
|
||||||
--> $DIR/rename.rs:70:9
|
--> $DIR/rename.rs:71:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::mem_discriminant_non_enum)]
|
LL | #![warn(clippy::mem_discriminant_non_enum)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
|
||||||
|
|
||||||
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
|
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
|
||||||
--> $DIR/rename.rs:71:9
|
--> $DIR/rename.rs:72:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::panic_params)]
|
LL | #![warn(clippy::panic_params)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
|
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
|
||||||
|
|
||||||
|
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
|
||||||
|
--> $DIR/rename.rs:73:9
|
||||||
|
|
|
||||||
|
LL | #![warn(clippy::positional_named_format_parameters)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
|
||||||
|
|
||||||
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
|
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
|
||||||
--> $DIR/rename.rs:72:9
|
--> $DIR/rename.rs:74:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::temporary_cstring_as_ptr)]
|
LL | #![warn(clippy::temporary_cstring_as_ptr)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
|
||||||
|
|
||||||
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
|
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
|
||||||
--> $DIR/rename.rs:73:9
|
--> $DIR/rename.rs:75:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::unknown_clippy_lints)]
|
LL | #![warn(clippy::unknown_clippy_lints)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
|
||||||
|
|
||||||
error: lint `clippy::unused_label` has been renamed to `unused_labels`
|
error: lint `clippy::unused_label` has been renamed to `unused_labels`
|
||||||
--> $DIR/rename.rs:74:9
|
--> $DIR/rename.rs:76:9
|
||||||
|
|
|
|
||||||
LL | #![warn(clippy::unused_label)]
|
LL | #![warn(clippy::unused_label)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
|
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
|
||||||
|
|
||||||
error: aborting due to 37 previous errors
|
error: aborting due to 38 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -417,3 +417,12 @@ mod issue_9351 {
|
|||||||
predicates_are_satisfied(id("abc".to_string()));
|
predicates_are_satisfied(id("abc".to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod issue_9504 {
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
async fn foo<S: AsRef<str>>(_: S) {}
|
||||||
|
async fn bar() {
|
||||||
|
foo(std::path::PathBuf::new().to_string_lossy().to_string()).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user