mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 17:24:06 +00:00
Merge remote-tracking branch 'upstream/master' into rustup
This commit is contained in:
commit
9d73371663
6
.github/driver.sh
vendored
6
.github/driver.sh
vendored
@ -24,16 +24,16 @@ unset CARGO_MANIFEST_DIR
|
||||
# FIXME: How to match the clippy invocation in compile-test.rs?
|
||||
./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/double_neg.rs 2>double_neg.stderr && exit 1
|
||||
sed -e "s,tests/ui,\$DIR," -e "/= help/d" double_neg.stderr >normalized.stderr
|
||||
diff normalized.stderr tests/ui/double_neg.stderr
|
||||
diff -u normalized.stderr tests/ui/double_neg.stderr
|
||||
|
||||
# make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same
|
||||
SYSROOT=$(rustc --print sysroot)
|
||||
diff <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose)
|
||||
diff -u <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose)
|
||||
|
||||
echo "fn main() {}" >target/driver_test.rs
|
||||
# we can't run 2 rustcs on the same file at the same time
|
||||
CLIPPY=$(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver ./target/driver_test.rs --rustc)
|
||||
RUSTC=$(rustc ./target/driver_test.rs)
|
||||
diff <($CLIPPY) <($RUSTC)
|
||||
diff -u <($CLIPPY) <($RUSTC)
|
||||
|
||||
# TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR
|
||||
|
@ -1665,6 +1665,7 @@ Released 2018-09-13
|
||||
[`cognitive_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity
|
||||
[`collapsible_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
|
||||
[`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain
|
||||
[`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty
|
||||
[`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator
|
||||
[`create_dir`]: https://rust-lang.github.io/rust-clippy/master/index.html#create_dir
|
||||
[`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute
|
||||
@ -1802,6 +1803,7 @@ Released 2018-09-13
|
||||
[`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or
|
||||
[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
|
||||
[`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone
|
||||
[`map_collect_result_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_collect_result_unit
|
||||
[`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry
|
||||
[`map_err_ignore`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_err_ignore
|
||||
[`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten
|
||||
|
@ -63,9 +63,10 @@ To figure out how this syntax structure is encoded in the AST, it is recommended
|
||||
Usually the lint will end up to be a nested series of matches and ifs, [like so][deep-nesting].
|
||||
But we can make it nest-less by using [if_chain] macro, [like this][nest-less].
|
||||
|
||||
[`E-medium`] issues are generally pretty easy too, though it's recommended you work on an E-easy issue first.
|
||||
They are mostly classified as [`E-medium`], since they might be somewhat involved code wise,
|
||||
but not difficult per-se.
|
||||
[`E-medium`] issues are generally pretty easy too, though it's recommended you work on an [`good first issue`]
|
||||
first. Sometimes they are only somewhat involved code wise, but not difficult per-se.
|
||||
Note that [`E-medium`] issues may require some knowledge of Clippy internals or some
|
||||
debugging to find the actual problem behind the issue.
|
||||
|
||||
[`T-middle`] issues can be more involved and require verifying types. The [`ty`] module contains a
|
||||
lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of
|
||||
|
@ -11,7 +11,7 @@ use std::path::PathBuf;
|
||||
// code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details
|
||||
|
||||
pub fn run(rustc_path: Option<&str>) {
|
||||
// we can unwrap here because the arg is required here
|
||||
// we can unwrap here because the arg is required by clap
|
||||
let rustc_path = PathBuf::from(rustc_path.unwrap());
|
||||
assert!(rustc_path.is_dir(), "path is not a directory");
|
||||
let rustc_source_basedir = rustc_path.join("compiler");
|
||||
@ -49,6 +49,15 @@ fn inject_deps_into_manifest(
|
||||
cargo_toml: &str,
|
||||
lib_rs: &str,
|
||||
) -> std::io::Result<()> {
|
||||
// do not inject deps if we have aleady done so
|
||||
if cargo_toml.contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]") {
|
||||
eprintln!(
|
||||
"cargo dev ra-setup: warning: deps already found inside {}, doing nothing.",
|
||||
manifest_path
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let extern_crates = lib_rs
|
||||
.lines()
|
||||
// get the deps
|
||||
|
@ -88,9 +88,28 @@ impl<'tcx> LateLintPass<'tcx> for Arithmetic {
|
||||
|
||||
let (l_ty, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
|
||||
if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() {
|
||||
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
|
||||
self.expr_span = Some(expr.span);
|
||||
} else if l_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
|
||||
match op.node {
|
||||
hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind {
|
||||
hir::ExprKind::Lit(_lit) => (),
|
||||
hir::ExprKind::Unary(hir::UnOp::UnNeg, expr) => {
|
||||
if let hir::ExprKind::Lit(lit) = &expr.kind {
|
||||
if let rustc_ast::ast::LitKind::Int(1, _) = lit.node {
|
||||
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
|
||||
self.expr_span = Some(expr.span);
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
|
||||
self.expr_span = Some(expr.span);
|
||||
},
|
||||
},
|
||||
_ => {
|
||||
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
|
||||
self.expr_span = Some(expr.span);
|
||||
},
|
||||
}
|
||||
} else if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
|
||||
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
|
||||
self.expr_span = Some(expr.span);
|
||||
}
|
||||
|
@ -92,13 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|
||||
|db| {
|
||||
cx.tcx.infer_ctxt().enter(|infcx| {
|
||||
for FulfillmentError { obligation, .. } in send_errors {
|
||||
infcx.maybe_note_obligation_cause_for_async_await(
|
||||
db,
|
||||
&obligation,
|
||||
);
|
||||
if let Trait(trait_pred, _) =
|
||||
obligation.predicate.skip_binders()
|
||||
{
|
||||
infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
|
||||
if let Trait(trait_pred, _) = obligation.predicate.skip_binders() {
|
||||
db.note(&format!(
|
||||
"`{}` doesn't implement `{}`",
|
||||
trait_pred.self_ty(),
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
use crate::utils::span_lint;
|
||||
use rustc_ast::ast::{Block, ItemKind, StmtKind};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
declare_clippy_lint! {
|
||||
@ -53,7 +54,7 @@ declare_lint_pass!(ItemsAfterStatements => [ITEMS_AFTER_STATEMENTS]);
|
||||
|
||||
impl EarlyLintPass for ItemsAfterStatements {
|
||||
fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) {
|
||||
if item.span.from_expansion() {
|
||||
if in_external_macro(cx.sess(), item.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -67,7 +68,7 @@ impl EarlyLintPass for ItemsAfterStatements {
|
||||
// lint on all further items
|
||||
for stmt in stmts {
|
||||
if let StmtKind::Item(ref it) = *stmt {
|
||||
if it.span.from_expansion() {
|
||||
if in_external_macro(cx.sess(), it.span) {
|
||||
return;
|
||||
}
|
||||
if let ItemKind::MacroDef(..) = it.kind {
|
||||
|
@ -68,7 +68,44 @@ declare_clippy_lint! {
|
||||
"traits or impls with a public `len` method but no corresponding `is_empty` method"
|
||||
}
|
||||
|
||||
declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY]);
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for comparing to an empty slice such as "" or [],`
|
||||
/// and suggests using `.is_empty()` where applicable.
|
||||
///
|
||||
/// **Why is this bad?** Some structures can answer `.is_empty()` much faster
|
||||
/// than checking for equality. So it is good to get into the habit of using
|
||||
/// `.is_empty()`, and having it is cheap.
|
||||
/// Besides, it makes the intent clearer than a manual comparison in some contexts.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```ignore
|
||||
/// if s == "" {
|
||||
/// ..
|
||||
/// }
|
||||
///
|
||||
/// if arr == [] {
|
||||
/// ..
|
||||
/// }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```ignore
|
||||
/// if s.is_empty() {
|
||||
/// ..
|
||||
/// }
|
||||
///
|
||||
/// if arr.is_empty() {
|
||||
/// ..
|
||||
/// }
|
||||
/// ```
|
||||
pub COMPARISON_TO_EMPTY,
|
||||
style,
|
||||
"checking `x == \"\"` or `x == []` (or similar) when `.is_empty()` could be used instead"
|
||||
}
|
||||
|
||||
declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY, COMPARISON_TO_EMPTY]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for LenZero {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
@ -221,6 +258,8 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>
|
||||
}
|
||||
|
||||
check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to)
|
||||
} else {
|
||||
check_empty_expr(cx, span, method, lit, op)
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,6 +297,42 @@ fn check_len(
|
||||
}
|
||||
}
|
||||
|
||||
fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Expr<'_>, op: &str) {
|
||||
if (is_empty_array(lit2) || is_empty_string(lit2)) && has_is_empty(cx, lit1) {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
COMPARISON_TO_EMPTY,
|
||||
span,
|
||||
"comparison to empty slice",
|
||||
&format!("using `{}is_empty` is clearer and more explicit", op),
|
||||
format!(
|
||||
"{}{}.is_empty()",
|
||||
op,
|
||||
snippet_with_applicability(cx, lit1.span, "_", &mut applicability)
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_empty_string(expr: &Expr<'_>) -> bool {
|
||||
if let ExprKind::Lit(ref lit) = expr.kind {
|
||||
if let LitKind::Str(lit, _) = lit.node {
|
||||
let lit = lit.as_str();
|
||||
return lit == "";
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn is_empty_array(expr: &Expr<'_>) -> bool {
|
||||
if let ExprKind::Array(ref arr) = expr.kind {
|
||||
return arr.is_empty();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Checks if this type has an `is_empty` method.
|
||||
fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
/// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
|
||||
|
@ -615,6 +615,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
&large_const_arrays::LARGE_CONST_ARRAYS,
|
||||
&large_enum_variant::LARGE_ENUM_VARIANT,
|
||||
&large_stack_arrays::LARGE_STACK_ARRAYS,
|
||||
&len_zero::COMPARISON_TO_EMPTY,
|
||||
&len_zero::LEN_WITHOUT_IS_EMPTY,
|
||||
&len_zero::LEN_ZERO,
|
||||
&let_if_seq::USELESS_LET_IF_SEQ,
|
||||
@ -702,6 +703,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
&methods::ITER_NTH_ZERO,
|
||||
&methods::ITER_SKIP_NEXT,
|
||||
&methods::MANUAL_SATURATING_ARITHMETIC,
|
||||
&methods::MAP_COLLECT_RESULT_UNIT,
|
||||
&methods::MAP_FLATTEN,
|
||||
&methods::MAP_UNWRAP_OR,
|
||||
&methods::NEW_RET_NO_SELF,
|
||||
@ -1366,6 +1368,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
LintId::of(&int_plus_one::INT_PLUS_ONE),
|
||||
LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS),
|
||||
LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT),
|
||||
LintId::of(&len_zero::COMPARISON_TO_EMPTY),
|
||||
LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
|
||||
LintId::of(&len_zero::LEN_ZERO),
|
||||
LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
|
||||
@ -1427,6 +1430,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
LintId::of(&methods::ITER_NTH_ZERO),
|
||||
LintId::of(&methods::ITER_SKIP_NEXT),
|
||||
LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC),
|
||||
LintId::of(&methods::MAP_COLLECT_RESULT_UNIT),
|
||||
LintId::of(&methods::NEW_RET_NO_SELF),
|
||||
LintId::of(&methods::OK_EXPECT),
|
||||
LintId::of(&methods::OPTION_AS_REF_DEREF),
|
||||
@ -1592,6 +1596,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
LintId::of(&functions::RESULT_UNIT_ERR),
|
||||
LintId::of(&if_let_some_result::IF_LET_SOME_RESULT),
|
||||
LintId::of(&inherent_to_string::INHERENT_TO_STRING),
|
||||
LintId::of(&len_zero::COMPARISON_TO_EMPTY),
|
||||
LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
|
||||
LintId::of(&len_zero::LEN_ZERO),
|
||||
LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING),
|
||||
@ -1621,6 +1626,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
LintId::of(&methods::ITER_NTH_ZERO),
|
||||
LintId::of(&methods::ITER_SKIP_NEXT),
|
||||
LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC),
|
||||
LintId::of(&methods::MAP_COLLECT_RESULT_UNIT),
|
||||
LintId::of(&methods::NEW_RET_NO_SELF),
|
||||
LintId::of(&methods::OK_EXPECT),
|
||||
LintId::of(&methods::OPTION_MAP_OR_NONE),
|
||||
|
@ -32,8 +32,7 @@ use crate::utils::{
|
||||
is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath,
|
||||
match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, remove_blocks, return_ty,
|
||||
single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
|
||||
span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty_depth,
|
||||
SpanlessEq,
|
||||
span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty_depth, SpanlessEq,
|
||||
};
|
||||
|
||||
declare_clippy_lint! {
|
||||
@ -1349,6 +1348,27 @@ declare_clippy_lint! {
|
||||
"using unnecessary lazy evaluation, which can be replaced with simpler eager evaluation"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for usage of `_.map(_).collect::<Result<(),_>()`.
|
||||
///
|
||||
/// **Why is this bad?** Using `try_for_each` instead is more readable and idiomatic.
|
||||
///
|
||||
/// **Known problems:** None
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
/// (0..3).map(|t| Err(t)).collect::<Result<(), _>>();
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// (0..3).try_for_each(|t| Err(t));
|
||||
/// ```
|
||||
pub MAP_COLLECT_RESULT_UNIT,
|
||||
style,
|
||||
"using `.map(_).collect::<Result<(),_>()`, which can be replaced with `try_for_each`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(Methods => [
|
||||
UNWRAP_USED,
|
||||
EXPECT_USED,
|
||||
@ -1398,6 +1418,7 @@ declare_lint_pass!(Methods => [
|
||||
FILETYPE_IS_FILE,
|
||||
OPTION_AS_REF_DEREF,
|
||||
UNNECESSARY_LAZY_EVALUATIONS,
|
||||
MAP_COLLECT_RESULT_UNIT,
|
||||
]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Methods {
|
||||
@ -1479,6 +1500,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
|
||||
["unwrap_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "unwrap_or"),
|
||||
["get_or_insert_with", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "get_or_insert"),
|
||||
["ok_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "ok_or"),
|
||||
["collect", "map"] => lint_map_collect(cx, expr, arg_lists[1], arg_lists[0]),
|
||||
_ => {},
|
||||
}
|
||||
|
||||
@ -1712,7 +1734,7 @@ fn lint_or_fun_call<'tcx>(
|
||||
"try this",
|
||||
format!(
|
||||
"{}.unwrap_or_default()",
|
||||
snippet_with_applicability(cx, self_expr.span, "_", &mut applicability)
|
||||
snippet_with_applicability(cx, self_expr.span, "..", &mut applicability)
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
@ -2119,7 +2141,7 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::
|
||||
return;
|
||||
};
|
||||
|
||||
let snippet = snippet_with_macro_callsite(cx, arg.span, "_");
|
||||
let snippet = snippet_with_macro_callsite(cx, arg.span, "..");
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
@ -2155,9 +2177,9 @@ fn lint_string_extend(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::E
|
||||
"try this",
|
||||
format!(
|
||||
"{}.push_str({}{})",
|
||||
snippet_with_applicability(cx, args[0].span, "_", &mut applicability),
|
||||
snippet_with_applicability(cx, args[0].span, "..", &mut applicability),
|
||||
ref_str,
|
||||
snippet_with_applicability(cx, target.span, "_", &mut applicability)
|
||||
snippet_with_applicability(cx, target.span, "..", &mut applicability)
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
@ -2404,7 +2426,7 @@ fn lint_get_unwrap<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, get_args:
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let expr_ty = cx.typeck_results().expr_ty(&get_args[0]);
|
||||
let get_args_str = if get_args.len() > 1 {
|
||||
snippet_with_applicability(cx, get_args[1].span, "_", &mut applicability)
|
||||
snippet_with_applicability(cx, get_args[1].span, "..", &mut applicability)
|
||||
} else {
|
||||
return; // not linting on a .get().unwrap() chain or variant
|
||||
};
|
||||
@ -2464,7 +2486,7 @@ fn lint_get_unwrap<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, get_args:
|
||||
format!(
|
||||
"{}{}[{}]",
|
||||
borrow_str,
|
||||
snippet_with_applicability(cx, get_args[0].span, "_", &mut applicability),
|
||||
snippet_with_applicability(cx, get_args[0].span, "..", &mut applicability),
|
||||
get_args_str
|
||||
),
|
||||
applicability,
|
||||
@ -2480,7 +2502,7 @@ fn lint_iter_skip_next(cx: &LateContext<'_>, expr: &hir::Expr<'_>, skip_args: &[
|
||||
cx,
|
||||
ITER_SKIP_NEXT,
|
||||
expr.span.trim_start(caller.span).unwrap(),
|
||||
"called `skip(x).next()` on an iterator",
|
||||
"called `skip(..).next()` on an iterator",
|
||||
"use `nth` instead",
|
||||
hint,
|
||||
Applicability::MachineApplicable,
|
||||
@ -2683,11 +2705,11 @@ fn lint_map_unwrap_or_else<'tcx>(
|
||||
|
||||
// lint message
|
||||
let msg = if is_option {
|
||||
"called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling \
|
||||
`map_or_else(g, f)` instead"
|
||||
"called `map(<f>).unwrap_or_else(<g>)` on an `Option` value. This can be done more directly by calling \
|
||||
`map_or_else(<g>, <f>)` instead"
|
||||
} else {
|
||||
"called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling \
|
||||
`.map_or_else(g, f)` instead"
|
||||
"called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling \
|
||||
`.map_or_else(<g>, <f>)` instead"
|
||||
};
|
||||
// get snippets for args to map() and unwrap_or_else()
|
||||
let map_snippet = snippet(cx, map_args[1].span, "..");
|
||||
@ -2697,16 +2719,15 @@ fn lint_map_unwrap_or_else<'tcx>(
|
||||
let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1;
|
||||
let same_span = map_args[1].span.ctxt() == unwrap_args[1].span.ctxt();
|
||||
if same_span && !multiline {
|
||||
span_lint_and_note(
|
||||
let var_snippet = snippet(cx, map_args[0].span, "..");
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MAP_UNWRAP_OR,
|
||||
expr.span,
|
||||
msg,
|
||||
None,
|
||||
&format!(
|
||||
"replace `map({0}).unwrap_or_else({1})` with `map_or_else({1}, {0})`",
|
||||
map_snippet, unwrap_snippet,
|
||||
),
|
||||
"try this",
|
||||
format!("{}.map_or_else({}, {})", var_snippet, unwrap_snippet, map_snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
} else if same_span && multiline {
|
||||
@ -2753,8 +2774,8 @@ fn lint_map_or_none<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map
|
||||
if is_option {
|
||||
let self_snippet = snippet(cx, map_or_args[0].span, "..");
|
||||
let func_snippet = snippet(cx, map_or_args[2].span, "..");
|
||||
let msg = "called `map_or(None, f)` on an `Option` value. This can be done more directly by calling \
|
||||
`and_then(f)` instead";
|
||||
let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
|
||||
`and_then(..)` instead";
|
||||
(
|
||||
OPTION_MAP_OR_NONE,
|
||||
msg,
|
||||
@ -2792,18 +2813,20 @@ fn lint_map_or_none<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map
|
||||
fn lint_filter_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, filter_args: &'tcx [hir::Expr<'_>]) {
|
||||
// lint if caller of `.filter().next()` is an Iterator
|
||||
if match_trait_method(cx, expr, &paths::ITERATOR) {
|
||||
let msg = "called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling \
|
||||
`.find(p)` instead.";
|
||||
let msg = "called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling \
|
||||
`.find(..)` instead.";
|
||||
let filter_snippet = snippet(cx, filter_args[1].span, "..");
|
||||
if filter_snippet.lines().count() <= 1 {
|
||||
let iter_snippet = snippet(cx, filter_args[0].span, "..");
|
||||
// add note if not multi-line
|
||||
span_lint_and_note(
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
FILTER_NEXT,
|
||||
expr.span,
|
||||
msg,
|
||||
None,
|
||||
&format!("replace `filter({0}).next()` with `find({0})`", filter_snippet),
|
||||
"try this",
|
||||
format!("{}.find({})", iter_snippet, filter_snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
span_lint(cx, FILTER_NEXT, expr.span, msg);
|
||||
@ -2823,9 +2846,9 @@ fn lint_skip_while_next<'tcx>(
|
||||
cx,
|
||||
SKIP_WHILE_NEXT,
|
||||
expr.span,
|
||||
"called `skip_while(p).next()` on an `Iterator`",
|
||||
"called `skip_while(<p>).next()` on an `Iterator`",
|
||||
None,
|
||||
"this is more succinctly expressed by calling `.find(!p)` instead",
|
||||
"this is more succinctly expressed by calling `.find(!<p>)` instead",
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -2839,7 +2862,7 @@ fn lint_filter_map<'tcx>(
|
||||
) {
|
||||
// lint if caller of `.filter().map()` is an Iterator
|
||||
if match_trait_method(cx, expr, &paths::ITERATOR) {
|
||||
let msg = "called `filter(p).map(q)` on an `Iterator`";
|
||||
let msg = "called `filter(..).map(..)` on an `Iterator`";
|
||||
let hint = "this is more succinctly expressed by calling `.filter_map(..)` instead";
|
||||
span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint);
|
||||
}
|
||||
@ -2848,17 +2871,19 @@ fn lint_filter_map<'tcx>(
|
||||
/// lint use of `filter_map().next()` for `Iterators`
|
||||
fn lint_filter_map_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, filter_args: &'tcx [hir::Expr<'_>]) {
|
||||
if match_trait_method(cx, expr, &paths::ITERATOR) {
|
||||
let msg = "called `filter_map(p).next()` on an `Iterator`. This is more succinctly expressed by calling \
|
||||
`.find_map(p)` instead.";
|
||||
let msg = "called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling \
|
||||
`.find_map(..)` instead.";
|
||||
let filter_snippet = snippet(cx, filter_args[1].span, "..");
|
||||
if filter_snippet.lines().count() <= 1 {
|
||||
span_lint_and_note(
|
||||
let iter_snippet = snippet(cx, filter_args[0].span, "..");
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
FILTER_MAP_NEXT,
|
||||
expr.span,
|
||||
msg,
|
||||
None,
|
||||
&format!("replace `filter_map({0}).next()` with `find_map({0})`", filter_snippet),
|
||||
"try this",
|
||||
format!("{}.find_map({})", iter_snippet, filter_snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
span_lint(cx, FILTER_MAP_NEXT, expr.span, msg);
|
||||
@ -2875,7 +2900,7 @@ fn lint_find_map<'tcx>(
|
||||
) {
|
||||
// lint if caller of `.filter().map()` is an Iterator
|
||||
if match_trait_method(cx, &map_args[0], &paths::ITERATOR) {
|
||||
let msg = "called `find(p).map(q)` on an `Iterator`";
|
||||
let msg = "called `find(..).map(..)` on an `Iterator`";
|
||||
let hint = "this is more succinctly expressed by calling `.find_map(..)` instead";
|
||||
span_lint_and_help(cx, FIND_MAP, expr.span, msg, None, hint);
|
||||
}
|
||||
@ -2890,7 +2915,7 @@ fn lint_filter_map_map<'tcx>(
|
||||
) {
|
||||
// lint if caller of `.filter().map()` is an Iterator
|
||||
if match_trait_method(cx, expr, &paths::ITERATOR) {
|
||||
let msg = "called `filter_map(p).map(q)` on an `Iterator`";
|
||||
let msg = "called `filter_map(..).map(..)` on an `Iterator`";
|
||||
let hint = "this is more succinctly expressed by only calling `.filter_map(..)` instead";
|
||||
span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint);
|
||||
}
|
||||
@ -2905,7 +2930,7 @@ fn lint_filter_flat_map<'tcx>(
|
||||
) {
|
||||
// lint if caller of `.filter().flat_map()` is an Iterator
|
||||
if match_trait_method(cx, expr, &paths::ITERATOR) {
|
||||
let msg = "called `filter(p).flat_map(q)` on an `Iterator`";
|
||||
let msg = "called `filter(..).flat_map(..)` on an `Iterator`";
|
||||
let hint = "this is more succinctly expressed by calling `.flat_map(..)` \
|
||||
and filtering by returning `iter::empty()`";
|
||||
span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint);
|
||||
@ -2921,7 +2946,7 @@ fn lint_filter_map_flat_map<'tcx>(
|
||||
) {
|
||||
// lint if caller of `.filter_map().flat_map()` is an Iterator
|
||||
if match_trait_method(cx, expr, &paths::ITERATOR) {
|
||||
let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`";
|
||||
let msg = "called `filter_map(..).flat_map(..)` on an `Iterator`";
|
||||
let hint = "this is more succinctly expressed by calling `.flat_map(..)` \
|
||||
and filtering by returning `iter::empty()`";
|
||||
span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint);
|
||||
@ -3092,9 +3117,9 @@ fn lint_chars_cmp(
|
||||
"like this",
|
||||
format!("{}{}.{}({})",
|
||||
if info.eq { "" } else { "!" },
|
||||
snippet_with_applicability(cx, args[0][0].span, "_", &mut applicability),
|
||||
snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
|
||||
suggest,
|
||||
snippet_with_applicability(cx, arg_char[0].span, "_", &mut applicability)),
|
||||
snippet_with_applicability(cx, arg_char[0].span, "..", &mut applicability)),
|
||||
applicability,
|
||||
);
|
||||
|
||||
@ -3141,7 +3166,7 @@ fn lint_chars_cmp_with_unwrap<'tcx>(
|
||||
"like this",
|
||||
format!("{}{}.{}('{}')",
|
||||
if info.eq { "" } else { "!" },
|
||||
snippet_with_applicability(cx, args[0][0].span, "_", &mut applicability),
|
||||
snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
|
||||
suggest,
|
||||
c),
|
||||
applicability,
|
||||
@ -3216,7 +3241,7 @@ fn lint_single_char_pattern(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, arg: &h
|
||||
fn lint_single_char_push_string(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) {
|
||||
let base_string_snippet = snippet_with_applicability(cx, args[0].span, "_", &mut applicability);
|
||||
let base_string_snippet = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
|
||||
let sugg = format!("{}.push({})", base_string_snippet, extension_string);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
@ -3259,7 +3284,7 @@ fn lint_asref(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, as_re
|
||||
expr.span,
|
||||
&format!("this call to `{}` does nothing", call_name),
|
||||
"try this",
|
||||
snippet_with_applicability(cx, recvr.span, "_", &mut applicability).to_string(),
|
||||
snippet_with_applicability(cx, recvr.span, "..", &mut applicability).to_string(),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
@ -3445,6 +3470,42 @@ fn lint_option_as_ref_deref<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_map_collect(
|
||||
cx: &LateContext<'_>,
|
||||
expr: &hir::Expr<'_>,
|
||||
map_args: &[hir::Expr<'_>],
|
||||
collect_args: &[hir::Expr<'_>],
|
||||
) {
|
||||
if_chain! {
|
||||
// called on Iterator
|
||||
if let [map_expr] = collect_args;
|
||||
if match_trait_method(cx, map_expr, &paths::ITERATOR);
|
||||
// return of collect `Result<(),_>`
|
||||
let collect_ret_ty = cx.typeck_results().expr_ty(expr);
|
||||
if is_type_diagnostic_item(cx, collect_ret_ty, sym!(result_type));
|
||||
if let ty::Adt(_, substs) = collect_ret_ty.kind();
|
||||
if let Some(result_t) = substs.types().next();
|
||||
if result_t.is_unit();
|
||||
// get parts for snippet
|
||||
if let [iter, map_fn] = map_args;
|
||||
then {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MAP_COLLECT_RESULT_UNIT,
|
||||
expr.span,
|
||||
"`.map().collect()` can be replaced with `.try_for_each()`",
|
||||
"try this",
|
||||
format!(
|
||||
"{}.try_for_each({})",
|
||||
snippet(cx, iter.span, ".."),
|
||||
snippet(cx, map_fn.span, "..")
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a `Result<T, E>` type, return its error type (`E`).
|
||||
fn get_error_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option<Ty<'a>> {
|
||||
match ty.kind() {
|
||||
|
@ -53,15 +53,15 @@ pub(super) fn lint<'tcx>(
|
||||
// lint message
|
||||
// comparing the snippet from source to raw text ("None") below is safe
|
||||
// because we already have checked the type.
|
||||
let arg = if unwrap_snippet == "None" { "None" } else { "a" };
|
||||
let arg = if unwrap_snippet == "None" { "None" } else { "<a>" };
|
||||
let unwrap_snippet_none = unwrap_snippet == "None";
|
||||
let suggest = if unwrap_snippet_none {
|
||||
"and_then(f)"
|
||||
"and_then(<f>)"
|
||||
} else {
|
||||
"map_or(a, f)"
|
||||
"map_or(<a>, <f>)"
|
||||
};
|
||||
let msg = &format!(
|
||||
"called `map(f).unwrap_or({})` on an `Option` value. \
|
||||
"called `map(<f>).unwrap_or({})` on an `Option` value. \
|
||||
This can be done more directly by calling `{}` instead",
|
||||
arg, suggest
|
||||
);
|
||||
|
@ -7,6 +7,7 @@ use rustc_hir::{
|
||||
StmtKind, TyKind, UnOp,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
@ -271,13 +272,16 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
|
||||
k: FnKind<'tcx>,
|
||||
decl: &'tcx FnDecl<'_>,
|
||||
body: &'tcx Body<'_>,
|
||||
_: Span,
|
||||
span: Span,
|
||||
_: HirId,
|
||||
) {
|
||||
if let FnKind::Closure(_) = k {
|
||||
// Does not apply to closures
|
||||
return;
|
||||
}
|
||||
if in_external_macro(cx.tcx.sess, span) {
|
||||
return;
|
||||
}
|
||||
for arg in iter_input_pats(decl, body) {
|
||||
if let PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..) = arg.pat.kind {
|
||||
span_lint(
|
||||
@ -293,13 +297,16 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
|
||||
|
||||
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
|
||||
if_chain! {
|
||||
if !in_external_macro(cx.tcx.sess, stmt.span);
|
||||
if let StmtKind::Local(ref local) = stmt.kind;
|
||||
if let PatKind::Binding(an, .., name, None) = local.pat.kind;
|
||||
if let Some(ref init) = local.init;
|
||||
if !higher::is_from_for_desugar(local);
|
||||
then {
|
||||
if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut {
|
||||
let sugg_init = if init.span.from_expansion() {
|
||||
// use the macro callsite when the init span (but not the whole local span)
|
||||
// comes from an expansion like `vec![1, 2, 3]` in `let ref _ = vec![1, 2, 3];`
|
||||
let sugg_init = if init.span.from_expansion() && !local.span.from_expansion() {
|
||||
Sugg::hir_with_macro_callsite(cx, init, "..")
|
||||
} else {
|
||||
Sugg::hir(cx, init, "..")
|
||||
@ -310,7 +317,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
|
||||
("", sugg_init.addr())
|
||||
};
|
||||
let tyopt = if let Some(ref ty) = local.ty {
|
||||
format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, "_"))
|
||||
format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, ".."))
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
@ -326,7 +333,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
|
||||
"try",
|
||||
format!(
|
||||
"let {name}{tyopt} = {initref};",
|
||||
name=snippet(cx, name.span, "_"),
|
||||
name=snippet(cx, name.span, ".."),
|
||||
tyopt=tyopt,
|
||||
initref=initref,
|
||||
),
|
||||
|
@ -10,9 +10,9 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::{
|
||||
BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericParamKind, HirId, ImplItem,
|
||||
ImplItemKind, Item, ItemKind, Lifetime, Lit, Local, MatchSource, MutTy, Mutability, Node, QPath, Stmt, StmtKind,
|
||||
TraitFn, TraitItem, TraitItemKind, TyKind, UnOp,
|
||||
BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericBounds, GenericParamKind, HirId,
|
||||
ImplItem, ImplItemKind, Item, ItemKind, Lifetime, Lit, Local, MatchSource, MutTy, Mutability, Node, QPath, Stmt,
|
||||
StmtKind, SyntheticTyParamKind, TraitFn, TraitItem, TraitItemKind, TyKind, UnOp,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::hir::map::Map;
|
||||
@ -678,17 +678,30 @@ impl Types {
|
||||
// details.
|
||||
return;
|
||||
}
|
||||
|
||||
// When trait objects or opaque types have lifetime or auto-trait bounds,
|
||||
// we need to add parentheses to avoid a syntax error due to its ambiguity.
|
||||
// Originally reported as the issue #3128.
|
||||
let inner_snippet = snippet(cx, inner.span, "..");
|
||||
let suggestion = match &inner.kind {
|
||||
TyKind::TraitObject(bounds, lt_bound) if bounds.len() > 1 || !lt_bound.is_elided() => {
|
||||
format!("&{}({})", ltopt, &inner_snippet)
|
||||
},
|
||||
TyKind::Path(qpath)
|
||||
if get_bounds_if_impl_trait(cx, qpath, inner.hir_id)
|
||||
.map_or(false, |bounds| bounds.len() > 1) =>
|
||||
{
|
||||
format!("&{}({})", ltopt, &inner_snippet)
|
||||
},
|
||||
_ => format!("&{}{}", ltopt, &inner_snippet),
|
||||
};
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
BORROWED_BOX,
|
||||
hir_ty.span,
|
||||
"you seem to be trying to use `&Box<T>`. Consider using just `&T`",
|
||||
"try",
|
||||
format!(
|
||||
"&{}{}",
|
||||
ltopt,
|
||||
&snippet(cx, inner.span, "..")
|
||||
),
|
||||
suggestion,
|
||||
// To make this `MachineApplicable`, at least one needs to check if it isn't a trait item
|
||||
// because the trait impls of it will break otherwise;
|
||||
// and there may be other cases that result in invalid code.
|
||||
@ -721,6 +734,21 @@ fn is_any_trait(t: &hir::Ty<'_>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: HirId) -> Option<GenericBounds<'tcx>> {
|
||||
if_chain! {
|
||||
if let Some(did) = qpath_res(cx, qpath, id).opt_def_id();
|
||||
if let Some(node) = cx.tcx.hir().get_if_local(did);
|
||||
if let Node::GenericParam(generic_param) = node;
|
||||
if let GenericParamKind::Type { synthetic, .. } = generic_param.kind;
|
||||
if synthetic == Some(SyntheticTyParamKind::ImplTrait);
|
||||
then {
|
||||
Some(generic_param.bounds)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for binding a unit value.
|
||||
///
|
||||
|
@ -298,6 +298,13 @@ vec![
|
||||
deprecation: None,
|
||||
module: "comparison_chain",
|
||||
},
|
||||
Lint {
|
||||
name: "comparison_to_empty",
|
||||
group: "style",
|
||||
desc: "checking `x == \"\"` or `x == []` (or similar) when `.is_empty()` could be used instead",
|
||||
deprecation: None,
|
||||
module: "len_zero",
|
||||
},
|
||||
Lint {
|
||||
name: "copy_iterator",
|
||||
group: "pedantic",
|
||||
@ -1222,6 +1229,13 @@ vec![
|
||||
deprecation: None,
|
||||
module: "map_clone",
|
||||
},
|
||||
Lint {
|
||||
name: "map_collect_result_unit",
|
||||
group: "style",
|
||||
desc: "using `.map(_).collect::<Result<(),_>()`, which can be replaced with `try_for_each`",
|
||||
deprecation: None,
|
||||
module: "methods",
|
||||
},
|
||||
Lint {
|
||||
name: "map_entry",
|
||||
group: "perf",
|
||||
|
@ -56,3 +56,17 @@ macro_rules! option_env_unwrap_external {
|
||||
option_env!($env).expect($message)
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! ref_arg_binding {
|
||||
() => {
|
||||
let ref _y = 42;
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! ref_arg_function {
|
||||
() => {
|
||||
fn fun_example(ref _x: usize) {}
|
||||
};
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
#![allow(unused_variables)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
pub fn test1(foo: &mut Box<bool>) {
|
||||
// Although this function could be changed to "&mut bool",
|
||||
// avoiding the Box, mutable references to boxes are not
|
||||
@ -89,6 +91,20 @@ pub fn test13(boxed_slice: &mut Box<[i32]>) {
|
||||
*boxed_slice = data.into_boxed_slice();
|
||||
}
|
||||
|
||||
// The suggestion should include proper parentheses to avoid a syntax error.
|
||||
pub fn test14(_display: &Box<dyn Display>) {}
|
||||
pub fn test15(_display: &Box<dyn Display + Send>) {}
|
||||
pub fn test16<'a>(_display: &'a Box<dyn Display + 'a>) {}
|
||||
|
||||
pub fn test17(_display: &Box<impl Display>) {}
|
||||
pub fn test18(_display: &Box<impl Display + Send>) {}
|
||||
pub fn test19<'a>(_display: &'a Box<impl Display + 'a>) {}
|
||||
|
||||
// This exists only to check what happens when parentheses are already present.
|
||||
// Even though the current implementation doesn't put extra parentheses,
|
||||
// it's fine that unnecessary parentheses appear in the future for some reason.
|
||||
pub fn test20(_display: &Box<(dyn Display + Send)>) {}
|
||||
|
||||
fn main() {
|
||||
test1(&mut Box::new(false));
|
||||
test2();
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
|
||||
--> $DIR/borrow_box.rs:19:14
|
||||
--> $DIR/borrow_box.rs:21:14
|
||||
|
|
||||
LL | let foo: &Box<bool>;
|
||||
| ^^^^^^^^^^ help: try: `&bool`
|
||||
@ -11,16 +11,58 @@ LL | #![deny(clippy::borrowed_box)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
|
||||
--> $DIR/borrow_box.rs:23:10
|
||||
--> $DIR/borrow_box.rs:25:10
|
||||
|
|
||||
LL | foo: &'a Box<bool>,
|
||||
| ^^^^^^^^^^^^^ help: try: `&'a bool`
|
||||
|
||||
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
|
||||
--> $DIR/borrow_box.rs:27:17
|
||||
--> $DIR/borrow_box.rs:29:17
|
||||
|
|
||||
LL | fn test4(a: &Box<bool>);
|
||||
| ^^^^^^^^^^ help: try: `&bool`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
|
||||
--> $DIR/borrow_box.rs:95:25
|
||||
|
|
||||
LL | pub fn test14(_display: &Box<dyn Display>) {}
|
||||
| ^^^^^^^^^^^^^^^^^ help: try: `&dyn Display`
|
||||
|
||||
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
|
||||
--> $DIR/borrow_box.rs:96:25
|
||||
|
|
||||
LL | pub fn test15(_display: &Box<dyn Display + Send>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)`
|
||||
|
||||
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
|
||||
--> $DIR/borrow_box.rs:97:29
|
||||
|
|
||||
LL | pub fn test16<'a>(_display: &'a Box<dyn Display + 'a>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (dyn Display + 'a)`
|
||||
|
||||
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
|
||||
--> $DIR/borrow_box.rs:99:25
|
||||
|
|
||||
LL | pub fn test17(_display: &Box<impl Display>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^ help: try: `&impl Display`
|
||||
|
||||
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
|
||||
--> $DIR/borrow_box.rs:100:25
|
||||
|
|
||||
LL | pub fn test18(_display: &Box<impl Display + Send>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(impl Display + Send)`
|
||||
|
||||
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
|
||||
--> $DIR/borrow_box.rs:101:29
|
||||
|
|
||||
LL | pub fn test19<'a>(_display: &'a Box<impl Display + 'a>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (impl Display + 'a)`
|
||||
|
||||
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
|
||||
--> $DIR/borrow_box.rs:106:25
|
||||
|
|
||||
LL | pub fn test20(_display: &Box<(dyn Display + Send)>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
23
tests/ui/comparison_to_empty.fixed
Normal file
23
tests/ui/comparison_to_empty.fixed
Normal file
@ -0,0 +1,23 @@
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::comparison_to_empty)]
|
||||
|
||||
fn main() {
|
||||
// Disallow comparisons to empty
|
||||
let s = String::new();
|
||||
let _ = s.is_empty();
|
||||
let _ = !s.is_empty();
|
||||
|
||||
let v = vec![0];
|
||||
let _ = v.is_empty();
|
||||
let _ = !v.is_empty();
|
||||
|
||||
// Allow comparisons to non-empty
|
||||
let s = String::new();
|
||||
let _ = s == " ";
|
||||
let _ = s != " ";
|
||||
|
||||
let v = vec![0];
|
||||
let _ = v == [0];
|
||||
let _ = v != [0];
|
||||
}
|
23
tests/ui/comparison_to_empty.rs
Normal file
23
tests/ui/comparison_to_empty.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::comparison_to_empty)]
|
||||
|
||||
fn main() {
|
||||
// Disallow comparisons to empty
|
||||
let s = String::new();
|
||||
let _ = s == "";
|
||||
let _ = s != "";
|
||||
|
||||
let v = vec![0];
|
||||
let _ = v == [];
|
||||
let _ = v != [];
|
||||
|
||||
// Allow comparisons to non-empty
|
||||
let s = String::new();
|
||||
let _ = s == " ";
|
||||
let _ = s != " ";
|
||||
|
||||
let v = vec![0];
|
||||
let _ = v == [0];
|
||||
let _ = v != [0];
|
||||
}
|
28
tests/ui/comparison_to_empty.stderr
Normal file
28
tests/ui/comparison_to_empty.stderr
Normal file
@ -0,0 +1,28 @@
|
||||
error: comparison to empty slice
|
||||
--> $DIR/comparison_to_empty.rs:8:13
|
||||
|
|
||||
LL | let _ = s == "";
|
||||
| ^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
|
||||
|
|
||||
= note: `-D clippy::comparison-to-empty` implied by `-D warnings`
|
||||
|
||||
error: comparison to empty slice
|
||||
--> $DIR/comparison_to_empty.rs:9:13
|
||||
|
|
||||
LL | let _ = s != "";
|
||||
| ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!s.is_empty()`
|
||||
|
||||
error: comparison to empty slice
|
||||
--> $DIR/comparison_to_empty.rs:12:13
|
||||
|
|
||||
LL | let _ = v == [];
|
||||
| ^^^^^^^ help: using `is_empty` is clearer and more explicit: `v.is_empty()`
|
||||
|
||||
error: comparison to empty slice
|
||||
--> $DIR/comparison_to_empty.rs:13:13
|
||||
|
|
||||
LL | let _ = v != [];
|
||||
| ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!v.is_empty()`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
16
tests/ui/crashes/ice-6250.rs
Normal file
16
tests/ui/crashes/ice-6250.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// originally from glacier/fixed/77218.rs
|
||||
// ice while adjusting...
|
||||
|
||||
pub struct Cache {
|
||||
data: Vec<i32>,
|
||||
}
|
||||
|
||||
pub fn list_data(cache: &Cache, key: usize) {
|
||||
for reference in vec![1, 2, 3] {
|
||||
if
|
||||
/* let */
|
||||
Some(reference) = cache.data.get(key) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
27
tests/ui/crashes/ice-6250.stderr
Normal file
27
tests/ui/crashes/ice-6250.stderr
Normal file
@ -0,0 +1,27 @@
|
||||
error[E0601]: `main` function not found in crate `ice_6250`
|
||||
--> $DIR/ice-6250.rs:4:1
|
||||
|
|
||||
LL | / pub struct Cache {
|
||||
LL | | data: Vec<i32>,
|
||||
LL | | }
|
||||
LL | |
|
||||
... |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_^ consider adding a `main` function to `$DIR/ice-6250.rs`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ice-6250.rs:12:9
|
||||
|
|
||||
LL | Some(reference) = cache.data.get(key) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
|
||||
|
|
||||
help: you might have meant to use pattern matching
|
||||
|
|
||||
LL | let Some(reference) = cache.data.get(key) {
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0601.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
6
tests/ui/crashes/ice-6251.rs
Normal file
6
tests/ui/crashes/ice-6251.rs
Normal file
@ -0,0 +1,6 @@
|
||||
// originally from glacier/fixed/77329.rs
|
||||
// assertion failed: `(left == right) ; different DefIds
|
||||
|
||||
fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
|
||||
std::iter::empty()
|
||||
}
|
43
tests/ui/crashes/ice-6251.stderr
Normal file
43
tests/ui/crashes/ice-6251.stderr
Normal file
@ -0,0 +1,43 @@
|
||||
error[E0601]: `main` function not found in crate `ice_6251`
|
||||
--> $DIR/ice-6251.rs:4:1
|
||||
|
|
||||
LL | / fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
|
||||
LL | | std::iter::empty()
|
||||
LL | | }
|
||||
| |_^ consider adding a `main` function to `$DIR/ice-6251.rs`
|
||||
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/ice-6251.rs:4:45
|
||||
|
|
||||
LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | fn bug<T>() -> impl Iterator<Item = [(); { |&x: [u8]| x }]> {
|
||||
| ^
|
||||
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/ice-6251.rs:4:54
|
||||
|
|
||||
LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ice-6251.rs:4:44
|
||||
|
|
||||
LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
|
||||
| ^^^^^^^^^^^ expected `usize`, found closure
|
||||
|
|
||||
= note: expected type `usize`
|
||||
found closure `[closure@$DIR/ice-6251.rs:4:44: 4:55]`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308, E0601.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
15
tests/ui/crashes/ice-6252.rs
Normal file
15
tests/ui/crashes/ice-6252.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// originally from glacier fixed/77919.rs
|
||||
// encountered errors resolving bounds after type-checking
|
||||
|
||||
trait TypeVal<T> {
|
||||
const VAL: T;
|
||||
}
|
||||
struct Five;
|
||||
struct Multiply<N, M> {
|
||||
_n: PhantomData,
|
||||
}
|
||||
impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
|
||||
|
||||
fn main() {
|
||||
[1; <Multiply<Five, Five>>::VAL];
|
||||
}
|
46
tests/ui/crashes/ice-6252.stderr
Normal file
46
tests/ui/crashes/ice-6252.stderr
Normal file
@ -0,0 +1,46 @@
|
||||
error[E0412]: cannot find type `PhantomData` in this scope
|
||||
--> $DIR/ice-6252.rs:9:9
|
||||
|
|
||||
LL | _n: PhantomData,
|
||||
| ^^^^^^^^^^^ not found in this scope
|
||||
|
|
||||
help: consider importing this struct
|
||||
|
|
||||
LL | use std::marker::PhantomData;
|
||||
|
|
||||
|
||||
error[E0412]: cannot find type `VAL` in this scope
|
||||
--> $DIR/ice-6252.rs:11:63
|
||||
|
|
||||
LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
|
||||
| - ^^^ not found in this scope
|
||||
| |
|
||||
| help: you might be missing a type parameter: `, VAL`
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `VAL`
|
||||
--> $DIR/ice-6252.rs:11:1
|
||||
|
|
||||
LL | const VAL: T;
|
||||
| ------------- `VAL` from trait
|
||||
...
|
||||
LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation
|
||||
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/ice-6252.rs:5:5
|
||||
|
|
||||
LL | const VAL: T;
|
||||
| ^^^^^^^^^^^^^ no MIR body is available for DefId(0:5 ~ ice_6252[317d]::TypeVal::VAL)
|
||||
|
|
||||
= note: `#[deny(const_err)]` on by default
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ice-6252.rs:14:9
|
||||
|
|
||||
LL | [1; <Multiply<Five, Five>>::VAL];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0046, E0080, E0412.
|
||||
For more information about an error, try `rustc --explain E0046`.
|
15
tests/ui/crashes/ice-6254.rs
Normal file
15
tests/ui/crashes/ice-6254.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// originally from ./src/test/ui/pattern/usefulness/consts-opaque.rs
|
||||
// panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())',
|
||||
// compiler/rustc_mir_build/src/thir/pattern/_match.rs:2030:5
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct Foo(i32);
|
||||
const FOO_REF_REF: &&Foo = &&Foo(42);
|
||||
|
||||
fn main() {
|
||||
// This used to cause an ICE (https://github.com/rust-lang/rust/issues/78071)
|
||||
match FOO_REF_REF {
|
||||
FOO_REF_REF => {},
|
||||
Foo(_) => {},
|
||||
}
|
||||
}
|
12
tests/ui/crashes/ice-6254.stderr
Normal file
12
tests/ui/crashes/ice-6254.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/ice-6254.rs:12:9
|
||||
|
|
||||
LL | FOO_REF_REF => {},
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D indirect-structural-match` implied by `-D warnings`
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
15
tests/ui/crashes/ice-6255.rs
Normal file
15
tests/ui/crashes/ice-6255.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// originally from rustc ./src/test/ui/macros/issue-78325-inconsistent-resolution.rs
|
||||
// inconsistent resolution for a macro
|
||||
|
||||
macro_rules! define_other_core {
|
||||
( ) => {
|
||||
extern crate std as core;
|
||||
//~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern`
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
core::panic!();
|
||||
}
|
||||
|
||||
define_other_core!();
|
13
tests/ui/crashes/ice-6255.stderr
Normal file
13
tests/ui/crashes/ice-6255.stderr
Normal file
@ -0,0 +1,13 @@
|
||||
error: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
|
||||
--> $DIR/ice-6255.rs:6:9
|
||||
|
|
||||
LL | extern crate std as core;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | define_other_core!();
|
||||
| --------------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
13
tests/ui/crashes/ice-6256.rs
Normal file
13
tests/ui/crashes/ice-6256.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// originally from rustc ./src/test/ui/regions/issue-78262.rs
|
||||
// ICE: to get the signature of a closure, use substs.as_closure().sig() not fn_sig()
|
||||
|
||||
trait TT {}
|
||||
|
||||
impl dyn TT {
|
||||
fn func(&self) {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
|
||||
//[nll]~^ ERROR: borrowed data escapes outside of closure
|
||||
}
|
18
tests/ui/crashes/ice-6256.stderr
Normal file
18
tests/ui/crashes/ice-6256.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ice-6256.rs:11:28
|
||||
|
|
||||
LL | let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
|
||||
| ^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected reference `&(dyn TT + 'static)`
|
||||
found reference `&dyn TT`
|
||||
note: the anonymous lifetime #1 defined on the body at 11:13...
|
||||
--> $DIR/ice-6256.rs:11:13
|
||||
|
|
||||
LL | let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...does not necessarily outlive the static lifetime
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -3,9 +3,6 @@
|
||||
fn main() {
|
||||
let a = ["1", "lol", "3", "NaN", "5"];
|
||||
|
||||
let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
|
||||
assert_eq!(element, Some(1));
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _: Option<u32> = vec![1, 2, 3, 4, 5, 6]
|
||||
.into_iter()
|
||||
|
@ -1,14 +1,5 @@
|
||||
error: called `filter_map(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(p)` instead.
|
||||
--> $DIR/filter_map_next.rs:6:32
|
||||
|
|
||||
LL | let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::filter-map-next` implied by `-D warnings`
|
||||
= note: replace `filter_map(|s| s.parse().ok()).next()` with `find_map(|s| s.parse().ok())`
|
||||
|
||||
error: called `filter_map(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(p)` instead.
|
||||
--> $DIR/filter_map_next.rs:10:26
|
||||
error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead.
|
||||
--> $DIR/filter_map_next.rs:7:26
|
||||
|
|
||||
LL | let _: Option<u32> = vec![1, 2, 3, 4, 5, 6]
|
||||
| __________________________^
|
||||
@ -19,6 +10,8 @@ LL | | if x == 2 {
|
||||
LL | | })
|
||||
LL | | .next();
|
||||
| |_______________^
|
||||
|
|
||||
= note: `-D clippy::filter-map-next` implied by `-D warnings`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
10
tests/ui/filter_map_next_fixable.fixed
Normal file
10
tests/ui/filter_map_next_fixable.fixed
Normal file
@ -0,0 +1,10 @@
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::all, clippy::pedantic)]
|
||||
|
||||
fn main() {
|
||||
let a = ["1", "lol", "3", "NaN", "5"];
|
||||
|
||||
let element: Option<i32> = a.iter().find_map(|s| s.parse().ok());
|
||||
assert_eq!(element, Some(1));
|
||||
}
|
10
tests/ui/filter_map_next_fixable.rs
Normal file
10
tests/ui/filter_map_next_fixable.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::all, clippy::pedantic)]
|
||||
|
||||
fn main() {
|
||||
let a = ["1", "lol", "3", "NaN", "5"];
|
||||
|
||||
let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
|
||||
assert_eq!(element, Some(1));
|
||||
}
|
10
tests/ui/filter_map_next_fixable.stderr
Normal file
10
tests/ui/filter_map_next_fixable.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead.
|
||||
--> $DIR/filter_map_next_fixable.rs:8:32
|
||||
|
|
||||
LL | let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `a.iter().find_map(|s| s.parse().ok())`
|
||||
|
|
||||
= note: `-D clippy::filter-map-next` implied by `-D warnings`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: called `filter(p).map(q)` on an `Iterator`
|
||||
error: called `filter(..).map(..)` on an `Iterator`
|
||||
--> $DIR/filter_methods.rs:5:21
|
||||
|
|
||||
LL | let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x * 2).collect();
|
||||
@ -7,7 +7,7 @@ LL | let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x *
|
||||
= note: `-D clippy::filter-map` implied by `-D warnings`
|
||||
= help: this is more succinctly expressed by calling `.filter_map(..)` instead
|
||||
|
||||
error: called `filter(p).flat_map(q)` on an `Iterator`
|
||||
error: called `filter(..).flat_map(..)` on an `Iterator`
|
||||
--> $DIR/filter_methods.rs:7:21
|
||||
|
|
||||
LL | let _: Vec<_> = vec![5_i8; 6]
|
||||
@ -19,7 +19,7 @@ LL | | .flat_map(|x| x.checked_mul(2))
|
||||
|
|
||||
= help: this is more succinctly expressed by calling `.flat_map(..)` and filtering by returning `iter::empty()`
|
||||
|
||||
error: called `filter_map(p).flat_map(q)` on an `Iterator`
|
||||
error: called `filter_map(..).flat_map(..)` on an `Iterator`
|
||||
--> $DIR/filter_methods.rs:13:21
|
||||
|
|
||||
LL | let _: Vec<_> = vec![5_i8; 6]
|
||||
@ -31,7 +31,7 @@ LL | | .flat_map(|x| x.checked_mul(2))
|
||||
|
|
||||
= help: this is more succinctly expressed by calling `.flat_map(..)` and filtering by returning `iter::empty()`
|
||||
|
||||
error: called `filter_map(p).map(q)` on an `Iterator`
|
||||
error: called `filter_map(..).map(..)` on an `Iterator`
|
||||
--> $DIR/filter_methods.rs:19:21
|
||||
|
|
||||
LL | let _: Vec<_> = vec![5_i8; 6]
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: called `find(p).map(q)` on an `Iterator`
|
||||
error: called `find(..).map(..)` on an `Iterator`
|
||||
--> $DIR/find_map.rs:20:26
|
||||
|
|
||||
LL | let _: Option<i32> = a.iter().find(|s| s.parse::<i32>().is_ok()).map(|s| s.parse().unwrap());
|
||||
@ -7,7 +7,7 @@ LL | let _: Option<i32> = a.iter().find(|s| s.parse::<i32>().is_ok()).map(|s
|
||||
= note: `-D clippy::find-map` implied by `-D warnings`
|
||||
= help: this is more succinctly expressed by calling `.find_map(..)` instead
|
||||
|
||||
error: called `find(p).map(q)` on an `Iterator`
|
||||
error: called `find(..).map(..)` on an `Iterator`
|
||||
--> $DIR/find_map.rs:23:29
|
||||
|
|
||||
LL | let _: Option<Flavor> = desserts_of_the_week
|
||||
|
@ -11,6 +11,8 @@
|
||||
#[rustfmt::skip]
|
||||
fn main() {
|
||||
let mut i = 1i32;
|
||||
let mut var1 = 0i32;
|
||||
let mut var2 = -1i32;
|
||||
1 + i;
|
||||
i * 2;
|
||||
1 %
|
||||
@ -32,7 +34,15 @@ fn main() {
|
||||
i -= 1;
|
||||
i *= 2;
|
||||
i /= 2;
|
||||
i /= 0;
|
||||
i /= -1;
|
||||
i /= var1;
|
||||
i /= var2;
|
||||
i %= 2;
|
||||
i %= 0;
|
||||
i %= -1;
|
||||
i %= var1;
|
||||
i %= var2;
|
||||
i <<= 3;
|
||||
i >>= 2;
|
||||
|
||||
|
@ -1,5 +1,19 @@
|
||||
error: this operation will panic at runtime
|
||||
--> $DIR/integer_arithmetic.rs:37:5
|
||||
|
|
||||
LL | i /= 0;
|
||||
| ^^^^^^ attempt to divide `_` by zero
|
||||
|
|
||||
= note: `#[deny(unconditional_panic)]` on by default
|
||||
|
||||
error: this operation will panic at runtime
|
||||
--> $DIR/integer_arithmetic.rs:42:5
|
||||
|
|
||||
LL | i %= 0;
|
||||
| ^^^^^^ attempt to calculate the remainder of `_` with a divisor of zero
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:14:5
|
||||
--> $DIR/integer_arithmetic.rs:16:5
|
||||
|
|
||||
LL | 1 + i;
|
||||
| ^^^^^
|
||||
@ -7,125 +21,149 @@ LL | 1 + i;
|
||||
= note: `-D clippy::integer-arithmetic` implied by `-D warnings`
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:15:5
|
||||
--> $DIR/integer_arithmetic.rs:17:5
|
||||
|
|
||||
LL | i * 2;
|
||||
| ^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:16:5
|
||||
--> $DIR/integer_arithmetic.rs:18:5
|
||||
|
|
||||
LL | / 1 %
|
||||
LL | | i / 2; // no error, this is part of the expression in the preceding line
|
||||
| |_________^
|
||||
| |_____^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:18:5
|
||||
--> $DIR/integer_arithmetic.rs:20:5
|
||||
|
|
||||
LL | i - 2 + 2 - i;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:19:5
|
||||
--> $DIR/integer_arithmetic.rs:21:5
|
||||
|
|
||||
LL | -i;
|
||||
| ^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:20:5
|
||||
--> $DIR/integer_arithmetic.rs:22:5
|
||||
|
|
||||
LL | i >> 1;
|
||||
| ^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:21:5
|
||||
--> $DIR/integer_arithmetic.rs:23:5
|
||||
|
|
||||
LL | i << 1;
|
||||
| ^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:31:5
|
||||
--> $DIR/integer_arithmetic.rs:33:5
|
||||
|
|
||||
LL | i += 1;
|
||||
| ^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:32:5
|
||||
--> $DIR/integer_arithmetic.rs:34:5
|
||||
|
|
||||
LL | i -= 1;
|
||||
| ^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:33:5
|
||||
--> $DIR/integer_arithmetic.rs:35:5
|
||||
|
|
||||
LL | i *= 2;
|
||||
| ^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:34:5
|
||||
--> $DIR/integer_arithmetic.rs:38:11
|
||||
|
|
||||
LL | i /= 2;
|
||||
| ^^^^^^
|
||||
LL | i /= -1;
|
||||
| ^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:35:5
|
||||
--> $DIR/integer_arithmetic.rs:39:5
|
||||
|
|
||||
LL | i %= 2;
|
||||
| ^^^^^^
|
||||
LL | i /= var1;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:36:5
|
||||
--> $DIR/integer_arithmetic.rs:40:5
|
||||
|
|
||||
LL | i /= var2;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:43:11
|
||||
|
|
||||
LL | i %= -1;
|
||||
| ^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:44:5
|
||||
|
|
||||
LL | i %= var1;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:45:5
|
||||
|
|
||||
LL | i %= var2;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:46:5
|
||||
|
|
||||
LL | i <<= 3;
|
||||
| ^^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:37:5
|
||||
--> $DIR/integer_arithmetic.rs:47:5
|
||||
|
|
||||
LL | i >>= 2;
|
||||
| ^^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:79:5
|
||||
--> $DIR/integer_arithmetic.rs:89:5
|
||||
|
|
||||
LL | 3 + &1;
|
||||
| ^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:80:5
|
||||
--> $DIR/integer_arithmetic.rs:90:5
|
||||
|
|
||||
LL | &3 + 1;
|
||||
| ^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:81:5
|
||||
--> $DIR/integer_arithmetic.rs:91:5
|
||||
|
|
||||
LL | &3 + &1;
|
||||
| ^^^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:86:5
|
||||
--> $DIR/integer_arithmetic.rs:96:5
|
||||
|
|
||||
LL | a + x
|
||||
| ^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:90:5
|
||||
--> $DIR/integer_arithmetic.rs:100:5
|
||||
|
|
||||
LL | x + y
|
||||
| ^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:94:5
|
||||
--> $DIR/integer_arithmetic.rs:104:5
|
||||
|
|
||||
LL | x + y
|
||||
| ^^^^^
|
||||
|
||||
error: integer arithmetic detected
|
||||
--> $DIR/integer_arithmetic.rs:98:5
|
||||
--> $DIR/integer_arithmetic.rs:108:5
|
||||
|
|
||||
LL | (&x + &y)
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to 21 previous errors
|
||||
error: aborting due to 27 previous errors
|
||||
|
||||
|
@ -28,7 +28,10 @@ fn mac() {
|
||||
// do not lint this, because it needs to be after `a`
|
||||
macro_rules! b {
|
||||
() => {{
|
||||
a = 6
|
||||
a = 6;
|
||||
fn say_something() {
|
||||
println!("something");
|
||||
}
|
||||
}};
|
||||
}
|
||||
b!();
|
||||
|
@ -16,5 +16,18 @@ LL | | println!("foo");
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: adding items after statements is confusing, since items exist from the start of the scope
|
||||
--> $DIR/item_after_statement.rs:32:13
|
||||
|
|
||||
LL | / fn say_something() {
|
||||
LL | | println!("something");
|
||||
LL | | }
|
||||
| |_____________^
|
||||
...
|
||||
LL | b!();
|
||||
| ----- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: called `skip(x).next()` on an iterator
|
||||
error: called `skip(..).next()` on an iterator
|
||||
--> $DIR/iter_skip_next.rs:15:28
|
||||
|
|
||||
LL | let _ = some_vec.iter().skip(42).next();
|
||||
@ -6,19 +6,19 @@ LL | let _ = some_vec.iter().skip(42).next();
|
||||
|
|
||||
= note: `-D clippy::iter-skip-next` implied by `-D warnings`
|
||||
|
||||
error: called `skip(x).next()` on an iterator
|
||||
error: called `skip(..).next()` on an iterator
|
||||
--> $DIR/iter_skip_next.rs:16:36
|
||||
|
|
||||
LL | let _ = some_vec.iter().cycle().skip(42).next();
|
||||
| ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)`
|
||||
|
||||
error: called `skip(x).next()` on an iterator
|
||||
error: called `skip(..).next()` on an iterator
|
||||
--> $DIR/iter_skip_next.rs:17:20
|
||||
|
|
||||
LL | let _ = (1..10).skip(10).next();
|
||||
| ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(10)`
|
||||
|
||||
error: called `skip(x).next()` on an iterator
|
||||
error: called `skip(..).next()` on an iterator
|
||||
--> $DIR/iter_skip_next.rs:18:33
|
||||
|
|
||||
LL | let _ = &some_vec[..].iter().skip(3).next();
|
||||
|
16
tests/ui/map_collect_result_unit.fixed
Normal file
16
tests/ui/map_collect_result_unit.fixed
Normal file
@ -0,0 +1,16 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::map_collect_result_unit)]
|
||||
|
||||
fn main() {
|
||||
{
|
||||
let _ = (0..3).try_for_each(|t| Err(t + 1));
|
||||
let _: Result<(), _> = (0..3).try_for_each(|t| Err(t + 1));
|
||||
|
||||
let _ = (0..3).try_for_each(|t| Err(t + 1));
|
||||
}
|
||||
}
|
||||
|
||||
fn _ignore() {
|
||||
let _ = (0..3).map(|t| Err(t + 1)).collect::<Result<Vec<i32>, _>>();
|
||||
let _ = (0..3).map(|t| Err(t + 1)).collect::<Vec<Result<(), _>>>();
|
||||
}
|
16
tests/ui/map_collect_result_unit.rs
Normal file
16
tests/ui/map_collect_result_unit.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::map_collect_result_unit)]
|
||||
|
||||
fn main() {
|
||||
{
|
||||
let _ = (0..3).map(|t| Err(t + 1)).collect::<Result<(), _>>();
|
||||
let _: Result<(), _> = (0..3).map(|t| Err(t + 1)).collect();
|
||||
|
||||
let _ = (0..3).try_for_each(|t| Err(t + 1));
|
||||
}
|
||||
}
|
||||
|
||||
fn _ignore() {
|
||||
let _ = (0..3).map(|t| Err(t + 1)).collect::<Result<Vec<i32>, _>>();
|
||||
let _ = (0..3).map(|t| Err(t + 1)).collect::<Vec<Result<(), _>>>();
|
||||
}
|
16
tests/ui/map_collect_result_unit.stderr
Normal file
16
tests/ui/map_collect_result_unit.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
error: `.map().collect()` can be replaced with `.try_for_each()`
|
||||
--> $DIR/map_collect_result_unit.rs:6:17
|
||||
|
|
||||
LL | let _ = (0..3).map(|t| Err(t + 1)).collect::<Result<(), _>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(0..3).try_for_each(|t| Err(t + 1))`
|
||||
|
|
||||
= note: `-D clippy::map-collect-result-unit` implied by `-D warnings`
|
||||
|
||||
error: `.map().collect()` can be replaced with `.try_for_each()`
|
||||
--> $DIR/map_collect_result_unit.rs:7:32
|
||||
|
|
||||
LL | let _: Result<(), _> = (0..3).map(|t| Err(t + 1)).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(0..3).try_for_each(|t| Err(t + 1))`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -1,4 +1,3 @@
|
||||
// FIXME: Add "run-rustfix" once it's supported for multipart suggestions
|
||||
// aux-build:option_helpers.rs
|
||||
|
||||
#![warn(clippy::map_unwrap_or)]
|
||||
@ -47,10 +46,6 @@ fn option_methods() {
|
||||
let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id);
|
||||
|
||||
// Check for `option.map(_).unwrap_or_else(_)` use.
|
||||
// single line case
|
||||
let _ = opt.map(|x| x + 1)
|
||||
// Should lint even though this call is on a separate line.
|
||||
.unwrap_or_else(|| 0);
|
||||
// Multi-line cases.
|
||||
let _ = opt.map(|x| {
|
||||
x + 1
|
||||
@ -60,37 +55,24 @@ fn option_methods() {
|
||||
.unwrap_or_else(||
|
||||
0
|
||||
);
|
||||
// Macro case.
|
||||
// Should not lint.
|
||||
let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0);
|
||||
|
||||
// Issue #4144
|
||||
{
|
||||
let mut frequencies = HashMap::new();
|
||||
let word = "foo";
|
||||
|
||||
frequencies
|
||||
.get_mut(word)
|
||||
.map(|count| {
|
||||
*count += 1;
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
frequencies.insert(word.to_owned(), 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn result_methods() {
|
||||
let res: Result<i32, ()> = Ok(1);
|
||||
|
||||
// Check for `result.map(_).unwrap_or_else(_)` use.
|
||||
// single line case
|
||||
let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line
|
||||
// multi line cases
|
||||
let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0);
|
||||
let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0);
|
||||
// multi line cases
|
||||
let _ = res.map(|x| {
|
||||
x + 1
|
||||
}
|
||||
).unwrap_or_else(|_e| 0);
|
||||
let _ = res.map(|x| x + 1)
|
||||
.unwrap_or_else(|_e| {
|
||||
0
|
||||
});
|
||||
// macro case
|
||||
let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|e| 0); // should not lint
|
||||
let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|_e| 0); // should not lint
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:17:13
|
||||
error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
|
||||
--> $DIR/map_unwrap_or.rs:16:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| x + 1)
|
||||
| _____________^
|
||||
@ -8,13 +8,13 @@ LL | | .unwrap_or(0);
|
||||
| |_____________________^
|
||||
|
|
||||
= note: `-D clippy::map-unwrap-or` implied by `-D warnings`
|
||||
help: use `map_or(a, f)` instead
|
||||
help: use `map_or(<a>, <f>)` instead
|
||||
|
|
||||
LL | let _ = opt.map_or(0, |x| x + 1);
|
||||
| ^^^^^^ ^^ --
|
||||
|
||||
error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:21:13
|
||||
error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
|
||||
--> $DIR/map_unwrap_or.rs:20:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| {
|
||||
| _____________^
|
||||
@ -23,7 +23,7 @@ LL | | }
|
||||
LL | | ).unwrap_or(0);
|
||||
| |__________________^
|
||||
|
|
||||
help: use `map_or(a, f)` instead
|
||||
help: use `map_or(<a>, <f>)` instead
|
||||
|
|
||||
LL | let _ = opt.map_or(0, |x| {
|
||||
LL | x + 1
|
||||
@ -31,8 +31,8 @@ LL | }
|
||||
LL | );
|
||||
|
|
||||
|
||||
error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:25:13
|
||||
error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
|
||||
--> $DIR/map_unwrap_or.rs:24:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| x + 1)
|
||||
| _____________^
|
||||
@ -41,26 +41,26 @@ LL | | 0
|
||||
LL | | });
|
||||
| |__________^
|
||||
|
|
||||
help: use `map_or(a, f)` instead
|
||||
help: use `map_or(<a>, <f>)` instead
|
||||
|
|
||||
LL | let _ = opt.map_or({
|
||||
LL | 0
|
||||
LL | }, |x| x + 1);
|
||||
|
|
||||
|
||||
error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:30:13
|
||||
error: called `map(<f>).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(<f>)` instead
|
||||
--> $DIR/map_unwrap_or.rs:29:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: use `and_then(f)` instead
|
||||
help: use `and_then(<f>)` instead
|
||||
|
|
||||
LL | let _ = opt.and_then(|x| Some(x + 1));
|
||||
| ^^^^^^^^ --
|
||||
|
||||
error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:32:13
|
||||
error: called `map(<f>).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(<f>)` instead
|
||||
--> $DIR/map_unwrap_or.rs:31:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| {
|
||||
| _____________^
|
||||
@ -69,7 +69,7 @@ LL | | }
|
||||
LL | | ).unwrap_or(None);
|
||||
| |_____________________^
|
||||
|
|
||||
help: use `and_then(f)` instead
|
||||
help: use `and_then(<f>)` instead
|
||||
|
|
||||
LL | let _ = opt.and_then(|x| {
|
||||
LL | Some(x + 1)
|
||||
@ -77,8 +77,8 @@ LL | }
|
||||
LL | );
|
||||
|
|
||||
|
||||
error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:36:13
|
||||
error: called `map(<f>).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(<f>)` instead
|
||||
--> $DIR/map_unwrap_or.rs:35:13
|
||||
|
|
||||
LL | let _ = opt
|
||||
| _____________^
|
||||
@ -86,35 +86,24 @@ LL | | .map(|x| Some(x + 1))
|
||||
LL | | .unwrap_or(None);
|
||||
| |________________________^
|
||||
|
|
||||
help: use `and_then(f)` instead
|
||||
help: use `and_then(<f>)` instead
|
||||
|
|
||||
LL | .and_then(|x| Some(x + 1));
|
||||
| ^^^^^^^^ --
|
||||
|
||||
error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:47:13
|
||||
error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
|
||||
--> $DIR/map_unwrap_or.rs:46:13
|
||||
|
|
||||
LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: use `map_or(a, f)` instead
|
||||
help: use `map_or(<a>, <f>)` instead
|
||||
|
|
||||
LL | let _ = Some("prefix").map_or(id, |p| format!("{}.", p));
|
||||
| ^^^^^^ ^^^ --
|
||||
|
||||
error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:51:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| x + 1)
|
||||
| _____________^
|
||||
LL | | // Should lint even though this call is on a separate line.
|
||||
LL | | .unwrap_or_else(|| 0);
|
||||
| |_____________________________^
|
||||
|
|
||||
= note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)`
|
||||
|
||||
error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:55:13
|
||||
error: called `map(<f>).unwrap_or_else(<g>)` on an `Option` value. This can be done more directly by calling `map_or_else(<g>, <f>)` instead
|
||||
--> $DIR/map_unwrap_or.rs:50:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| {
|
||||
| _____________^
|
||||
@ -123,8 +112,8 @@ LL | | }
|
||||
LL | | ).unwrap_or_else(|| 0);
|
||||
| |__________________________^
|
||||
|
||||
error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:59:13
|
||||
error: called `map(<f>).unwrap_or_else(<g>)` on an `Option` value. This can be done more directly by calling `map_or_else(<g>, <f>)` instead
|
||||
--> $DIR/map_unwrap_or.rs:54:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| x + 1)
|
||||
| _____________^
|
||||
@ -133,29 +122,25 @@ LL | | 0
|
||||
LL | | );
|
||||
| |_________^
|
||||
|
||||
error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:88:13
|
||||
error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
|
||||
--> $DIR/map_unwrap_or.rs:66:13
|
||||
|
|
||||
LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)`
|
||||
LL | let _ = res.map(|x| {
|
||||
| _____________^
|
||||
LL | | x + 1
|
||||
LL | | }
|
||||
LL | | ).unwrap_or_else(|_e| 0);
|
||||
| |____________________________^
|
||||
|
||||
error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:90:13
|
||||
error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
|
||||
--> $DIR/map_unwrap_or.rs:70:13
|
||||
|
|
||||
LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)`
|
||||
LL | let _ = res.map(|x| x + 1)
|
||||
| _____________^
|
||||
LL | | .unwrap_or_else(|_e| {
|
||||
LL | | 0
|
||||
LL | | });
|
||||
| |__________^
|
||||
|
||||
error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead
|
||||
--> $DIR/map_unwrap_or.rs:91:13
|
||||
|
|
||||
LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)`
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
54
tests/ui/map_unwrap_or_fixable.fixed
Normal file
54
tests/ui/map_unwrap_or_fixable.fixed
Normal file
@ -0,0 +1,54 @@
|
||||
// run-rustfix
|
||||
// aux-build:option_helpers.rs
|
||||
|
||||
#![warn(clippy::map_unwrap_or)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate option_helpers;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn option_methods() {
|
||||
let opt = Some(1);
|
||||
|
||||
// Check for `option.map(_).unwrap_or_else(_)` use.
|
||||
// single line case
|
||||
let _ = opt.map_or_else(|| 0, |x| x + 1);
|
||||
|
||||
// Macro case.
|
||||
// Should not lint.
|
||||
let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0);
|
||||
|
||||
// Issue #4144
|
||||
{
|
||||
let mut frequencies = HashMap::new();
|
||||
let word = "foo";
|
||||
|
||||
frequencies
|
||||
.get_mut(word)
|
||||
.map(|count| {
|
||||
*count += 1;
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
frequencies.insert(word.to_owned(), 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn result_methods() {
|
||||
let res: Result<i32, ()> = Ok(1);
|
||||
|
||||
// Check for `result.map(_).unwrap_or_else(_)` use.
|
||||
// single line case
|
||||
let _ = res.map_or_else(|_e| 0, |x| x + 1);
|
||||
|
||||
// macro case
|
||||
let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|_e| 0); // should not lint
|
||||
}
|
||||
|
||||
fn main() {
|
||||
option_methods();
|
||||
result_methods();
|
||||
}
|
58
tests/ui/map_unwrap_or_fixable.rs
Normal file
58
tests/ui/map_unwrap_or_fixable.rs
Normal file
@ -0,0 +1,58 @@
|
||||
// run-rustfix
|
||||
// aux-build:option_helpers.rs
|
||||
|
||||
#![warn(clippy::map_unwrap_or)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate option_helpers;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn option_methods() {
|
||||
let opt = Some(1);
|
||||
|
||||
// Check for `option.map(_).unwrap_or_else(_)` use.
|
||||
// single line case
|
||||
let _ = opt.map(|x| x + 1)
|
||||
// Should lint even though this call is on a separate line.
|
||||
.unwrap_or_else(|| 0);
|
||||
|
||||
// Macro case.
|
||||
// Should not lint.
|
||||
let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0);
|
||||
|
||||
// Issue #4144
|
||||
{
|
||||
let mut frequencies = HashMap::new();
|
||||
let word = "foo";
|
||||
|
||||
frequencies
|
||||
.get_mut(word)
|
||||
.map(|count| {
|
||||
*count += 1;
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
frequencies.insert(word.to_owned(), 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn result_methods() {
|
||||
let res: Result<i32, ()> = Ok(1);
|
||||
|
||||
// Check for `result.map(_).unwrap_or_else(_)` use.
|
||||
// single line case
|
||||
let _ = res.map(|x| x + 1)
|
||||
// should lint even though this call is on a separate line
|
||||
.unwrap_or_else(|_e| 0);
|
||||
|
||||
// macro case
|
||||
let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|_e| 0); // should not lint
|
||||
}
|
||||
|
||||
fn main() {
|
||||
option_methods();
|
||||
result_methods();
|
||||
}
|
22
tests/ui/map_unwrap_or_fixable.stderr
Normal file
22
tests/ui/map_unwrap_or_fixable.stderr
Normal file
@ -0,0 +1,22 @@
|
||||
error: called `map(<f>).unwrap_or_else(<g>)` on an `Option` value. This can be done more directly by calling `map_or_else(<g>, <f>)` instead
|
||||
--> $DIR/map_unwrap_or_fixable.rs:17:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| x + 1)
|
||||
| _____________^
|
||||
LL | | // Should lint even though this call is on a separate line.
|
||||
LL | | .unwrap_or_else(|| 0);
|
||||
| |_____________________________^ help: try this: `opt.map_or_else(|| 0, |x| x + 1)`
|
||||
|
|
||||
= note: `-D clippy::map-unwrap-or` implied by `-D warnings`
|
||||
|
||||
error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
|
||||
--> $DIR/map_unwrap_or_fixable.rs:47:13
|
||||
|
|
||||
LL | let _ = res.map(|x| x + 1)
|
||||
| _____________^
|
||||
LL | | // should lint even though this call is on a separate line
|
||||
LL | | .unwrap_or_else(|_e| 0);
|
||||
| |_______________________________^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -122,16 +122,13 @@ impl Mul<T> for T {
|
||||
fn filter_next() {
|
||||
let v = vec![3, 2, 1, 0, -1, -2, -3];
|
||||
|
||||
// Single-line case.
|
||||
let _ = v.iter().filter(|&x| *x < 0).next();
|
||||
|
||||
// Multi-line case.
|
||||
let _ = v.iter().filter(|&x| {
|
||||
*x < 0
|
||||
}
|
||||
).next();
|
||||
|
||||
// Check that hat we don't lint if the caller is not an `Iterator`.
|
||||
// Check that we don't lint if the caller is not an `Iterator`.
|
||||
let foo = IteratorFalsePositives { foo: 0 };
|
||||
let _ = foo.filter().next();
|
||||
}
|
||||
|
@ -8,27 +8,20 @@ LL | | }
|
||||
|
|
||||
= note: `-D clippy::new-ret-no-self` implied by `-D warnings`
|
||||
|
||||
error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead.
|
||||
error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead.
|
||||
--> $DIR/methods.rs:126:13
|
||||
|
|
||||
LL | let _ = v.iter().filter(|&x| *x < 0).next();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::filter-next` implied by `-D warnings`
|
||||
= note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)`
|
||||
|
||||
error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead.
|
||||
--> $DIR/methods.rs:129:13
|
||||
|
|
||||
LL | let _ = v.iter().filter(|&x| {
|
||||
| _____________^
|
||||
LL | | *x < 0
|
||||
LL | | }
|
||||
LL | | ).next();
|
||||
| |___________________________^
|
||||
|
|
||||
= note: `-D clippy::filter-next` implied by `-D warnings`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:146:22
|
||||
--> $DIR/methods.rs:143:22
|
||||
|
|
||||
LL | let _ = v.iter().find(|&x| *x < 0).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)`
|
||||
@ -36,25 +29,25 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some();
|
||||
= note: `-D clippy::search-is-some` implied by `-D warnings`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:147:20
|
||||
--> $DIR/methods.rs:144:20
|
||||
|
|
||||
LL | let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| **y == x)`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:148:20
|
||||
--> $DIR/methods.rs:145:20
|
||||
|
|
||||
LL | let _ = (0..1).find(|x| *x == 0).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| x == 0)`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:149:22
|
||||
--> $DIR/methods.rs:146:22
|
||||
|
|
||||
LL | let _ = v.iter().find(|x| **x == 0).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x == 0)`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:152:13
|
||||
--> $DIR/methods.rs:149:13
|
||||
|
|
||||
LL | let _ = v.iter().find(|&x| {
|
||||
| _____________^
|
||||
@ -64,13 +57,13 @@ LL | | ).is_some();
|
||||
| |______________________________^
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:158:22
|
||||
--> $DIR/methods.rs:155:22
|
||||
|
|
||||
LL | let _ = v.iter().position(|&x| x < 0).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:161:13
|
||||
--> $DIR/methods.rs:158:13
|
||||
|
|
||||
LL | let _ = v.iter().position(|&x| {
|
||||
| _____________^
|
||||
@ -80,13 +73,13 @@ LL | | ).is_some();
|
||||
| |______________________________^
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:167:22
|
||||
--> $DIR/methods.rs:164:22
|
||||
|
|
||||
LL | let _ = v.iter().rposition(|&x| x < 0).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:170:13
|
||||
--> $DIR/methods.rs:167:13
|
||||
|
|
||||
LL | let _ = v.iter().rposition(|&x| {
|
||||
| _____________^
|
||||
@ -95,5 +88,5 @@ LL | | }
|
||||
LL | | ).is_some();
|
||||
| |______________________________^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
11
tests/ui/methods_fixable.fixed
Normal file
11
tests/ui/methods_fixable.fixed
Normal file
@ -0,0 +1,11 @@
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::filter_next)]
|
||||
|
||||
/// Checks implementation of `FILTER_NEXT` lint.
|
||||
fn main() {
|
||||
let v = vec![3, 2, 1, 0, -1, -2, -3];
|
||||
|
||||
// Single-line case.
|
||||
let _ = v.iter().find(|&x| *x < 0);
|
||||
}
|
11
tests/ui/methods_fixable.rs
Normal file
11
tests/ui/methods_fixable.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::filter_next)]
|
||||
|
||||
/// Checks implementation of `FILTER_NEXT` lint.
|
||||
fn main() {
|
||||
let v = vec![3, 2, 1, 0, -1, -2, -3];
|
||||
|
||||
// Single-line case.
|
||||
let _ = v.iter().filter(|&x| *x < 0).next();
|
||||
}
|
10
tests/ui/methods_fixable.stderr
Normal file
10
tests/ui/methods_fixable.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead.
|
||||
--> $DIR/methods_fixable.rs:10:13
|
||||
|
|
||||
LL | let _ = v.iter().filter(|&x| *x < 0).next();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `v.iter().find(|&x| *x < 0)`
|
||||
|
|
||||
= note: `-D clippy::filter-next` implied by `-D warnings`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: called `map_or(None, f)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead
|
||||
error: called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling `and_then(..)` instead
|
||||
--> $DIR/option_map_or_none.rs:10:13
|
||||
|
|
||||
LL | let _ = opt.map_or(None, |x| Some(x + 1));
|
||||
@ -6,7 +6,7 @@ LL | let _ = opt.map_or(None, |x| Some(x + 1));
|
||||
|
|
||||
= note: `-D clippy::option-map-or-none` implied by `-D warnings`
|
||||
|
||||
error: called `map_or(None, f)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead
|
||||
error: called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling `and_then(..)` instead
|
||||
--> $DIR/option_map_or_none.rs:13:13
|
||||
|
|
||||
LL | let _ = opt.map_or(None, |x| {
|
||||
|
@ -1,13 +1,13 @@
|
||||
error: called `skip_while(p).next()` on an `Iterator`
|
||||
error: called `skip_while(<p>).next()` on an `Iterator`
|
||||
--> $DIR/skip_while_next.rs:14:13
|
||||
|
|
||||
LL | let _ = v.iter().skip_while(|&x| *x < 0).next();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::skip-while-next` implied by `-D warnings`
|
||||
= help: this is more succinctly expressed by calling `.find(!p)` instead
|
||||
= help: this is more succinctly expressed by calling `.find(!<p>)` instead
|
||||
|
||||
error: called `skip_while(p).next()` on an `Iterator`
|
||||
error: called `skip_while(<p>).next()` on an `Iterator`
|
||||
--> $DIR/skip_while_next.rs:17:13
|
||||
|
|
||||
LL | let _ = v.iter().skip_while(|&x| {
|
||||
@ -17,7 +17,7 @@ LL | | }
|
||||
LL | | ).next();
|
||||
| |___________________________^
|
||||
|
|
||||
= help: this is more succinctly expressed by calling `.find(!p)` instead
|
||||
= help: this is more succinctly expressed by calling `.find(!<p>)` instead
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#![warn(clippy::temporary_assignment)]
|
||||
#![allow(const_item_mutation)]
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:48:5
|
||||
--> $DIR/temporary_assignment.rs:47:5
|
||||
|
|
||||
LL | Struct { field: 0 }.field = 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -7,7 +7,7 @@ LL | Struct { field: 0 }.field = 1;
|
||||
= note: `-D clippy::temporary-assignment` implied by `-D warnings`
|
||||
|
||||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:49:5
|
||||
--> $DIR/temporary_assignment.rs:48:5
|
||||
|
|
||||
LL | / MultiStruct {
|
||||
LL | | structure: Struct { field: 0 },
|
||||
@ -17,13 +17,13 @@ LL | | .field = 1;
|
||||
| |______________^
|
||||
|
||||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:54:5
|
||||
--> $DIR/temporary_assignment.rs:53:5
|
||||
|
|
||||
LL | ArrayStruct { array: [0] }.array[0] = 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:55:5
|
||||
--> $DIR/temporary_assignment.rs:54:5
|
||||
|
|
||||
LL | (0, 0).0 = 1;
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -1,7 +1,17 @@
|
||||
// run-rustfix
|
||||
// aux-build:macro_rules.rs
|
||||
|
||||
#![warn(clippy::toplevel_ref_arg)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate macro_rules;
|
||||
|
||||
macro_rules! gen_binding {
|
||||
() => {
|
||||
let _y = &42;
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Closures should not warn
|
||||
let y = |ref x| println!("{:?}", x);
|
||||
@ -26,4 +36,15 @@ fn main() {
|
||||
|
||||
// ok
|
||||
for ref _x in 0..10 {}
|
||||
|
||||
// lint in macro
|
||||
#[allow(unused)]
|
||||
{
|
||||
gen_binding!();
|
||||
}
|
||||
|
||||
// do not lint in external macro
|
||||
{
|
||||
ref_arg_binding!();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,17 @@
|
||||
// run-rustfix
|
||||
// aux-build:macro_rules.rs
|
||||
|
||||
#![warn(clippy::toplevel_ref_arg)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate macro_rules;
|
||||
|
||||
macro_rules! gen_binding {
|
||||
() => {
|
||||
let ref _y = 42;
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Closures should not warn
|
||||
let y = |ref x| println!("{:?}", x);
|
||||
@ -26,4 +36,15 @@ fn main() {
|
||||
|
||||
// ok
|
||||
for ref _x in 0..10 {}
|
||||
|
||||
// lint in macro
|
||||
#[allow(unused)]
|
||||
{
|
||||
gen_binding!();
|
||||
}
|
||||
|
||||
// do not lint in external macro
|
||||
{
|
||||
ref_arg_binding!();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
|
||||
--> $DIR/toplevel_ref_arg.rs:10:9
|
||||
--> $DIR/toplevel_ref_arg.rs:20:9
|
||||
|
|
||||
LL | let ref _x = 1;
|
||||
| ----^^^^^^----- help: try: `let _x = &1;`
|
||||
@ -7,28 +7,39 @@ LL | let ref _x = 1;
|
||||
= note: `-D clippy::toplevel-ref-arg` implied by `-D warnings`
|
||||
|
||||
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
|
||||
--> $DIR/toplevel_ref_arg.rs:12:9
|
||||
--> $DIR/toplevel_ref_arg.rs:22:9
|
||||
|
|
||||
LL | let ref _y: (&_, u8) = (&1, 2);
|
||||
| ----^^^^^^--------------------- help: try: `let _y: &(&_, u8) = &(&1, 2);`
|
||||
|
||||
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
|
||||
--> $DIR/toplevel_ref_arg.rs:14:9
|
||||
--> $DIR/toplevel_ref_arg.rs:24:9
|
||||
|
|
||||
LL | let ref _z = 1 + 2;
|
||||
| ----^^^^^^--------- help: try: `let _z = &(1 + 2);`
|
||||
|
||||
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
|
||||
--> $DIR/toplevel_ref_arg.rs:16:9
|
||||
--> $DIR/toplevel_ref_arg.rs:26:9
|
||||
|
|
||||
LL | let ref mut _z = 1 + 2;
|
||||
| ----^^^^^^^^^^--------- help: try: `let _z = &mut (1 + 2);`
|
||||
|
||||
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
|
||||
--> $DIR/toplevel_ref_arg.rs:21:9
|
||||
--> $DIR/toplevel_ref_arg.rs:31:9
|
||||
|
|
||||
LL | let ref _x = vec![1, 2, 3];
|
||||
| ----^^^^^^----------------- help: try: `let _x = &vec![1, 2, 3];`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
|
||||
--> $DIR/toplevel_ref_arg.rs:11:13
|
||||
|
|
||||
LL | let ref _y = 42;
|
||||
| ----^^^^^^------ help: try: `let _y = &42;`
|
||||
...
|
||||
LL | gen_binding!();
|
||||
| --------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
@ -1,11 +1,33 @@
|
||||
// aux-build:macro_rules.rs
|
||||
|
||||
#![warn(clippy::toplevel_ref_arg)]
|
||||
#![allow(unused)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate macro_rules;
|
||||
|
||||
fn the_answer(ref mut x: u8) {
|
||||
*x = 42;
|
||||
}
|
||||
|
||||
macro_rules! gen_function {
|
||||
() => {
|
||||
fn fun_example(ref _x: usize) {}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut x = 0;
|
||||
the_answer(x);
|
||||
|
||||
// lint in macro
|
||||
#[allow(unused)]
|
||||
{
|
||||
gen_function!();
|
||||
}
|
||||
|
||||
// do not lint in external macro
|
||||
{
|
||||
ref_arg_function!();
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,21 @@
|
||||
error: `ref` directly on a function argument is ignored. Consider using a reference type instead.
|
||||
--> $DIR/toplevel_ref_arg_non_rustfix.rs:4:15
|
||||
--> $DIR/toplevel_ref_arg_non_rustfix.rs:9:15
|
||||
|
|
||||
LL | fn the_answer(ref mut x: u8) {
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::toplevel-ref-arg` implied by `-D warnings`
|
||||
|
||||
error: aborting due to previous error
|
||||
error: `ref` directly on a function argument is ignored. Consider using a reference type instead.
|
||||
--> $DIR/toplevel_ref_arg_non_rustfix.rs:15:24
|
||||
|
|
||||
LL | fn fun_example(ref _x: usize) {}
|
||||
| ^^^^^^
|
||||
...
|
||||
LL | gen_function!();
|
||||
| ---------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user