diff --git a/CHANGELOG.md b/CHANGELOG.md index acc9d8ffbf7f..c50d28273bf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5366,6 +5366,7 @@ Released 2018-09-13 [`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit [`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings [`unwrap_in_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_in_result +[`unwrap_or_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_or_default [`unwrap_or_else_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_or_else_default [`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used [`upper_case_acronyms`]: https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 47995fea9f9e..cb5fed5f1093 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -422,7 +422,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::UNNECESSARY_LITERAL_UNWRAP_INFO, crate::methods::UNNECESSARY_SORT_BY_INFO, crate::methods::UNNECESSARY_TO_OWNED_INFO, - crate::methods::UNWRAP_OR_ELSE_DEFAULT_INFO, + crate::methods::UNWRAP_OR_DEFAULT_INFO, crate::methods::UNWRAP_USED_INFO, crate::methods::USELESS_ASREF_INFO, crate::methods::VEC_RESIZE_TO_ZERO_INFO, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index be71072acd6c..1058289679bd 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -103,7 +103,6 @@ mod unnecessary_lazy_eval; mod unnecessary_literal_unwrap; mod unnecessary_sort_by; mod unnecessary_to_owned; -mod unwrap_or_else_default; mod unwrap_used; mod useless_asref; mod utils; @@ -476,29 +475,40 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usage of `_.unwrap_or_else(Default::default)` on `Option` and - /// `Result` values. + /// Checks for usages of the following functions with an argument that constructs a default value + /// (e.g., `Default::default` or `String::new`): + /// - `unwrap_or` + /// - `unwrap_or_else` + /// - `or_insert` + /// - `or_insert_with` /// /// ### Why is this bad? - /// Readability, these can be written as `_.unwrap_or_default`, which is - /// simpler and more concise. + /// Readability. Using `unwrap_or_default` in place of `unwrap_or`/`unwrap_or_else`, or `or_default` + /// in place of `or_insert`/`or_insert_with`, is simpler and more concise. + /// + /// ### Known problems + /// In some cases, the argument of `unwrap_or`, etc. is needed for type inference. The lint uses a + /// heuristic to try to identify such cases. However, the heuristic can produce false negatives. /// /// ### Examples /// ```rust /// # let x = Some(1); - /// x.unwrap_or_else(Default::default); - /// x.unwrap_or_else(u32::default); + /// # let mut map = std::collections::HashMap::::new(); + /// x.unwrap_or(Default::default()); + /// map.entry(42).or_insert_with(String::new); /// ``` /// /// Use instead: /// ```rust /// # let x = Some(1); + /// # let mut map = std::collections::HashMap::::new(); /// x.unwrap_or_default(); + /// map.entry(42).or_default(); /// ``` #[clippy::version = "1.56.0"] - pub UNWRAP_OR_ELSE_DEFAULT, + pub UNWRAP_OR_DEFAULT, style, - "using `.unwrap_or_else(Default::default)`, which is more succinctly expressed as `.unwrap_or_default()`" + "using `.unwrap_or`, etc. with an argument that constructs a default value" } declare_clippy_lint! { @@ -3495,7 +3505,7 @@ impl_lint_pass!(Methods => [ SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION, OK_EXPECT, - UNWRAP_OR_ELSE_DEFAULT, + UNWRAP_OR_DEFAULT, MAP_UNWRAP_OR, RESULT_MAP_OR_INTO_OPTION, OPTION_MAP_OR_NONE, @@ -3756,8 +3766,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { then { let first_arg_span = first_arg_ty.span; let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty); - let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()) - .self_ty(); + let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty(); wrong_self_convention::check( cx, item.ident.name.as_str(), @@ -3774,8 +3783,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if item.ident.name == sym::new; if let TraitItemKind::Fn(_, _) = item.kind; let ret_ty = return_ty(cx, item.owner_id); - let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()) - .self_ty(); + let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty(); if !ret_ty.contains(self_ty); then { @@ -4134,7 +4142,6 @@ impl Methods { Some(("map", recv, [map_arg], _, _)) if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {}, _ => { - unwrap_or_else_default::check(cx, expr, recv, u_arg); unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"); }, } diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs index 9165c1248f0a..9fe863ecc0dc 100644 --- a/clippy_lints/src/methods/or_fun_call.rs +++ b/clippy_lints/src/methods/or_fun_call.rs @@ -1,16 +1,17 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::eager_or_lazy::switch_to_lazy_eval; use clippy_utils::source::snippet_with_context; -use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; -use clippy_utils::{contains_return, is_trait_item, last_path_segment}; +use clippy_utils::ty::{expr_type_is_certain, implements_trait, is_type_diagnostic_item}; +use clippy_utils::{contains_return, is_default_equivalent, is_default_equivalent_call, last_path_segment}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_middle::ty; use rustc_span::source_map::Span; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{self, sym, Symbol}; +use {rustc_ast as ast, rustc_hir as hir}; -use super::OR_FUN_CALL; +use super::{OR_FUN_CALL, UNWRAP_OR_DEFAULT}; /// Checks for the `OR_FUN_CALL` lint. #[allow(clippy::too_many_lines)] @@ -24,53 +25,72 @@ pub(super) fn check<'tcx>( ) { /// Checks for `unwrap_or(T::new())`, `unwrap_or(T::default())`, /// `or_insert(T::new())` or `or_insert(T::default())`. + /// Similarly checks for `unwrap_or_else(T::new)`, `unwrap_or_else(T::default)`, + /// `or_insert_with(T::new)` or `or_insert_with(T::default)`. #[allow(clippy::too_many_arguments)] fn check_unwrap_or_default( cx: &LateContext<'_>, name: &str, + receiver: &hir::Expr<'_>, fun: &hir::Expr<'_>, - arg: &hir::Expr<'_>, - or_has_args: bool, + call_expr: Option<&hir::Expr<'_>>, span: Span, method_span: Span, ) -> bool { - let is_default_default = || is_trait_item(cx, fun, sym::Default); + if !expr_type_is_certain(cx, receiver) { + return false; + } - let implements_default = |arg, default_trait_id| { - let arg_ty = cx.typeck_results().expr_ty(arg); - implements_trait(cx, arg_ty, default_trait_id, &[]) + let is_new = |fun: &hir::Expr<'_>| { + if let hir::ExprKind::Path(ref qpath) = fun.kind { + let path = last_path_segment(qpath).ident.name; + matches!(path, sym::new) + } else { + false + } }; - if_chain! { - if !or_has_args; - if let Some(sugg) = match name { - "unwrap_or" => Some("unwrap_or_default"), - "or_insert" => Some("or_default"), - _ => None, - }; - if let hir::ExprKind::Path(ref qpath) = fun.kind; - if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default); - let path = last_path_segment(qpath).ident.name; - // needs to target Default::default in particular or be *::new and have a Default impl - // available - if (matches!(path, kw::Default) && is_default_default()) - || (matches!(path, sym::new) && implements_default(arg, default_trait_id)); - - then { - span_lint_and_sugg( - cx, - OR_FUN_CALL, - method_span.with_hi(span.hi()), - &format!("use of `{name}` followed by a call to `{path}`"), - "try", - format!("{sugg}()"), - Applicability::MachineApplicable, - ); - - true + let output_type_implements_default = |fun| { + let fun_ty = cx.typeck_results().expr_ty(fun); + if let ty::FnDef(def_id, substs) = fun_ty.kind() { + let output_ty = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs).skip_binder().output(); + cx.tcx + .get_diagnostic_item(sym::Default) + .map_or(false, |default_trait_id| { + implements_trait(cx, output_ty, default_trait_id, substs) + }) } else { false } + }; + + let sugg = match (name, call_expr.is_some()) { + ("unwrap_or", true) | ("unwrap_or_else", false) => "unwrap_or_default", + ("or_insert", true) | ("or_insert_with", false) => "or_default", + _ => return false, + }; + + // needs to target Default::default in particular or be *::new and have a Default impl + // available + if (is_new(fun) && output_type_implements_default(fun)) + || match call_expr { + Some(call_expr) => is_default_equivalent(cx, call_expr), + None => is_default_equivalent_call(cx, fun) || closure_body_returns_empty_to_string(cx, fun), + } + { + span_lint_and_sugg( + cx, + UNWRAP_OR_DEFAULT, + method_span.with_hi(span.hi()), + &format!("use of `{name}` to construct default value"), + "try", + format!("{sugg}()"), + Applicability::MachineApplicable, + ); + + true + } else { + false } } @@ -168,11 +188,16 @@ pub(super) fn check<'tcx>( match inner_arg.kind { hir::ExprKind::Call(fun, or_args) => { let or_has_args = !or_args.is_empty(); - if !check_unwrap_or_default(cx, name, fun, arg, or_has_args, expr.span, method_span) { + if or_has_args + || !check_unwrap_or_default(cx, name, receiver, fun, Some(inner_arg), expr.span, method_span) + { let fun_span = if or_has_args { None } else { Some(fun.span) }; check_general_case(cx, name, method_span, receiver, arg, None, expr.span, fun_span); } }, + hir::ExprKind::Path(..) | hir::ExprKind::Closure(..) => { + check_unwrap_or_default(cx, name, receiver, inner_arg, None, expr.span, method_span); + }, hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => { check_general_case(cx, name, method_span, receiver, arg, None, expr.span, None); }, @@ -189,3 +214,22 @@ pub(super) fn check<'tcx>( } } } + +fn closure_body_returns_empty_to_string(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> bool { + if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = e.kind { + let body = cx.tcx.hir().body(body); + + if body.params.is_empty() + && let hir::Expr{ kind, .. } = &body.value + && let hir::ExprKind::MethodCall(hir::PathSegment {ident, ..}, self_arg, _, _) = kind + && ident.name == sym::to_string + && let hir::Expr{ kind, .. } = self_arg + && let hir::ExprKind::Lit(lit) = kind + && let ast::LitKind::Str(symbol::kw::Empty, _) = lit.node + { + return true; + } + } + + false +} diff --git a/clippy_lints/src/methods/unwrap_or_else_default.rs b/clippy_lints/src/methods/unwrap_or_else_default.rs deleted file mode 100644 index cfb1f7bbba8f..000000000000 --- a/clippy_lints/src/methods/unwrap_or_else_default.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! Lint for `some_result_or_option.unwrap_or_else(Default::default)` - -use super::UNWRAP_OR_ELSE_DEFAULT; -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_default_equivalent_call; -use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::{expr_type_is_certain, is_type_diagnostic_item}; -use rustc_ast::ast::LitKind; -use rustc_errors::Applicability; -use rustc_hir as hir; -use rustc_lint::LateContext; -use rustc_span::{sym, symbol}; - -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - recv: &'tcx hir::Expr<'_>, - u_arg: &'tcx hir::Expr<'_>, -) { - if !expr_type_is_certain(cx, recv) { - return; - } - - // something.unwrap_or_else(Default::default) - // ^^^^^^^^^- recv ^^^^^^^^^^^^^^^^- u_arg - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- expr - let recv_ty = cx.typeck_results().expr_ty(recv); - let is_option = is_type_diagnostic_item(cx, recv_ty, sym::Option); - let is_result = is_type_diagnostic_item(cx, recv_ty, sym::Result); - - if_chain! { - if is_option || is_result; - if closure_body_returns_empty_to_string(cx, u_arg) || is_default_equivalent_call(cx, u_arg); - then { - let mut applicability = Applicability::MachineApplicable; - - span_lint_and_sugg( - cx, - UNWRAP_OR_ELSE_DEFAULT, - expr.span, - "use of `.unwrap_or_else(..)` to construct default value", - "try", - format!( - "{}.unwrap_or_default()", - snippet_with_applicability(cx, recv.span, "..", &mut applicability) - ), - applicability, - ); - } - } -} - -fn closure_body_returns_empty_to_string(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> bool { - if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = e.kind { - let body = cx.tcx.hir().body(body); - - if body.params.is_empty() - && let hir::Expr{ kind, .. } = &body.value - && let hir::ExprKind::MethodCall(hir::PathSegment {ident, ..}, self_arg, _, _) = kind - && ident == &symbol::Ident::from_str("to_string") - && let hir::Expr{ kind, .. } = self_arg - && let hir::ExprKind::Lit(lit) = kind - && let LitKind::Str(symbol::kw::Empty, _) = lit.node - { - return true; - } - } - - false -} diff --git a/clippy_lints/src/renamed_lints.rs b/clippy_lints/src/renamed_lints.rs index d24215c22924..13086f996eee 100644 --- a/clippy_lints/src/renamed_lints.rs +++ b/clippy_lints/src/renamed_lints.rs @@ -30,6 +30,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[ ("clippy::single_char_push_str", "clippy::single_char_add_str"), ("clippy::stutter", "clippy::module_name_repetitions"), ("clippy::to_string_in_display", "clippy::recursive_format_impl"), + ("clippy::unwrap_or_else_default", "clippy::unwrap_or_default"), ("clippy::zero_width_space", "clippy::invisible_characters"), ("clippy::cast_ref_to_mut", "cast_ref_to_mut"), ("clippy::clone_double_ref", "suspicious_double_ref_op"), diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index 6deff0f3240a..581f3ad45c7d 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -190,7 +190,7 @@ mod issue8239 { acc.push_str(&f); acc }) - .unwrap_or_default(); + .unwrap_or(String::new()); } fn more_to_max_suggestion_highest_lines_1() { @@ -203,7 +203,7 @@ mod issue8239 { acc.push_str(&f); acc }) - .unwrap_or_default(); + .unwrap_or(String::new()); } fn equal_to_max_suggestion_highest_lines() { @@ -215,7 +215,7 @@ mod issue8239 { acc.push_str(&f); acc }) - .unwrap_or_default(); + .unwrap_or(String::new()); } fn less_than_max_suggestion_highest_lines() { @@ -226,7 +226,7 @@ mod issue8239 { acc.push_str(&f); acc }) - .unwrap_or_default(); + .unwrap_or(String::new()); } } @@ -257,4 +257,59 @@ mod issue8993 { } } +mod lazy { + use super::*; + + fn foo() { + struct Foo; + + impl Foo { + fn new() -> Foo { + Foo + } + } + + struct FakeDefault; + impl FakeDefault { + fn default() -> Self { + FakeDefault + } + } + + impl Default for FakeDefault { + fn default() -> Self { + FakeDefault + } + } + + let with_new = Some(vec![1]); + with_new.unwrap_or_default(); + + let with_default_trait = Some(1); + with_default_trait.unwrap_or_default(); + + let with_default_type = Some(1); + with_default_type.unwrap_or_default(); + + let real_default = None::; + real_default.unwrap_or_default(); + + let mut map = HashMap::::new(); + map.entry(42).or_default(); + + let mut btree = BTreeMap::::new(); + btree.entry(42).or_default(); + + let stringy = Some(String::new()); + let _ = stringy.unwrap_or_default(); + + // negative tests + let self_default = None::; + self_default.unwrap_or_else(::default); + + let without_default = Some(Foo); + without_default.unwrap_or_else(Foo::new); + } +} + fn main() {} diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index b05b33e6ee2b..1f3987eb8917 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -257,4 +257,59 @@ mod issue8993 { } } +mod lazy { + use super::*; + + fn foo() { + struct Foo; + + impl Foo { + fn new() -> Foo { + Foo + } + } + + struct FakeDefault; + impl FakeDefault { + fn default() -> Self { + FakeDefault + } + } + + impl Default for FakeDefault { + fn default() -> Self { + FakeDefault + } + } + + let with_new = Some(vec![1]); + with_new.unwrap_or_else(Vec::new); + + let with_default_trait = Some(1); + with_default_trait.unwrap_or_else(Default::default); + + let with_default_type = Some(1); + with_default_type.unwrap_or_else(u64::default); + + let real_default = None::; + real_default.unwrap_or_else(::default); + + let mut map = HashMap::::new(); + map.entry(42).or_insert_with(String::new); + + let mut btree = BTreeMap::::new(); + btree.entry(42).or_insert_with(String::new); + + let stringy = Some(String::new()); + let _ = stringy.unwrap_or_else(String::new); + + // negative tests + let self_default = None::; + self_default.unwrap_or_else(::default); + + let without_default = Some(Foo); + without_default.unwrap_or_else(Foo::new); + } +} + fn main() {} diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index 7342b0c2914b..519f09165626 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -6,11 +6,13 @@ LL | with_constructor.unwrap_or(make()); | = note: `-D clippy::or-fun-call` implied by `-D warnings` -error: use of `unwrap_or` followed by a call to `new` +error: use of `unwrap_or` to construct default value --> $DIR/or_fun_call.rs:56:14 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` + | + = note: `-D clippy::unwrap-or-default` implied by `-D warnings` error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:59:21 @@ -30,13 +32,13 @@ error: use of `unwrap_or` followed by a function call LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| Vec::with_capacity(12))` -error: use of `unwrap_or` followed by a call to `default` +error: use of `unwrap_or` to construct default value --> $DIR/or_fun_call.rs:68:24 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `unwrap_or` followed by a call to `default` +error: use of `unwrap_or` to construct default value --> $DIR/or_fun_call.rs:71:23 | LL | with_default_type.unwrap_or(u64::default()); @@ -48,13 +50,13 @@ error: use of `unwrap_or` followed by a function call LL | self_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(::default)` -error: use of `unwrap_or` followed by a call to `default` +error: use of `unwrap_or` to construct default value --> $DIR/or_fun_call.rs:77:18 | LL | real_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `unwrap_or` followed by a call to `new` +error: use of `unwrap_or` to construct default value --> $DIR/or_fun_call.rs:80:14 | LL | with_vec.unwrap_or(vec![]); @@ -66,31 +68,31 @@ error: use of `unwrap_or` followed by a function call LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(Foo::new)` -error: use of `or_insert` followed by a call to `new` +error: use of `or_insert` to construct default value --> $DIR/or_fun_call.rs:86:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` -error: use of `or_insert` followed by a call to `new` +error: use of `or_insert` to construct default value --> $DIR/or_fun_call.rs:89:23 | LL | map_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try: `or_default()` -error: use of `or_insert` followed by a call to `new` +error: use of `or_insert` to construct default value --> $DIR/or_fun_call.rs:92:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` -error: use of `or_insert` followed by a call to `new` +error: use of `or_insert` to construct default value --> $DIR/or_fun_call.rs:95:25 | LL | btree_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try: `or_default()` -error: use of `unwrap_or` followed by a call to `new` +error: use of `unwrap_or` to construct default value --> $DIR/or_fun_call.rs:98:21 | LL | let _ = stringy.unwrap_or(String::new()); @@ -132,30 +134,6 @@ error: use of `unwrap_or` followed by a function call LL | None.unwrap_or( unsafe { ptr_to_ref(s) } ); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` -error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:193:14 - | -LL | .unwrap_or(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` - -error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:206:14 - | -LL | .unwrap_or(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` - -error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:218:14 - | -LL | .unwrap_or(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` - -error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:229:10 - | -LL | .unwrap_or(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` - error: use of `map_or` followed by a function call --> $DIR/or_fun_call.rs:254:25 | @@ -168,5 +146,47 @@ error: use of `map_or` followed by a function call LL | let _ = Some(4).map_or(g(), f); | ^^^^^^^^^^^^^^ help: try: `map_or_else(g, f)` -error: aborting due to 28 previous errors +error: use of `unwrap_or_else` to construct default value + --> $DIR/or_fun_call.rs:286:18 + | +LL | with_new.unwrap_or_else(Vec::new); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` + +error: use of `unwrap_or_else` to construct default value + --> $DIR/or_fun_call.rs:289:28 + | +LL | with_default_trait.unwrap_or_else(Default::default); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` + +error: use of `unwrap_or_else` to construct default value + --> $DIR/or_fun_call.rs:292:27 + | +LL | with_default_type.unwrap_or_else(u64::default); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` + +error: use of `unwrap_or_else` to construct default value + --> $DIR/or_fun_call.rs:295:22 + | +LL | real_default.unwrap_or_else(::default); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` + +error: use of `or_insert_with` to construct default value + --> $DIR/or_fun_call.rs:298:23 + | +LL | map.entry(42).or_insert_with(String::new); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` + +error: use of `or_insert_with` to construct default value + --> $DIR/or_fun_call.rs:301:25 + | +LL | btree.entry(42).or_insert_with(String::new); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` + +error: use of `unwrap_or_else` to construct default value + --> $DIR/or_fun_call.rs:304:25 + | +LL | let _ = stringy.unwrap_or_else(String::new); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` + +error: aborting due to 31 previous errors diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed index cab02bb93c9c..6936d526aebc 100644 --- a/tests/ui/rename.fixed +++ b/tests/ui/rename.fixed @@ -27,6 +27,7 @@ #![allow(clippy::single_char_add_str)] #![allow(clippy::module_name_repetitions)] #![allow(clippy::recursive_format_impl)] +#![allow(clippy::unwrap_or_default)] #![allow(clippy::invisible_characters)] #![allow(cast_ref_to_mut)] #![allow(suspicious_double_ref_op)] @@ -78,6 +79,7 @@ #![warn(clippy::single_char_add_str)] #![warn(clippy::module_name_repetitions)] #![warn(clippy::recursive_format_impl)] +#![warn(clippy::unwrap_or_default)] #![warn(clippy::invisible_characters)] #![warn(cast_ref_to_mut)] #![warn(suspicious_double_ref_op)] diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index e5e31452149d..626e52020253 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -27,6 +27,7 @@ #![allow(clippy::single_char_add_str)] #![allow(clippy::module_name_repetitions)] #![allow(clippy::recursive_format_impl)] +#![allow(clippy::unwrap_or_default)] #![allow(clippy::invisible_characters)] #![allow(cast_ref_to_mut)] #![allow(suspicious_double_ref_op)] @@ -78,6 +79,7 @@ #![warn(clippy::single_char_push_str)] #![warn(clippy::stutter)] #![warn(clippy::to_string_in_display)] +#![warn(clippy::unwrap_or_else_default)] #![warn(clippy::zero_width_space)] #![warn(clippy::cast_ref_to_mut)] #![warn(clippy::clone_double_ref)] diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 783608a08410..a0e0a66892e9 100644 --- a/tests/ui/rename.stderr +++ b/tests/ui/rename.stderr @@ -1,5 +1,5 @@ error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` - --> $DIR/rename.rs:53:9 + --> $DIR/rename.rs:54:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -7,316 +7,322 @@ LL | #![warn(clippy::almost_complete_letter_range)] = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` - --> $DIR/rename.rs:54:9 + --> $DIR/rename.rs:55:9 | LL | #![warn(clippy::blacklisted_name)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:55:9 + --> $DIR/rename.rs:56:9 | LL | #![warn(clippy::block_in_if_condition_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:56:9 + --> $DIR/rename.rs:57:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> $DIR/rename.rs:57:9 + --> $DIR/rename.rs:58:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> $DIR/rename.rs:58:9 + --> $DIR/rename.rs:59:9 | LL | #![warn(clippy::const_static_lifetime)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> $DIR/rename.rs:59:9 + --> $DIR/rename.rs:60:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq` - --> $DIR/rename.rs:60:9 + --> $DIR/rename.rs:61:9 | LL | #![warn(clippy::derive_hash_xor_eq)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` - --> $DIR/rename.rs:61:9 + --> $DIR/rename.rs:62:9 | LL | #![warn(clippy::disallowed_method)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` - --> $DIR/rename.rs:62:9 + --> $DIR/rename.rs:63:9 | LL | #![warn(clippy::disallowed_type)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` - --> $DIR/rename.rs:63:9 + --> $DIR/rename.rs:64:9 | LL | #![warn(clippy::eval_order_dependence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` - --> $DIR/rename.rs:64:9 + --> $DIR/rename.rs:65:9 | LL | #![warn(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` - --> $DIR/rename.rs:65:9 + --> $DIR/rename.rs:66:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> $DIR/rename.rs:66:9 + --> $DIR/rename.rs:67:9 | LL | #![warn(clippy::integer_arithmetic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> $DIR/rename.rs:67:9 + --> $DIR/rename.rs:68:9 | LL | #![warn(clippy::logic_bug)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> $DIR/rename.rs:68:9 + --> $DIR/rename.rs:69:9 | LL | #![warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` - --> $DIR/rename.rs:69:9 + --> $DIR/rename.rs:70:9 | LL | #![warn(clippy::option_and_then_some)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:70:9 + --> $DIR/rename.rs:71:9 | LL | #![warn(clippy::option_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:71:9 + --> $DIR/rename.rs:72:9 | LL | #![warn(clippy::option_map_unwrap_or)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:72:9 + --> $DIR/rename.rs:73:9 | LL | #![warn(clippy::option_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:73:9 + --> $DIR/rename.rs:74:9 | LL | #![warn(clippy::option_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` - --> $DIR/rename.rs:74:9 + --> $DIR/rename.rs:75:9 | LL | #![warn(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:75:9 + --> $DIR/rename.rs:76:9 | LL | #![warn(clippy::result_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:76:9 + --> $DIR/rename.rs:77:9 | LL | #![warn(clippy::result_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:77:9 + --> $DIR/rename.rs:78:9 | LL | #![warn(clippy::result_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` - --> $DIR/rename.rs:78:9 + --> $DIR/rename.rs:79:9 | LL | #![warn(clippy::single_char_push_str)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> $DIR/rename.rs:79:9 + --> $DIR/rename.rs:80:9 | LL | #![warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` - --> $DIR/rename.rs:80:9 + --> $DIR/rename.rs:81:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` +error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default` + --> $DIR/rename.rs:82:9 + | +LL | #![warn(clippy::unwrap_or_else_default)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default` + error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> $DIR/rename.rs:81:9 + --> $DIR/rename.rs:83:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut` - --> $DIR/rename.rs:82:9 + --> $DIR/rename.rs:84:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> $DIR/rename.rs:83:9 + --> $DIR/rename.rs:85:9 | LL | #![warn(clippy::clone_double_ref)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op` error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons` - --> $DIR/rename.rs:84:9 + --> $DIR/rename.rs:86:9 | LL | #![warn(clippy::cmp_nan)] | ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons` error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` - --> $DIR/rename.rs:85:9 + --> $DIR/rename.rs:87:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` - --> $DIR/rename.rs:86:9 + --> $DIR/rename.rs:88:9 | LL | #![warn(clippy::drop_copy)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` error: lint `clippy::drop_ref` has been renamed to `dropping_references` - --> $DIR/rename.rs:87:9 + --> $DIR/rename.rs:89:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:88:9 + --> $DIR/rename.rs:90:9 | LL | #![warn(clippy::for_loop_over_option)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:89:9 + --> $DIR/rename.rs:91:9 | LL | #![warn(clippy::for_loop_over_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:90:9 + --> $DIR/rename.rs:92:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` - --> $DIR/rename.rs:91:9 + --> $DIR/rename.rs:93:9 | LL | #![warn(clippy::forget_copy)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` error: lint `clippy::forget_ref` has been renamed to `forgetting_references` - --> $DIR/rename.rs:92:9 + --> $DIR/rename.rs:94:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` error: lint `clippy::fn_null_check` has been renamed to `incorrect_fn_null_checks` - --> $DIR/rename.rs:93:9 + --> $DIR/rename.rs:95:9 | LL | #![warn(clippy::fn_null_check)] | ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `incorrect_fn_null_checks` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/rename.rs:94:9 + --> $DIR/rename.rs:96:9 | LL | #![warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> $DIR/rename.rs:95:9 + --> $DIR/rename.rs:97:9 | LL | #![warn(clippy::invalid_atomic_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> $DIR/rename.rs:96:9 + --> $DIR/rename.rs:98:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` - --> $DIR/rename.rs:97:9 + --> $DIR/rename.rs:99:9 | LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> $DIR/rename.rs:98:9 + --> $DIR/rename.rs:100:9 | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> $DIR/rename.rs:99:9 + --> $DIR/rename.rs:101:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> $DIR/rename.rs:100:9 + --> $DIR/rename.rs:102:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> $DIR/rename.rs:101:9 + --> $DIR/rename.rs:103:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` - --> $DIR/rename.rs:102:9 + --> $DIR/rename.rs:104:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` - --> $DIR/rename.rs:103:9 + --> $DIR/rename.rs:105:9 | LL | #![warn(clippy::undropped_manually_drops)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> $DIR/rename.rs:104:9 + --> $DIR/rename.rs:106:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> $DIR/rename.rs:105:9 + --> $DIR/rename.rs:107:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` -error: aborting due to 53 previous errors +error: aborting due to 54 previous errors diff --git a/tests/ui/unwrap_or_else_default.fixed b/tests/ui/unwrap_or_else_default.fixed index e6b6ab359dfb..89a6b1395e5c 100644 --- a/tests/ui/unwrap_or_else_default.fixed +++ b/tests/ui/unwrap_or_else_default.fixed @@ -1,10 +1,10 @@ //@run-rustfix -#![warn(clippy::unwrap_or_else_default)] +#![warn(clippy::unwrap_or_default)] #![allow(dead_code)] #![allow(clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] -/// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint. +/// Checks implementation of the `UNWRAP_OR_DEFAULT` lint. fn unwrap_or_else_default() { struct Foo; @@ -111,4 +111,21 @@ fn type_certainty(option: Option>) { option.unwrap_or_else(Vec::new).push(1); } +fn method_call_with_deref() { + use std::cell::RefCell; + use std::collections::HashMap; + + let cell = RefCell::new(HashMap::>::new()); + + let mut outer_map = cell.borrow_mut(); + + #[allow(unused_assignments)] + let mut option = None; + option = Some(0); + + let inner_map = outer_map.get_mut(&option.unwrap()).unwrap(); + + let _ = inner_map.entry(0).or_default(); +} + fn main() {} diff --git a/tests/ui/unwrap_or_else_default.rs b/tests/ui/unwrap_or_else_default.rs index 38fa2e4595df..e5ebf35adda3 100644 --- a/tests/ui/unwrap_or_else_default.rs +++ b/tests/ui/unwrap_or_else_default.rs @@ -1,10 +1,10 @@ //@run-rustfix -#![warn(clippy::unwrap_or_else_default)] +#![warn(clippy::unwrap_or_default)] #![allow(dead_code)] #![allow(clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] -/// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint. +/// Checks implementation of the `UNWRAP_OR_DEFAULT` lint. fn unwrap_or_else_default() { struct Foo; @@ -111,4 +111,21 @@ fn type_certainty(option: Option>) { option.unwrap_or_else(Vec::new).push(1); } +fn method_call_with_deref() { + use std::cell::RefCell; + use std::collections::HashMap; + + let cell = RefCell::new(HashMap::>::new()); + + let mut outer_map = cell.borrow_mut(); + + #[allow(unused_assignments)] + let mut option = None; + option = Some(0); + + let inner_map = outer_map.get_mut(&option.unwrap()).unwrap(); + + let _ = inner_map.entry(0).or_insert_with(Default::default); +} + fn main() {} diff --git a/tests/ui/unwrap_or_else_default.stderr b/tests/ui/unwrap_or_else_default.stderr index a6815e8f9169..91e48375f186 100644 --- a/tests/ui/unwrap_or_else_default.stderr +++ b/tests/ui/unwrap_or_else_default.stderr @@ -1,88 +1,94 @@ -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:48:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:48:14 | LL | with_new.unwrap_or_else(Vec::new); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_new.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` | - = note: `-D clippy::unwrap-or-else-default` implied by `-D warnings` + = note: `-D clippy::unwrap-or-default` implied by `-D warnings` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:62:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:62:23 | LL | with_real_default.unwrap_or_else(::default); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_real_default.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:65:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:65:24 | LL | with_default_trait.unwrap_or_else(Default::default); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_default_trait.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:68:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:68:23 | LL | with_default_type.unwrap_or_else(u64::default); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_default_type.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:71:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:71:23 | LL | with_default_type.unwrap_or_else(Vec::new); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_default_type.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:74:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:74:18 | LL | empty_string.unwrap_or_else(|| "".to_string()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `empty_string.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:78:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:78:12 | LL | option.unwrap_or_else(Vec::new).push(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `option.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:81:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:81:12 | LL | option.unwrap_or_else(Vec::new).push(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `option.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:84:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:84:12 | LL | option.unwrap_or_else(Vec::new).push(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `option.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:87:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:87:12 | LL | option.unwrap_or_else(Vec::new).push(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `option.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:90:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:90:12 | LL | option.unwrap_or_else(Vec::new).push(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `option.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:93:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:93:12 | LL | option.unwrap_or_else(Vec::new).push(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `option.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:96:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:96:12 | LL | option.unwrap_or_else(Vec::new).push(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `option.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `.unwrap_or_else(..)` to construct default value - --> $DIR/unwrap_or_else_default.rs:99:5 +error: use of `unwrap_or_else` to construct default value + --> $DIR/unwrap_or_else_default.rs:99:12 | LL | option.unwrap_or_else(Vec::new).push(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `option.unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: aborting due to 14 previous errors +error: use of `or_insert_with` to construct default value + --> $DIR/unwrap_or_else_default.rs:128:32 + | +LL | let _ = inner_map.entry(0).or_insert_with(Default::default); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` + +error: aborting due to 15 previous errors