From: Oliver Schneider Date: Tue, 10 Oct 2017 08:06:14 +0000 (+0200) Subject: Merge pull request #2126 from camsteffen/split-tests X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=b62b1b68edcdf23a70cb12f31403c80e97f13634;hp=408b5220a8c1df87f314e60b5089d2f0f2759941;p=rust.git Merge pull request #2126 from camsteffen/split-tests Split some UI tests --- diff --git a/tests/ui/cstring.rs b/tests/ui/cstring.rs new file mode 100644 index 00000000000..8b7b0b66bc6 --- /dev/null +++ b/tests/ui/cstring.rs @@ -0,0 +1,8 @@ +fn main() {} + +#[allow(result_unwrap_used)] +fn temporary_cstring() { + use std::ffi::CString; + + CString::new("foo").unwrap().as_ptr(); +} diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr new file mode 100644 index 00000000000..ddb74ce9cac --- /dev/null +++ b/tests/ui/cstring.stderr @@ -0,0 +1,22 @@ +error: function is never used: `temporary_cstring` + --> $DIR/cstring.rs:4:1 + | +4 | fn temporary_cstring() { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D dead-code` implied by `-D warnings` + +error: you are getting the inner pointer of a temporary `CString` + --> $DIR/cstring.rs:7:5 + | +7 | CString::new("foo").unwrap().as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D temporary-cstring-as-ptr` implied by `-D warnings` + = note: that pointer will be invalid outside this expression +help: assign the `CString` to a variable to extend its lifetime + --> $DIR/cstring.rs:7:5 + | +7 | CString::new("foo").unwrap().as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs new file mode 100644 index 00000000000..a10d4d18262 --- /dev/null +++ b/tests/ui/get_unwrap.rs @@ -0,0 +1,46 @@ +#![allow(unused_mut)] + +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::collections::VecDeque; +use std::iter::FromIterator; + +struct GetFalsePositive { + arr: [u32; 3], +} + +impl GetFalsePositive { + fn get(&self, pos: usize) -> Option<&u32> { self.arr.get(pos) } + fn get_mut(&mut self, pos: usize) -> Option<&mut u32> { self.arr.get_mut(pos) } +} + +fn main() { + let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); + let mut some_slice = &mut [0, 1, 2, 3]; + let mut some_vec = vec![0, 1, 2, 3]; + let mut some_vecdeque: VecDeque<_> = some_vec.iter().cloned().collect(); + let mut some_hashmap: HashMap = HashMap::from_iter(vec![(1, 'a'), (2, 'b')]); + let mut some_btreemap: BTreeMap = BTreeMap::from_iter(vec![(1, 'a'), (2, 'b')]); + let mut false_positive = GetFalsePositive { arr: [0, 1, 2] }; + + { // Test `get().unwrap()` + let _ = boxed_slice.get(1).unwrap(); + let _ = some_slice.get(0).unwrap(); + let _ = some_vec.get(0).unwrap(); + let _ = some_vecdeque.get(0).unwrap(); + let _ = some_hashmap.get(&1).unwrap(); + let _ = some_btreemap.get(&1).unwrap(); + let _ = false_positive.get(0).unwrap(); + } + + { // Test `get_mut().unwrap()` + *boxed_slice.get_mut(0).unwrap() = 1; + *some_slice.get_mut(0).unwrap() = 1; + *some_vec.get_mut(0).unwrap() = 1; + *some_vecdeque.get_mut(0).unwrap() = 1; + // Check false positives + *some_hashmap.get_mut(&1).unwrap() = 'b'; + *some_btreemap.get_mut(&1).unwrap() = 'b'; + *false_positive.get_mut(0).unwrap() = 1; + } +} diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr new file mode 100644 index 00000000000..3724cbfc852 --- /dev/null +++ b/tests/ui/get_unwrap.stderr @@ -0,0 +1,62 @@ +error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:27:17 + | +27 | let _ = boxed_slice.get(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` + | + = note: `-D get-unwrap` implied by `-D warnings` + +error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:28:17 + | +28 | let _ = some_slice.get(0).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` + +error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:29:17 + | +29 | let _ = some_vec.get(0).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` + +error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:30:17 + | +30 | let _ = some_vecdeque.get(0).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` + +error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:31:17 + | +31 | let _ = some_hashmap.get(&1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` + +error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:32:17 + | +32 | let _ = some_btreemap.get(&1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` + +error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:37:10 + | +37 | *boxed_slice.get_mut(0).unwrap() = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` + +error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:38:10 + | +38 | *some_slice.get_mut(0).unwrap() = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` + +error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:39:10 + | +39 | *some_vec.get_mut(0).unwrap() = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` + +error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:40:10 + | +40 | *some_vecdeque.get_mut(0).unwrap() = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` + diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 3395280ba05..827d2182cab 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -189,15 +189,6 @@ fn skip(self, _: usize) -> IteratorFalsePositives { } } -#[derive(Copy, Clone)] -struct HasChars; - -impl HasChars { - fn chars(self) -> std::str::Chars<'static> { - "HasChars".chars() - } -} - /// Checks implementation of `FILTER_NEXT` lint fn filter_next() { let v = vec![3, 2, 1, 0, -1, -2, -3]; @@ -358,232 +349,8 @@ fn iter_skip_next() { let _ = foo.filter().skip(42).next(); } -struct GetFalsePositive { - arr: [u32; 3], -} - -impl GetFalsePositive { - fn get(&self, pos: usize) -> Option<&u32> { self.arr.get(pos) } - fn get_mut(&mut self, pos: usize) -> Option<&mut u32> { self.arr.get_mut(pos) } -} - -/// Checks implementation of `GET_UNWRAP` lint -fn get_unwrap() { - let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); - let mut some_slice = &mut [0, 1, 2, 3]; - let mut some_vec = vec![0, 1, 2, 3]; - let mut some_vecdeque: VecDeque<_> = some_vec.iter().cloned().collect(); - let mut some_hashmap: HashMap = HashMap::from_iter(vec![(1, 'a'), (2, 'b')]); - let mut some_btreemap: BTreeMap = BTreeMap::from_iter(vec![(1, 'a'), (2, 'b')]); - let mut false_positive = GetFalsePositive { arr: [0, 1, 2] }; - - { // Test `get().unwrap()` - let _ = boxed_slice.get(1).unwrap(); - let _ = some_slice.get(0).unwrap(); - let _ = some_vec.get(0).unwrap(); - let _ = some_vecdeque.get(0).unwrap(); - let _ = some_hashmap.get(&1).unwrap(); - let _ = some_btreemap.get(&1).unwrap(); - let _ = false_positive.get(0).unwrap(); - } - - { // Test `get_mut().unwrap()` - *boxed_slice.get_mut(0).unwrap() = 1; - *some_slice.get_mut(0).unwrap() = 1; - *some_vec.get_mut(0).unwrap() = 1; - *some_vecdeque.get_mut(0).unwrap() = 1; - // Check false positives - *some_hashmap.get_mut(&1).unwrap() = 'b'; - *some_btreemap.get_mut(&1).unwrap() = 'b'; - *false_positive.get_mut(0).unwrap() = 1; - } -} - - #[allow(similar_names)] fn main() { - use std::io; - let opt = Some(0); let _ = opt.unwrap(); - - let res: Result = Ok(0); - let _ = res.unwrap(); - - res.ok().expect("disaster!"); - // the following should not warn, since `expect` isn't implemented unless - // the error type implements `Debug` - let res2: Result = Ok(0); - res2.ok().expect("oh noes!"); - let res3: Result>= Ok(0); - res3.ok().expect("whoof"); - let res4: Result = Ok(0); - res4.ok().expect("argh"); - let res5: io::Result = Ok(0); - res5.ok().expect("oops"); - let res6: Result = Ok(0); - res6.ok().expect("meh"); -} - -struct MyError(()); // doesn't implement Debug - -#[derive(Debug)] -struct MyErrorWithParam { - x: T -} - -#[allow(unnecessary_operation)] -fn starts_with() { - "".chars().next() == Some(' '); - Some(' ') != "".chars().next(); -} - -fn str_extend_chars() { - let abc = "abc"; - let def = String::from("def"); - let mut s = String::new(); - - s.push_str(abc); - s.extend(abc.chars()); - - s.push_str("abc"); - s.extend("abc".chars()); - - s.push_str(&def); - s.extend(def.chars()); - - s.extend(abc.chars().skip(1)); - s.extend("abc".chars().skip(1)); - s.extend(['a', 'b', 'c'].iter()); - - let f = HasChars; - s.extend(f.chars()); -} - -fn clone_on_copy() { - 42.clone(); - - vec![1].clone(); // ok, not a Copy type - Some(vec![1]).clone(); // ok, not a Copy type - (&42).clone(); -} - -fn clone_on_ref_ptr() { - let rc = Rc::new(true); - let arc = Arc::new(true); - - let rcweak = Rc::downgrade(&rc); - let arc_weak = Arc::downgrade(&arc); - - rc.clone(); - Rc::clone(&rc); - - arc.clone(); - Arc::clone(&arc); - - rcweak.clone(); - rc::Weak::clone(&rcweak); - - arc_weak.clone(); - sync::Weak::clone(&arc_weak); - - -} - -fn clone_on_copy_generic(t: T) { - t.clone(); - - Some(t).clone(); -} - -fn clone_on_double_ref() { - let x = vec![1]; - let y = &&x; - let z: &Vec<_> = y.clone(); - - println!("{:p} {:p}",*y, z); -} - -fn single_char_pattern() { - let x = "foo"; - x.split("x"); - x.split("xx"); - x.split('x'); - - let y = "x"; - x.split(y); - // Not yet testing for multi-byte characters - // Changing `r.len() == 1` to `r.chars().count() == 1` in `lint_single_char_pattern` - // should have done this but produced an ICE - // - // We may not want to suggest changing these anyway - // See: https://github.com/rust-lang-nursery/rust-clippy/issues/650#issuecomment-184328984 - x.split("ß"); - x.split("ℝ"); - x.split("💣"); - // Can't use this lint for unicode code points which don't fit in a char - x.split("❤️"); - x.contains("x"); - x.starts_with("x"); - x.ends_with("x"); - x.find("x"); - x.rfind("x"); - x.rsplit("x"); - x.split_terminator("x"); - x.rsplit_terminator("x"); - x.splitn(0, "x"); - x.rsplitn(0, "x"); - x.matches("x"); - x.rmatches("x"); - x.match_indices("x"); - x.rmatch_indices("x"); - x.trim_left_matches("x"); - x.trim_right_matches("x"); - - let h = HashSet::::new(); - h.contains("X"); // should not warn -} - -#[allow(result_unwrap_used)] -fn temporary_cstring() { - use std::ffi::CString; - - CString::new("foo").unwrap().as_ptr(); -} - -fn iter_clone_collect() { - let v = [1,2,3,4,5]; - let v2 : Vec = v.iter().cloned().collect(); - let v3 : HashSet = v.iter().cloned().collect(); - let v4 : VecDeque = v.iter().cloned().collect(); -} - -fn chars_cmp_with_unwrap() { - let s = String::from("foo"); - if s.chars().next().unwrap() == 'f' { // s.starts_with('f') - // Nothing here - } - if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') - // Nothing here - } - if s.chars().last().unwrap() == 'o' { // s.ends_with('o') - // Nothing here - } - if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') - // Nothing here - } - if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') - // Nothing here - } - if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') - // Nothing here - } -} - -#[allow(unnecessary_operation)] -fn ends_with() { - "".chars().last() == Some(' '); - Some(' ') != "".chars().last(); - "".chars().next_back() == Some(' '); - Some(' ') != "".chars().next_back(); } diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index a1bc219eaf8..167ad8c768e 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -214,654 +214,234 @@ error: unnecessary structure name repetition | ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:206:13 + --> $DIR/methods.rs:197:13 | -206 | let _ = v.iter().filter(|&x| *x < 0).next(); +197 | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D 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:209:13 + --> $DIR/methods.rs:200:13 | -209 | let _ = v.iter().filter(|&x| { +200 | let _ = v.iter().filter(|&x| { | _____________^ -210 | | *x < 0 -211 | | } -212 | | ).next(); +201 | | *x < 0 +202 | | } +203 | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:224:13 + --> $DIR/methods.rs:215:13 | -224 | let _ = v.iter().find(|&x| *x < 0).is_some(); +215 | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D search-is-some` implied by `-D warnings` = note: replace `find(|&x| *x < 0).is_some()` with `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:227:13 + --> $DIR/methods.rs:218:13 | -227 | let _ = v.iter().find(|&x| { +218 | let _ = v.iter().find(|&x| { | _____________^ -228 | | *x < 0 -229 | | } -230 | | ).is_some(); +219 | | *x < 0 +220 | | } +221 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:233:13 + --> $DIR/methods.rs:224:13 | -233 | let _ = v.iter().position(|&x| x < 0).is_some(); +224 | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `position(|&x| x < 0).is_some()` with `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:236:13 + --> $DIR/methods.rs:227:13 | -236 | let _ = v.iter().position(|&x| { +227 | let _ = v.iter().position(|&x| { | _____________^ -237 | | x < 0 -238 | | } -239 | | ).is_some(); +228 | | x < 0 +229 | | } +230 | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:242:13 + --> $DIR/methods.rs:233:13 | -242 | let _ = v.iter().rposition(|&x| x < 0).is_some(); +233 | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: replace `rposition(|&x| x < 0).is_some()` with `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:245:13 + --> $DIR/methods.rs:236:13 | -245 | let _ = v.iter().rposition(|&x| { +236 | let _ = v.iter().rposition(|&x| { | _____________^ -246 | | x < 0 -247 | | } -248 | | ).is_some(); +237 | | x < 0 +238 | | } +239 | | ).is_some(); | |______________________________^ error: unnecessary structure name repetition - --> $DIR/methods.rs:262:21 + --> $DIR/methods.rs:253:21 | -262 | fn new() -> Foo { Foo } +253 | fn new() -> Foo { Foo } | ^^^ help: use the applicable keyword: `Self` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:280:5 + --> $DIR/methods.rs:271:5 | -280 | with_constructor.unwrap_or(make()); +271 | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_constructor.unwrap_or_else(make)` | = note: `-D or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:283:5 + --> $DIR/methods.rs:274:5 | -283 | with_new.unwrap_or(Vec::new()); +274 | 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/methods.rs:286:5 + --> $DIR/methods.rs:277:5 | -286 | with_const_args.unwrap_or(Vec::with_capacity(12)); +277 | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_const_args.unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:289:5 + --> $DIR/methods.rs:280:5 | -289 | with_err.unwrap_or(make()); +280 | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err.unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:292:5 + --> $DIR/methods.rs:283:5 | -292 | with_err_args.unwrap_or(Vec::with_capacity(12)); +283 | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_err_args.unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:295:5 + --> $DIR/methods.rs:286:5 | -295 | with_default_trait.unwrap_or(Default::default()); +286 | 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/methods.rs:298:5 + --> $DIR/methods.rs:289:5 | -298 | with_default_type.unwrap_or(u64::default()); +289 | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:301:5 + --> $DIR/methods.rs:292:5 | -301 | with_vec.unwrap_or(vec![]); +292 | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:306:5 + --> $DIR/methods.rs:297:5 | -306 | without_default.unwrap_or(Foo::new()); +297 | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `without_default.unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:309:5 + --> $DIR/methods.rs:300:5 | -309 | map.entry(42).or_insert(String::new()); +300 | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `map.entry(42).or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:312:5 + --> $DIR/methods.rs:303:5 | -312 | btree.entry(42).or_insert(String::new()); +303 | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `btree.entry(42).or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:315:13 + --> $DIR/methods.rs:306:13 | -315 | let _ = stringy.unwrap_or("".to_owned()); +306 | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `stringy.unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:326:23 + --> $DIR/methods.rs:317:23 | -326 | let bad_vec = some_vec.iter().nth(3); +317 | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:327:26 + --> $DIR/methods.rs:318:26 | -327 | let bad_slice = &some_vec[..].iter().nth(3); +318 | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:328:31 + --> $DIR/methods.rs:319:31 | -328 | let bad_boxed_slice = boxed_slice.iter().nth(3); +319 | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:329:29 + --> $DIR/methods.rs:320:29 | -329 | let bad_vec_deque = some_vec_deque.iter().nth(3); +320 | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:334:23 + --> $DIR/methods.rs:325:23 | -334 | let bad_vec = some_vec.iter_mut().nth(3); +325 | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:337:26 + --> $DIR/methods.rs:328:26 | -337 | let bad_slice = &some_vec[..].iter_mut().nth(3); +328 | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:340:29 + --> $DIR/methods.rs:331:29 | -340 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); +331 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:352:13 + --> $DIR/methods.rs:343:13 | -352 | let _ = some_vec.iter().skip(42).next(); +343 | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:353:13 + --> $DIR/methods.rs:344:13 | -353 | let _ = some_vec.iter().cycle().skip(42).next(); +344 | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:354:13 + --> $DIR/methods.rs:345:13 | -354 | let _ = (1..10).skip(10).next(); +345 | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/methods.rs:355:14 + --> $DIR/methods.rs:346:14 | -355 | let _ = &some_vec[..].iter().skip(3).next(); +346 | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:381:17 - | -381 | let _ = boxed_slice.get(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` - | - = note: `-D get-unwrap` implied by `-D warnings` - -error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:382:17 - | -382 | let _ = some_slice.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` - -error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:383:17 - | -383 | let _ = some_vec.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` - -error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:384:17 - | -384 | let _ = some_vecdeque.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` - -error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:385:17 - | -385 | let _ = some_hashmap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` - -error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/methods.rs:386:17 - | -386 | let _ = some_btreemap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` - -error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:391:10 - | -391 | *boxed_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut boxed_slice[0]` - -error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/methods.rs:392:10 - | -392 | *some_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_slice[0]` - -error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/methods.rs:393:10 - | -393 | *some_vec.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vec[0]` - -error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/methods.rs:394:10 - | -394 | *some_vecdeque.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut some_vecdeque[0]` - error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:408:13 + --> $DIR/methods.rs:355:13 | -408 | let _ = opt.unwrap(); +355 | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D option-unwrap-used` implied by `-D warnings` -error: used unwrap() on a Result value. If you don't want to handle the Err case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:411:13 - | -411 | let _ = res.unwrap(); - | ^^^^^^^^^^^^ - | - = note: `-D result-unwrap-used` implied by `-D warnings` - -error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:413:5 - | -413 | res.ok().expect("disaster!"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D ok-expect` implied by `-D warnings` - -error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:419:5 - | -419 | res3.ok().expect("whoof"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:421:5 - | -421 | res4.ok().expect("argh"); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:423:5 - | -423 | res5.ok().expect("oops"); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` - --> $DIR/methods.rs:425:5 - | -425 | res6.ok().expect("meh"); - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `starts_with` method - --> $DIR/methods.rs:437:5 - | -437 | "".chars().next() == Some(' '); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` - | - = note: `-D chars-next-cmp` implied by `-D warnings` - -error: you should use the `starts_with` method - --> $DIR/methods.rs:438:5 - | -438 | Some(' ') != "".chars().next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` - -error: calling `.extend(_.chars())` - --> $DIR/methods.rs:447:5 - | -447 | s.extend(abc.chars()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` - | - = note: `-D string-extend-chars` implied by `-D warnings` - -error: calling `.extend(_.chars())` - --> $DIR/methods.rs:450:5 - | -450 | s.extend("abc".chars()); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` - -error: calling `.extend(_.chars())` - --> $DIR/methods.rs:453:5 - | -453 | s.extend(def.chars()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` - -error: using `clone` on a `Copy` type - --> $DIR/methods.rs:464:5 - | -464 | 42.clone(); - | ^^^^^^^^^^ help: try removing the `clone` call: `42` - | - = note: `-D clone-on-copy` implied by `-D warnings` - -error: using `clone` on a `Copy` type - --> $DIR/methods.rs:468:5 - | -468 | (&42).clone(); - | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` - -error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:478:5 - | -478 | rc.clone(); - | ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` - | - = note: `-D clone-on-ref-ptr` implied by `-D warnings` - -error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:481:5 - | -481 | arc.clone(); - | ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` - -error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:484:5 - | -484 | rcweak.clone(); - | ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` - -error: using '.clone()' on a ref-counted pointer - --> $DIR/methods.rs:487:5 - | -487 | arc_weak.clone(); - | ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` - -error: using `clone` on a `Copy` type - --> $DIR/methods.rs:494:5 - | -494 | t.clone(); - | ^^^^^^^^^ help: try removing the `clone` call: `t` - -error: using `clone` on a `Copy` type - --> $DIR/methods.rs:496:5 - | -496 | Some(t).clone(); - | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` - -error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/methods.rs:502:22 - | -502 | let z: &Vec<_> = y.clone(); - | ^^^^^^^^^ help: try dereferencing it: `(*y).clone()` - | - = note: `-D clone-double-ref` implied by `-D warnings` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:509:13 - | -509 | x.split("x"); - | --------^^^- help: try using a char instead: `x.split('x')` - | - = note: `-D single-char-pattern` implied by `-D warnings` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:526:16 - | -526 | x.contains("x"); - | -----------^^^- help: try using a char instead: `x.contains('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:527:19 - | -527 | x.starts_with("x"); - | --------------^^^- help: try using a char instead: `x.starts_with('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:528:17 - | -528 | x.ends_with("x"); - | ------------^^^- help: try using a char instead: `x.ends_with('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:529:12 - | -529 | x.find("x"); - | -------^^^- help: try using a char instead: `x.find('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:530:13 - | -530 | x.rfind("x"); - | --------^^^- help: try using a char instead: `x.rfind('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:531:14 - | -531 | x.rsplit("x"); - | ---------^^^- help: try using a char instead: `x.rsplit('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:532:24 - | -532 | x.split_terminator("x"); - | -------------------^^^- help: try using a char instead: `x.split_terminator('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:533:25 - | -533 | x.rsplit_terminator("x"); - | --------------------^^^- help: try using a char instead: `x.rsplit_terminator('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:534:17 - | -534 | x.splitn(0, "x"); - | ------------^^^- help: try using a char instead: `x.splitn(0, 'x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:535:18 - | -535 | x.rsplitn(0, "x"); - | -------------^^^- help: try using a char instead: `x.rsplitn(0, 'x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:536:15 - | -536 | x.matches("x"); - | ----------^^^- help: try using a char instead: `x.matches('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:537:16 - | -537 | x.rmatches("x"); - | -----------^^^- help: try using a char instead: `x.rmatches('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:538:21 - | -538 | x.match_indices("x"); - | ----------------^^^- help: try using a char instead: `x.match_indices('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:539:22 - | -539 | x.rmatch_indices("x"); - | -----------------^^^- help: try using a char instead: `x.rmatch_indices('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:540:25 - | -540 | x.trim_left_matches("x"); - | --------------------^^^- help: try using a char instead: `x.trim_left_matches('x')` - -error: single-character string constant used as pattern - --> $DIR/methods.rs:541:26 - | -541 | x.trim_right_matches("x"); - | ---------------------^^^- help: try using a char instead: `x.trim_right_matches('x')` - -error: you are getting the inner pointer of a temporary `CString` - --> $DIR/methods.rs:551:5 - | -551 | CString::new("foo").unwrap().as_ptr(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D temporary-cstring-as-ptr` implied by `-D warnings` - = note: that pointer will be invalid outside this expression -help: assign the `CString` to a variable to extend its lifetime - --> $DIR/methods.rs:551:5 - | -551 | CString::new("foo").unwrap().as_ptr(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/methods.rs:556:27 - | -556 | let v2 : Vec = v.iter().cloned().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D iter-cloned-collect` implied by `-D warnings` - -error: you should use the `starts_with` method - --> $DIR/methods.rs:563:8 - | -563 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:563:8 - | -563 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `ends_with` method - --> $DIR/methods.rs:566:8 - | -566 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` - | - = note: `-D chars-last-cmp` implied by `-D warnings` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:566:8 - | -566 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `ends_with` method - --> $DIR/methods.rs:569:8 - | -569 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:569:8 - | -569 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `starts_with` method - --> $DIR/methods.rs:572:8 - | -572 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:572:8 - | -572 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `ends_with` method - --> $DIR/methods.rs:575:8 - | -575 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:575:8 - | -575 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `ends_with` method - --> $DIR/methods.rs:578:8 - | -578 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` - -error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:578:8 - | -578 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should use the `ends_with` method - --> $DIR/methods.rs:585:5 - | -585 | "".chars().last() == Some(' '); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` - -error: you should use the `ends_with` method - --> $DIR/methods.rs:586:5 - | -586 | Some(' ') != "".chars().last(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` - -error: you should use the `ends_with` method - --> $DIR/methods.rs:587:5 - | -587 | "".chars().next_back() == Some(' '); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` - -error: you should use the `ends_with` method - --> $DIR/methods.rs:588:5 - | -588 | Some(' ') != "".chars().next_back(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` - diff --git a/tests/ui/ok_expect.rs b/tests/ui/ok_expect.rs new file mode 100644 index 00000000000..4341e8ea70b --- /dev/null +++ b/tests/ui/ok_expect.rs @@ -0,0 +1,27 @@ +use std::io; + +struct MyError(()); // doesn't implement Debug + +#[derive(Debug)] +struct MyErrorWithParam { + x: T +} + +fn main() { + let res: Result = Ok(0); + let _ = res.unwrap(); + + res.ok().expect("disaster!"); + // the following should not warn, since `expect` isn't implemented unless + // the error type implements `Debug` + let res2: Result = Ok(0); + res2.ok().expect("oh noes!"); + let res3: Result>= Ok(0); + res3.ok().expect("whoof"); + let res4: Result = Ok(0); + res4.ok().expect("argh"); + let res5: io::Result = Ok(0); + res5.ok().expect("oops"); + let res6: Result = Ok(0); + res6.ok().expect("meh"); +} diff --git a/tests/ui/ok_expect.stderr b/tests/ui/ok_expect.stderr new file mode 100644 index 00000000000..79b09b3fa8a --- /dev/null +++ b/tests/ui/ok_expect.stderr @@ -0,0 +1,32 @@ +error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` + --> $DIR/ok_expect.rs:14:5 + | +14 | res.ok().expect("disaster!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D ok-expect` implied by `-D warnings` + +error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` + --> $DIR/ok_expect.rs:20:5 + | +20 | res3.ok().expect("whoof"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` + --> $DIR/ok_expect.rs:22:5 + | +22 | res4.ok().expect("argh"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` + --> $DIR/ok_expect.rs:24:5 + | +24 | res5.ok().expect("oops"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `ok().expect()` on a Result value. You can call `expect` directly on the `Result` + --> $DIR/ok_expect.rs:26:5 + | +26 | res6.ok().expect("meh"); + | ^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs new file mode 100644 index 00000000000..948a8ff0e41 --- /dev/null +++ b/tests/ui/single_char_pattern.rs @@ -0,0 +1,41 @@ +use std::collections::HashSet; + +fn main() { + let x = "foo"; + x.split("x"); + x.split("xx"); + x.split('x'); + + let y = "x"; + x.split(y); + // Not yet testing for multi-byte characters + // Changing `r.len() == 1` to `r.chars().count() == 1` in `lint_single_char_pattern` + // should have done this but produced an ICE + // + // We may not want to suggest changing these anyway + // See: https://github.com/rust-lang-nursery/rust-clippy/issues/650#issuecomment-184328984 + x.split("ß"); + x.split("ℝ"); + x.split("💣"); + // Can't use this lint for unicode code points which don't fit in a char + x.split("❤️"); + x.contains("x"); + x.starts_with("x"); + x.ends_with("x"); + x.find("x"); + x.rfind("x"); + x.rsplit("x"); + x.split_terminator("x"); + x.rsplit_terminator("x"); + x.splitn(0, "x"); + x.rsplitn(0, "x"); + x.matches("x"); + x.rmatches("x"); + x.match_indices("x"); + x.rmatch_indices("x"); + x.trim_left_matches("x"); + x.trim_right_matches("x"); + + let h = HashSet::::new(); + h.contains("X"); // should not warn +} diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr new file mode 100644 index 00000000000..d5f21f210a3 --- /dev/null +++ b/tests/ui/single_char_pattern.stderr @@ -0,0 +1,104 @@ +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:5:13 + | +5 | x.split("x"); + | --------^^^- help: try using a char instead: `x.split('x')` + | + = note: `-D single-char-pattern` implied by `-D warnings` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:22:16 + | +22 | x.contains("x"); + | -----------^^^- help: try using a char instead: `x.contains('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:23:19 + | +23 | x.starts_with("x"); + | --------------^^^- help: try using a char instead: `x.starts_with('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:24:17 + | +24 | x.ends_with("x"); + | ------------^^^- help: try using a char instead: `x.ends_with('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:25:12 + | +25 | x.find("x"); + | -------^^^- help: try using a char instead: `x.find('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:26:13 + | +26 | x.rfind("x"); + | --------^^^- help: try using a char instead: `x.rfind('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:27:14 + | +27 | x.rsplit("x"); + | ---------^^^- help: try using a char instead: `x.rsplit('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:28:24 + | +28 | x.split_terminator("x"); + | -------------------^^^- help: try using a char instead: `x.split_terminator('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:29:25 + | +29 | x.rsplit_terminator("x"); + | --------------------^^^- help: try using a char instead: `x.rsplit_terminator('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:30:17 + | +30 | x.splitn(0, "x"); + | ------------^^^- help: try using a char instead: `x.splitn(0, 'x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:31:18 + | +31 | x.rsplitn(0, "x"); + | -------------^^^- help: try using a char instead: `x.rsplitn(0, 'x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:32:15 + | +32 | x.matches("x"); + | ----------^^^- help: try using a char instead: `x.matches('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:33:16 + | +33 | x.rmatches("x"); + | -----------^^^- help: try using a char instead: `x.rmatches('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:34:21 + | +34 | x.match_indices("x"); + | ----------------^^^- help: try using a char instead: `x.match_indices('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:35:22 + | +35 | x.rmatch_indices("x"); + | -----------------^^^- help: try using a char instead: `x.rmatch_indices('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:36:25 + | +36 | x.trim_left_matches("x"); + | --------------------^^^- help: try using a char instead: `x.trim_left_matches('x')` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:37:26 + | +37 | x.trim_right_matches("x"); + | ---------------------^^^- help: try using a char instead: `x.trim_right_matches('x')` + diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs new file mode 100644 index 00000000000..d47c8a5b076 --- /dev/null +++ b/tests/ui/starts_ends_with.rs @@ -0,0 +1,39 @@ +#![allow(dead_code)] + +fn main() {} + +#[allow(unnecessary_operation)] +fn starts_with() { + "".chars().next() == Some(' '); + Some(' ') != "".chars().next(); +} + +fn chars_cmp_with_unwrap() { + let s = String::from("foo"); + if s.chars().next().unwrap() == 'f' { // s.starts_with('f') + // Nothing here + } + if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') + // Nothing here + } + if s.chars().last().unwrap() == 'o' { // s.ends_with('o') + // Nothing here + } + if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') + // Nothing here + } + if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') + // Nothing here + } + if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') + // Nothing here + } +} + +#[allow(unnecessary_operation)] +fn ends_with() { + "".chars().last() == Some(' '); + Some(' ') != "".chars().last(); + "".chars().next_back() == Some(' '); + Some(' ') != "".chars().next_back(); +} diff --git a/tests/ui/starts_ends_with.stderr b/tests/ui/starts_ends_with.stderr new file mode 100644 index 00000000000..c67cc8a86ea --- /dev/null +++ b/tests/ui/starts_ends_with.stderr @@ -0,0 +1,76 @@ +error: you should use the `starts_with` method + --> $DIR/starts_ends_with.rs:7:5 + | +7 | "".chars().next() == Some(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with(' ')` + | + = note: `-D chars-next-cmp` implied by `-D warnings` + +error: you should use the `starts_with` method + --> $DIR/starts_ends_with.rs:8:5 + | +8 | Some(' ') != "".chars().next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` + +error: you should use the `starts_with` method + --> $DIR/starts_ends_with.rs:13:8 + | +13 | if s.chars().next().unwrap() == 'f' { // s.starts_with('f') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:16:8 + | +16 | if s.chars().next_back().unwrap() == 'o' { // s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` + | + = note: `-D chars-last-cmp` implied by `-D warnings` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:19:8 + | +19 | if s.chars().last().unwrap() == 'o' { // s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` + +error: you should use the `starts_with` method + --> $DIR/starts_ends_with.rs:22:8 + | +22 | if s.chars().next().unwrap() != 'f' { // !s.starts_with('f') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:25:8 + | +25 | if s.chars().next_back().unwrap() != 'o' { // !s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:28:8 + | +28 | if s.chars().last().unwrap() != 'o' { // !s.ends_with('o') + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:35:5 + | +35 | "".chars().last() == Some(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:36:5 + | +36 | Some(' ') != "".chars().last(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:37:5 + | +37 | "".chars().next_back() == Some(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` + +error: you should use the `ends_with` method + --> $DIR/starts_ends_with.rs:38:5 + | +38 | Some(' ') != "".chars().next_back(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` + diff --git a/tests/ui/string_extend.rs b/tests/ui/string_extend.rs new file mode 100644 index 00000000000..d99adb19f89 --- /dev/null +++ b/tests/ui/string_extend.rs @@ -0,0 +1,30 @@ +#[derive(Copy, Clone)] +struct HasChars; + +impl HasChars { + fn chars(self) -> std::str::Chars<'static> { + "HasChars".chars() + } +} + +fn main() { + let abc = "abc"; + let def = String::from("def"); + let mut s = String::new(); + + s.push_str(abc); + s.extend(abc.chars()); + + s.push_str("abc"); + s.extend("abc".chars()); + + s.push_str(&def); + s.extend(def.chars()); + + s.extend(abc.chars().skip(1)); + s.extend("abc".chars().skip(1)); + s.extend(['a', 'b', 'c'].iter()); + + let f = HasChars; + s.extend(f.chars()); +} diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr new file mode 100644 index 00000000000..1f6d9400743 --- /dev/null +++ b/tests/ui/string_extend.stderr @@ -0,0 +1,20 @@ +error: calling `.extend(_.chars())` + --> $DIR/string_extend.rs:16:5 + | +16 | s.extend(abc.chars()); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` + | + = note: `-D string-extend-chars` implied by `-D warnings` + +error: calling `.extend(_.chars())` + --> $DIR/string_extend.rs:19:5 + | +19 | s.extend("abc".chars()); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` + +error: calling `.extend(_.chars())` + --> $DIR/string_extend.rs:22:5 + | +22 | s.extend(def.chars()); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` + diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs new file mode 100644 index 00000000000..f33def9eb4e --- /dev/null +++ b/tests/ui/unnecessary_clone.rs @@ -0,0 +1,59 @@ +#![allow(unused)] + +use std::collections::HashSet; +use std::collections::VecDeque; +use std::rc::{self, Rc}; +use std::sync::{self, Arc}; + +fn main() {} + +fn clone_on_copy() { + 42.clone(); + + vec![1].clone(); // ok, not a Copy type + Some(vec![1]).clone(); // ok, not a Copy type + (&42).clone(); +} + +fn clone_on_ref_ptr() { + let rc = Rc::new(true); + let arc = Arc::new(true); + + let rcweak = Rc::downgrade(&rc); + let arc_weak = Arc::downgrade(&arc); + + rc.clone(); + Rc::clone(&rc); + + arc.clone(); + Arc::clone(&arc); + + rcweak.clone(); + rc::Weak::clone(&rcweak); + + arc_weak.clone(); + sync::Weak::clone(&arc_weak); + + +} + +fn clone_on_copy_generic(t: T) { + t.clone(); + + Some(t).clone(); +} + +fn clone_on_double_ref() { + let x = vec![1]; + let y = &&x; + let z: &Vec<_> = y.clone(); + + println!("{:p} {:p}",*y, z); +} + +fn iter_clone_collect() { + let v = [1,2,3,4,5]; + let v2 : Vec = v.iter().cloned().collect(); + let v3 : HashSet = v.iter().cloned().collect(); + let v4 : VecDeque = v.iter().cloned().collect(); +} diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr new file mode 100644 index 00000000000..17263756980 --- /dev/null +++ b/tests/ui/unnecessary_clone.stderr @@ -0,0 +1,68 @@ +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:11:5 + | +11 | 42.clone(); + | ^^^^^^^^^^ help: try removing the `clone` call: `42` + | + = note: `-D clone-on-copy` implied by `-D warnings` + +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:15:5 + | +15 | (&42).clone(); + | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/unnecessary_clone.rs:25:5 + | +25 | rc.clone(); + | ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` + | + = note: `-D clone-on-ref-ptr` implied by `-D warnings` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/unnecessary_clone.rs:28:5 + | +28 | arc.clone(); + | ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/unnecessary_clone.rs:31:5 + | +31 | rcweak.clone(); + | ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` + +error: using '.clone()' on a ref-counted pointer + --> $DIR/unnecessary_clone.rs:34:5 + | +34 | arc_weak.clone(); + | ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` + +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:41:5 + | +41 | t.clone(); + | ^^^^^^^^^ help: try removing the `clone` call: `t` + +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:43:5 + | +43 | Some(t).clone(); + | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` + +error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type + --> $DIR/unnecessary_clone.rs:49:22 + | +49 | let z: &Vec<_> = y.clone(); + | ^^^^^^^^^ help: try dereferencing it: `(*y).clone()` + | + = note: `-D clone-double-ref` implied by `-D warnings` + +error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable + --> $DIR/unnecessary_clone.rs:56:27 + | +56 | let v2 : Vec = v.iter().cloned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D iter-cloned-collect` implied by `-D warnings` +