From 55af14c8c543620fdb9f1226c8266248087b00c1 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 4 Jun 2020 09:11:59 +0700 Subject: [PATCH 1/2] Add test for const fn --- tests/ui/or_fun_call.fixed | 119 ----------------------- tests/ui/or_fun_call.rs | 184 +++++++++++++++++++----------------- tests/ui/or_fun_call.stderr | 82 ---------------- 3 files changed, 95 insertions(+), 290 deletions(-) delete mode 100644 tests/ui/or_fun_call.fixed delete mode 100644 tests/ui/or_fun_call.stderr diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed deleted file mode 100644 index 7bb08797ef39..000000000000 --- a/tests/ui/or_fun_call.fixed +++ /dev/null @@ -1,119 +0,0 @@ -// run-rustfix - -#![warn(clippy::or_fun_call)] -#![allow(dead_code)] - -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::time::Duration; - -/// Checks implementation of the `OR_FUN_CALL` lint. -fn or_fun_call() { - struct Foo; - - impl Foo { - fn new() -> Foo { - Foo - } - } - - enum Enum { - A(i32), - } - - fn make() -> T { - unimplemented!(); - } - - let with_enum = Some(Enum::A(1)); - with_enum.unwrap_or(Enum::A(5)); - - let with_const_fn = Some(Duration::from_secs(1)); - with_const_fn.unwrap_or(Duration::from_secs(5)); - - let with_constructor = Some(vec![1]); - with_constructor.unwrap_or_else(make); - - let with_new = Some(vec![1]); - with_new.unwrap_or_default(); - - let with_const_args = Some(vec![1]); - with_const_args.unwrap_or_else(|| Vec::with_capacity(12)); - - let with_err: Result<_, ()> = Ok(vec![1]); - with_err.unwrap_or_else(|_| make()); - - let with_err_args: Result<_, ()> = Ok(vec![1]); - with_err_args.unwrap_or_else(|_| Vec::with_capacity(12)); - - 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 with_vec = Some(vec![1]); - with_vec.unwrap_or_default(); - - let without_default = Some(Foo); - without_default.unwrap_or_else(Foo::new); - - 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::from("")); - let _ = stringy.unwrap_or_else(|| "".to_owned()); - - let opt = Some(1); - let hello = "Hello"; - let _ = opt.ok_or(format!("{} world.", hello)); -} - -struct Foo(u8); -struct Bar(String, Duration); -#[rustfmt::skip] -fn test_or_with_ctors() { - let opt = Some(1); - let opt_opt = Some(Some(1)); - // we also test for const promotion, this makes sure we don't hit that - let two = 2; - - let _ = opt_opt.unwrap_or(Some(2)); - let _ = opt_opt.unwrap_or(Some(two)); - let _ = opt.ok_or(Some(2)); - let _ = opt.ok_or(Some(two)); - let _ = opt.ok_or(Foo(2)); - let _ = opt.ok_or(Foo(two)); - let _ = opt.or(Some(2)); - let _ = opt.or(Some(two)); - - let _ = Some("a".to_string()).or_else(|| Some("b".to_string())); - - let b = "b".to_string(); - let _ = Some(Bar("a".to_string(), Duration::from_secs(1))) - .or(Some(Bar(b, Duration::from_secs(2)))); - - let vec = vec!["foo"]; - let _ = opt.ok_or(vec.len()); - - let array = ["foo"]; - let _ = opt.ok_or(array.len()); - - let slice = &["foo"][..]; - let _ = opt.ok_or(slice.len()); -} - -// Issue 4514 - early return -fn f() -> Option<()> { - let a = Some(1); - let b = 1i32; - - let _ = a.unwrap_or(b.checked_mul(3)?.min(240)); - - Some(()) -} - -fn main() {} diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 522f31b72d01..494eb287aec3 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -1,119 +1,125 @@ // run-rustfix #![warn(clippy::or_fun_call)] -#![allow(dead_code)] -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::time::Duration; +// use std::collections::BTreeMap; +// use std::collections::HashMap; +// use std::time::Duration; -/// Checks implementation of the `OR_FUN_CALL` lint. -fn or_fun_call() { - struct Foo; +// /// Checks implementation of the `OR_FUN_CALL` lint. +// pub fn or_fun_call() { +// struct Foo; - impl Foo { - fn new() -> Foo { - Foo - } - } +// impl Foo { +// fn new() -> Foo { +// Foo +// } +// } - enum Enum { - A(i32), - } +// enum Enum { +// A(i32), +// } - fn make() -> T { - unimplemented!(); - } +// fn make() -> T { +// unimplemented!(); +// } - let with_enum = Some(Enum::A(1)); - with_enum.unwrap_or(Enum::A(5)); +// let with_enum = Some(Enum::A(1)); +// with_enum.unwrap_or(Enum::A(5)); - let with_const_fn = Some(Duration::from_secs(1)); - with_const_fn.unwrap_or(Duration::from_secs(5)); +// let with_const_fn = Some(Duration::from_secs(1)); +// with_const_fn.unwrap_or(Duration::from_secs(5)); - let with_constructor = Some(vec![1]); - with_constructor.unwrap_or(make()); +// let with_constructor = Some(vec![1]); +// with_constructor.unwrap_or(make()); - let with_new = Some(vec![1]); - with_new.unwrap_or(Vec::new()); +// let with_new = Some(vec![1]); +// with_new.unwrap_or(Vec::new()); - let with_const_args = Some(vec![1]); - with_const_args.unwrap_or(Vec::with_capacity(12)); +// let with_const_args = Some(vec![1]); +// with_const_args.unwrap_or(Vec::with_capacity(12)); - let with_err: Result<_, ()> = Ok(vec![1]); - with_err.unwrap_or(make()); +// let with_err: Result<_, ()> = Ok(vec![1]); +// with_err.unwrap_or(make()); - let with_err_args: Result<_, ()> = Ok(vec![1]); - with_err_args.unwrap_or(Vec::with_capacity(12)); +// let with_err_args: Result<_, ()> = Ok(vec![1]); +// with_err_args.unwrap_or(Vec::with_capacity(12)); - let with_default_trait = Some(1); - with_default_trait.unwrap_or(Default::default()); +// let with_default_trait = Some(1); +// with_default_trait.unwrap_or(Default::default()); - let with_default_type = Some(1); - with_default_type.unwrap_or(u64::default()); +// let with_default_type = Some(1); +// with_default_type.unwrap_or(u64::default()); - let with_vec = Some(vec![1]); - with_vec.unwrap_or(vec![]); +// let with_vec = Some(vec![1]); +// with_vec.unwrap_or(vec![]); - let without_default = Some(Foo); - without_default.unwrap_or(Foo::new()); +// let without_default = Some(Foo); +// without_default.unwrap_or(Foo::new()); - let mut map = HashMap::::new(); - map.entry(42).or_insert(String::new()); +// let mut map = HashMap::::new(); +// map.entry(42).or_insert(String::new()); - let mut btree = BTreeMap::::new(); - btree.entry(42).or_insert(String::new()); +// let mut btree = BTreeMap::::new(); +// btree.entry(42).or_insert(String::new()); - let stringy = Some(String::from("")); - let _ = stringy.unwrap_or("".to_owned()); +// let stringy = Some(String::from("")); +// let _ = stringy.unwrap_or("".to_owned()); - let opt = Some(1); - let hello = "Hello"; - let _ = opt.ok_or(format!("{} world.", hello)); -} +// let opt = Some(1); +// let hello = "Hello"; +// let _ = opt.ok_or(format!("{} world.", hello)); +// } -struct Foo(u8); -struct Bar(String, Duration); -#[rustfmt::skip] -fn test_or_with_ctors() { - let opt = Some(1); - let opt_opt = Some(Some(1)); - // we also test for const promotion, this makes sure we don't hit that - let two = 2; - - let _ = opt_opt.unwrap_or(Some(2)); - let _ = opt_opt.unwrap_or(Some(two)); - let _ = opt.ok_or(Some(2)); - let _ = opt.ok_or(Some(two)); - let _ = opt.ok_or(Foo(2)); - let _ = opt.ok_or(Foo(two)); - let _ = opt.or(Some(2)); - let _ = opt.or(Some(two)); - - let _ = Some("a".to_string()).or(Some("b".to_string())); - - let b = "b".to_string(); - let _ = Some(Bar("a".to_string(), Duration::from_secs(1))) - .or(Some(Bar(b, Duration::from_secs(2)))); - - let vec = vec!["foo"]; - let _ = opt.ok_or(vec.len()); - - let array = ["foo"]; - let _ = opt.ok_or(array.len()); - - let slice = &["foo"][..]; - let _ = opt.ok_or(slice.len()); -} +// struct Foo(u8); +// struct Bar(String, Duration); +// #[rustfmt::skip] +// pub fn test_or_with_ctors() { +// let opt = Some(1); +// let opt_opt = Some(Some(1)); +// // we also test for const promotion, this makes sure we don't hit that +// let two = 2; + +// let _ = opt_opt.unwrap_or(Some(2)); +// let _ = opt_opt.unwrap_or(Some(two)); +// let _ = opt.ok_or(Some(2)); +// let _ = opt.ok_or(Some(two)); +// let _ = opt.ok_or(Foo(2)); +// let _ = opt.ok_or(Foo(two)); +// let _ = opt.or(Some(2)); +// let _ = opt.or(Some(two)); + +// let _ = Some("a".to_string()).or(Some("b".to_string())); -// Issue 4514 - early return -fn f() -> Option<()> { - let a = Some(1); - let b = 1i32; +// let b = "b".to_string(); +// let _ = Some(Bar("a".to_string(), Duration::from_secs(1))) +// .or(Some(Bar(b, Duration::from_secs(2)))); - let _ = a.unwrap_or(b.checked_mul(3)?.min(240)); +// let vec = vec!["foo"]; +// let _ = opt.ok_or(vec.len()); - Some(()) +// let array = ["foo"]; +// let _ = opt.ok_or(array.len()); + +// let slice = &["foo"][..]; +// let _ = opt.ok_or(slice.len()); +// } + +// // Issue 4514 - early return +// pub fn f() -> Option<()> { +// let a = Some(1); +// let b = 1i32; + +// let _ = a.unwrap_or(b.checked_mul(3)?.min(240)); + +// Some(()) +// } + +pub fn skip_const_fn() { + const fn foo(v: i32) -> Option { + Some(v) + } + let _ = None.or(foo(42)); } fn main() {} diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr deleted file mode 100644 index 96d55771e6ce..000000000000 --- a/tests/ui/or_fun_call.stderr +++ /dev/null @@ -1,82 +0,0 @@ -error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:35:22 - | -LL | with_constructor.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` - | - = note: `-D clippy::or-fun-call` implied by `-D warnings` - -error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:38:5 - | -LL | with_new.unwrap_or(Vec::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` - -error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:41:21 - | -LL | with_const_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` - -error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:44:14 - | -LL | with_err.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` - -error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:47:19 - | -LL | with_err_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` - -error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:50:5 - | -LL | with_default_trait.unwrap_or(Default::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` - -error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:53:5 - | -LL | with_default_type.unwrap_or(u64::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` - -error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:56:5 - | -LL | with_vec.unwrap_or(vec![]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_default()` - -error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:59:21 - | -LL | without_default.unwrap_or(Foo::new()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` - -error: use of `or_insert` followed by a function call - --> $DIR/or_fun_call.rs:62:19 - | -LL | map.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` - -error: use of `or_insert` followed by a function call - --> $DIR/or_fun_call.rs:65:21 - | -LL | btree.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` - -error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:68:21 - | -LL | let _ = stringy.unwrap_or("".to_owned()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` - -error: use of `or` followed by a function call - --> $DIR/or_fun_call.rs:93:35 - | -LL | let _ = Some("a".to_string()).or(Some("b".to_string())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))` - -error: aborting due to 13 previous errors - From 48702d3eeedaffaa7bd333c3beb174355a50a25e Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 4 Jun 2020 09:17:24 +0700 Subject: [PATCH 2/2] Ignore const fn in or_fun_call lint --- clippy_lints/src/methods/mod.rs | 7 +- clippy_lints/src/utils/mod.rs | 1 + tests/ui/or_fun_call.fixed | 125 ++++++++++++++++++++++ tests/ui/or_fun_call.rs | 182 ++++++++++++++++---------------- tests/ui/or_fun_call.stderr | 82 ++++++++++++++ 5 files changed, 300 insertions(+), 97 deletions(-) create mode 100644 tests/ui/or_fun_call.fixed create mode 100644 tests/ui/or_fun_call.stderr diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index a9c0ff24fa60..477af3dbd12f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1685,12 +1685,7 @@ fn lint_or_fun_call<'a, 'tcx>( if path.ident.as_str() == "len" { let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0])); - match ty.kind { - ty::Slice(_) | ty::Array(_, _) => return, - _ => (), - } - - if match_type(cx, ty, &paths::VEC) { + if matches!(ty.kind, ty::Slice(_) | ty::Array(..)) || match_type(cx, ty, &paths::VEC) { return; } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 7e07e7751e34..d0acd2b56ccf 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -911,6 +911,7 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_, '_>, expr: &Exp if let ExprKind::Path(ref qp) = fun.kind { let res = cx.tables.qpath_res(qp, fun.hir_id); return match res { + def::Res::Def(DefKind::Fn, def_id) => rustc_mir::const_eval::is_const_fn(cx.tcx, def_id), def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true, def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id), _ => false, diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed new file mode 100644 index 000000000000..576cd1803ec6 --- /dev/null +++ b/tests/ui/or_fun_call.fixed @@ -0,0 +1,125 @@ +// run-rustfix + +#![warn(clippy::or_fun_call)] + +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::time::Duration; + +/// Checks implementation of the `OR_FUN_CALL` lint. +pub fn or_fun_call() { + struct Foo; + + impl Foo { + fn new() -> Foo { + Foo + } + } + + enum Enum { + A(i32), + } + + fn make() -> T { + unimplemented!(); + } + + let with_enum = Some(Enum::A(1)); + with_enum.unwrap_or(Enum::A(5)); + + let with_const_fn = Some(Duration::from_secs(1)); + with_const_fn.unwrap_or(Duration::from_secs(5)); + + let with_constructor = Some(vec![1]); + with_constructor.unwrap_or_else(make); + + let with_new = Some(vec![1]); + with_new.unwrap_or_default(); + + let with_const_args = Some(vec![1]); + with_const_args.unwrap_or_else(|| Vec::with_capacity(12)); + + let with_err: Result<_, ()> = Ok(vec![1]); + with_err.unwrap_or_else(|_| make()); + + let with_err_args: Result<_, ()> = Ok(vec![1]); + with_err_args.unwrap_or_else(|_| Vec::with_capacity(12)); + + 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 with_vec = Some(vec![1]); + with_vec.unwrap_or_default(); + + let without_default = Some(Foo); + without_default.unwrap_or_else(Foo::new); + + 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::from("")); + let _ = stringy.unwrap_or_else(|| "".to_owned()); + + let opt = Some(1); + let hello = "Hello"; + let _ = opt.ok_or(format!("{} world.", hello)); +} + +struct Foo(u8); +struct Bar(String, Duration); +#[rustfmt::skip] +pub fn test_or_with_ctors() { + let opt = Some(1); + let opt_opt = Some(Some(1)); + // we also test for const promotion, this makes sure we don't hit that + let two = 2; + + let _ = opt_opt.unwrap_or(Some(2)); + let _ = opt_opt.unwrap_or(Some(two)); + let _ = opt.ok_or(Some(2)); + let _ = opt.ok_or(Some(two)); + let _ = opt.ok_or(Foo(2)); + let _ = opt.ok_or(Foo(two)); + let _ = opt.or(Some(2)); + let _ = opt.or(Some(two)); + + let _ = Some("a".to_string()).or_else(|| Some("b".to_string())); + + let b = "b".to_string(); + let _ = Some(Bar("a".to_string(), Duration::from_secs(1))) + .or(Some(Bar(b, Duration::from_secs(2)))); + + let vec = vec!["foo"]; + let _ = opt.ok_or(vec.len()); + + let array = ["foo"]; + let _ = opt.ok_or(array.len()); + + let slice = &["foo"][..]; + let _ = opt.ok_or(slice.len()); +} + +// Issue 4514 - early return +pub fn f() -> Option<()> { + let a = Some(1); + let b = 1i32; + + let _ = a.unwrap_or(b.checked_mul(3)?.min(240)); + + Some(()) +} + +pub fn skip_const_fn() { + const fn foo(v: i32) -> Option { + Some(v) + } + let _ = None.or(foo(42)); +} + +fn main() {} diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 494eb287aec3..69a262fee472 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -2,118 +2,118 @@ #![warn(clippy::or_fun_call)] -// use std::collections::BTreeMap; -// use std::collections::HashMap; -// use std::time::Duration; - -// /// Checks implementation of the `OR_FUN_CALL` lint. -// pub fn or_fun_call() { -// struct Foo; - -// impl Foo { -// fn new() -> Foo { -// Foo -// } -// } - -// enum Enum { -// A(i32), -// } - -// fn make() -> T { -// unimplemented!(); -// } - -// let with_enum = Some(Enum::A(1)); -// with_enum.unwrap_or(Enum::A(5)); - -// let with_const_fn = Some(Duration::from_secs(1)); -// with_const_fn.unwrap_or(Duration::from_secs(5)); - -// let with_constructor = Some(vec![1]); -// with_constructor.unwrap_or(make()); - -// let with_new = Some(vec![1]); -// with_new.unwrap_or(Vec::new()); +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::time::Duration; + +/// Checks implementation of the `OR_FUN_CALL` lint. +pub fn or_fun_call() { + struct Foo; + + impl Foo { + fn new() -> Foo { + Foo + } + } -// let with_const_args = Some(vec![1]); -// with_const_args.unwrap_or(Vec::with_capacity(12)); + enum Enum { + A(i32), + } -// let with_err: Result<_, ()> = Ok(vec![1]); -// with_err.unwrap_or(make()); + fn make() -> T { + unimplemented!(); + } -// let with_err_args: Result<_, ()> = Ok(vec![1]); -// with_err_args.unwrap_or(Vec::with_capacity(12)); + let with_enum = Some(Enum::A(1)); + with_enum.unwrap_or(Enum::A(5)); -// let with_default_trait = Some(1); -// with_default_trait.unwrap_or(Default::default()); + let with_const_fn = Some(Duration::from_secs(1)); + with_const_fn.unwrap_or(Duration::from_secs(5)); -// let with_default_type = Some(1); -// with_default_type.unwrap_or(u64::default()); + let with_constructor = Some(vec![1]); + with_constructor.unwrap_or(make()); -// let with_vec = Some(vec![1]); -// with_vec.unwrap_or(vec![]); + let with_new = Some(vec![1]); + with_new.unwrap_or(Vec::new()); -// let without_default = Some(Foo); -// without_default.unwrap_or(Foo::new()); + let with_const_args = Some(vec![1]); + with_const_args.unwrap_or(Vec::with_capacity(12)); -// let mut map = HashMap::::new(); -// map.entry(42).or_insert(String::new()); + let with_err: Result<_, ()> = Ok(vec![1]); + with_err.unwrap_or(make()); -// let mut btree = BTreeMap::::new(); -// btree.entry(42).or_insert(String::new()); + let with_err_args: Result<_, ()> = Ok(vec![1]); + with_err_args.unwrap_or(Vec::with_capacity(12)); -// let stringy = Some(String::from("")); -// let _ = stringy.unwrap_or("".to_owned()); + let with_default_trait = Some(1); + with_default_trait.unwrap_or(Default::default()); -// let opt = Some(1); -// let hello = "Hello"; -// let _ = opt.ok_or(format!("{} world.", hello)); -// } + let with_default_type = Some(1); + with_default_type.unwrap_or(u64::default()); -// struct Foo(u8); -// struct Bar(String, Duration); -// #[rustfmt::skip] -// pub fn test_or_with_ctors() { -// let opt = Some(1); -// let opt_opt = Some(Some(1)); -// // we also test for const promotion, this makes sure we don't hit that -// let two = 2; + let with_vec = Some(vec![1]); + with_vec.unwrap_or(vec![]); -// let _ = opt_opt.unwrap_or(Some(2)); -// let _ = opt_opt.unwrap_or(Some(two)); -// let _ = opt.ok_or(Some(2)); -// let _ = opt.ok_or(Some(two)); -// let _ = opt.ok_or(Foo(2)); -// let _ = opt.ok_or(Foo(two)); -// let _ = opt.or(Some(2)); -// let _ = opt.or(Some(two)); + let without_default = Some(Foo); + without_default.unwrap_or(Foo::new()); -// let _ = Some("a".to_string()).or(Some("b".to_string())); + let mut map = HashMap::::new(); + map.entry(42).or_insert(String::new()); -// let b = "b".to_string(); -// let _ = Some(Bar("a".to_string(), Duration::from_secs(1))) -// .or(Some(Bar(b, Duration::from_secs(2)))); + let mut btree = BTreeMap::::new(); + btree.entry(42).or_insert(String::new()); -// let vec = vec!["foo"]; -// let _ = opt.ok_or(vec.len()); + let stringy = Some(String::from("")); + let _ = stringy.unwrap_or("".to_owned()); -// let array = ["foo"]; -// let _ = opt.ok_or(array.len()); + let opt = Some(1); + let hello = "Hello"; + let _ = opt.ok_or(format!("{} world.", hello)); +} -// let slice = &["foo"][..]; -// let _ = opt.ok_or(slice.len()); -// } +struct Foo(u8); +struct Bar(String, Duration); +#[rustfmt::skip] +pub fn test_or_with_ctors() { + let opt = Some(1); + let opt_opt = Some(Some(1)); + // we also test for const promotion, this makes sure we don't hit that + let two = 2; + + let _ = opt_opt.unwrap_or(Some(2)); + let _ = opt_opt.unwrap_or(Some(two)); + let _ = opt.ok_or(Some(2)); + let _ = opt.ok_or(Some(two)); + let _ = opt.ok_or(Foo(2)); + let _ = opt.ok_or(Foo(two)); + let _ = opt.or(Some(2)); + let _ = opt.or(Some(two)); + + let _ = Some("a".to_string()).or(Some("b".to_string())); + + let b = "b".to_string(); + let _ = Some(Bar("a".to_string(), Duration::from_secs(1))) + .or(Some(Bar(b, Duration::from_secs(2)))); + + let vec = vec!["foo"]; + let _ = opt.ok_or(vec.len()); + + let array = ["foo"]; + let _ = opt.ok_or(array.len()); + + let slice = &["foo"][..]; + let _ = opt.ok_or(slice.len()); +} -// // Issue 4514 - early return -// pub fn f() -> Option<()> { -// let a = Some(1); -// let b = 1i32; +// Issue 4514 - early return +pub fn f() -> Option<()> { + let a = Some(1); + let b = 1i32; -// let _ = a.unwrap_or(b.checked_mul(3)?.min(240)); + let _ = a.unwrap_or(b.checked_mul(3)?.min(240)); -// Some(()) -// } + Some(()) +} pub fn skip_const_fn() { const fn foo(v: i32) -> Option { diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr new file mode 100644 index 000000000000..16755502cd2c --- /dev/null +++ b/tests/ui/or_fun_call.stderr @@ -0,0 +1,82 @@ +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:34:22 + | +LL | with_constructor.unwrap_or(make()); + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` + | + = note: `-D clippy::or-fun-call` implied by `-D warnings` + +error: use of `unwrap_or` followed by a call to `new` + --> $DIR/or_fun_call.rs:37:5 + | +LL | with_new.unwrap_or(Vec::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:40:21 + | +LL | with_const_args.unwrap_or(Vec::with_capacity(12)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:43:14 + | +LL | with_err.unwrap_or(make()); + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:46:19 + | +LL | with_err_args.unwrap_or(Vec::with_capacity(12)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` + +error: use of `unwrap_or` followed by a call to `default` + --> $DIR/or_fun_call.rs:49:5 + | +LL | with_default_trait.unwrap_or(Default::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` + +error: use of `unwrap_or` followed by a call to `default` + --> $DIR/or_fun_call.rs:52:5 + | +LL | with_default_type.unwrap_or(u64::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` + +error: use of `unwrap_or` followed by a call to `new` + --> $DIR/or_fun_call.rs:55:5 + | +LL | with_vec.unwrap_or(vec![]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_default()` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:58:21 + | +LL | without_default.unwrap_or(Foo::new()); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` + +error: use of `or_insert` followed by a function call + --> $DIR/or_fun_call.rs:61:19 + | +LL | map.entry(42).or_insert(String::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` + +error: use of `or_insert` followed by a function call + --> $DIR/or_fun_call.rs:64:21 + | +LL | btree.entry(42).or_insert(String::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:67:21 + | +LL | let _ = stringy.unwrap_or("".to_owned()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` + +error: use of `or` followed by a function call + --> $DIR/or_fun_call.rs:92:35 + | +LL | let _ = Some("a".to_string()).or(Some("b".to_string())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))` + +error: aborting due to 13 previous errors +