Auto merge of - uHOOCCOOHu:fix/async_fn_lifetime, r=flip1995

Ignore generated fresh lifetimes in elision check

<!--
Thank you for making Clippy better!

We're collecting our changelog from pull request descriptions.
If your PR only updates to the latest nightly, you can leave the
`changelog` entry as `none`. Otherwise, please write a short comment
explaining your change.

If your PR fixes an issue, you can add "fixes #issue_number" into this
PR description. This way the issue will be automatically closed when
your PR is merged.

If you added a new lint, here's a checklist for things that will be
checked during review or continuous integration.

- [ ] Followed [lint naming conventions][lint_naming]
- [ ] Added passing UI tests (including committed `.stderr` file)
- [ ] `cargo test` passes locally
- [ ] Executed `util/dev update_lints`
- [ ] Added lint documentation
- [ ] Run `cargo fmt`

Note that you can skip the above if you are just opening a WIP PR in
order to get feedback.

Delete this line and everything above before opening your PR -->

fixes 

changelog: Ignore generated fresh lifetimes in elision check.

**HELP**: It seems `tests/ui` are compiled under edition 2015, and I don't know how to add tests for this properly.

Here is the test input it had already passed:
```rust
#![feature(async_await)]
#![allow(dead_code)]

async fn sink1<'a>(_: &'a str) {} // lint
async fn sink1_elided(_: &str) {} // ok

async fn one_to_one<'a>(s: &'a str) -> &'a str { s } // lint
async fn one_to_one_elided(s: &str) -> &str { s } // ok
async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str { a } // ok
// async fn unrelated(_: &str, _: &str) {} // Not allowed in async fn

// 
struct Foo;
impl Foo {
    pub async fn foo(&mut self) {} // ok
}

// 
async fn print(s: &str) { // ok
    println!("{}", s);
}

fn main() {}

```
This commit is contained in:
bors 2019-07-23 09:52:18 +00:00
commit d71e9c4f10
12 changed files with 86 additions and 28 deletions

@ -283,6 +283,8 @@ impl<'v, 't> RefVisitor<'v, 't> {
if let Some(ref lt) = *lifetime {
if lt.name == LifetimeName::Static {
self.lts.push(RefLt::Static);
} else if let LifetimeName::Param(ParamName::Fresh(_)) = lt.name {
// Fresh lifetimes generated should be ignored.
} else if lt.is_elided() {
self.lts.push(RefLt::Unnamed);
} else {

@ -2,5 +2,5 @@ max_width = 120
comment_width = 100
match_block_trailing_comma = true
wrap_comments = true
edition = "2018"
error_on_line_overflow = true

@ -313,7 +313,7 @@ fn mcarton_sees_all() {
}
#[clippy::cognitive_complexity = "0"]
fn try() -> Result<i32, &'static str> {
fn try_() -> Result<i32, &'static str> {
match 5 {
5 => Ok(5),
_ => return Err("bla"),
@ -322,14 +322,14 @@ fn try() -> Result<i32, &'static str> {
#[clippy::cognitive_complexity = "0"]
fn try_again() -> Result<i32, &'static str> {
let _ = try!(Ok(42));
let _ = try!(Ok(43));
let _ = try!(Ok(44));
let _ = try!(Ok(45));
let _ = try!(Ok(46));
let _ = try!(Ok(47));
let _ = try!(Ok(48));
let _ = try!(Ok(49));
let _ = r#try!(Ok(42));
let _ = r#try!(Ok(43));
let _ = r#try!(Ok(44));
let _ = r#try!(Ok(45));
let _ = r#try!(Ok(46));
let _ = r#try!(Ok(47));
let _ = r#try!(Ok(48));
let _ = r#try!(Ok(49));
match 5 {
5 => Ok(5),
_ => return Err("bla"),

@ -216,7 +216,7 @@ LL | | }
error: the function has a cognitive complexity of 1
--> $DIR/cognitive_complexity.rs:316:1
|
LL | / fn try() -> Result<i32, &'static str> {
LL | / fn try_() -> Result<i32, &'static str> {
LL | | match 5 {
LL | | 5 => Ok(5),
LL | | _ => return Err("bla"),
@ -230,9 +230,9 @@ error: the function has a cognitive complexity of 1
--> $DIR/cognitive_complexity.rs:324:1
|
LL | / fn try_again() -> Result<i32, &'static str> {
LL | | let _ = try!(Ok(42));
LL | | let _ = try!(Ok(43));
LL | | let _ = try!(Ok(44));
LL | | let _ = r#try!(Ok(42));
LL | | let _ = r#try!(Ok(43));
LL | | let _ = r#try!(Ok(44));
... |
LL | | }
LL | | }

@ -7,7 +7,7 @@ use alloc::collections::linked_list::LinkedList;
trait Foo {
type Baz = LinkedList<u8>;
fn foo(LinkedList<u8>);
fn foo(_: LinkedList<u8>);
const BAR: Option<LinkedList<u8>>;
}

@ -8,10 +8,10 @@ LL | type Baz = LinkedList<u8>;
= help: a VecDeque might work
error: I see you're using a LinkedList! Perhaps you meant some other data structure?
--> $DIR/dlist.rs:10:12
--> $DIR/dlist.rs:10:15
|
LL | fn foo(LinkedList<u8>);
| ^^^^^^^^^^^^^^
LL | fn foo(_: LinkedList<u8>);
| ^^^^^^^^^^^^^^
|
= help: a VecDeque might work

@ -215,10 +215,10 @@ fn if_same_then_else() -> Result<&'static str, ()> {
};
if true {
try!(Ok("foo"));
r#try!(Ok("foo"));
} else {
//~ ERROR same body as `if` block
try!(Ok("foo"));
r#try!(Ok("foo"));
}
if true {

@ -197,7 +197,7 @@ error: this `if` has identical blocks
LL | } else {
| ____________^
LL | | //~ ERROR same body as `if` block
LL | | try!(Ok("foo"));
LL | | r#try!(Ok("foo"));
LL | | }
| |_____^
|
@ -206,7 +206,7 @@ note: same as this
|
LL | if true {
| _____________^
LL | | try!(Ok("foo"));
LL | | r#try!(Ok("foo"));
LL | | } else {
| |_____^

38
tests/ui/issue_4266.rs Normal file

@ -0,0 +1,38 @@
// compile-flags: --edition 2018
#![feature(async_await)]
#![allow(dead_code)]
async fn sink1<'a>(_: &'a str) {} // lint
async fn sink1_elided(_: &str) {} // ok
// lint
async fn one_to_one<'a>(s: &'a str) -> &'a str {
s
}
// ok
async fn one_to_one_elided(s: &str) -> &str {
s
}
// ok
async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str {
a
}
// async fn unrelated(_: &str, _: &str) {} // Not allowed in async fn
// #3988
struct Foo;
impl Foo {
// ok
pub async fn foo(&mut self) {}
}
// rust-lang/rust#61115
// ok
async fn print(s: &str) {
println!("{}", s);
}
fn main() {}

@ -0,0 +1,18 @@
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
--> $DIR/issue_4266.rs:5:1
|
LL | async fn sink1<'a>(_: &'a str) {} // lint
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::needless-lifetimes` implied by `-D warnings`
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
--> $DIR/issue_4266.rs:9:1
|
LL | / async fn one_to_one<'a>(s: &'a str) -> &'a str {
LL | | s
LL | | }
| |_^
error: aborting due to 2 previous errors

@ -4,9 +4,9 @@
use std::io;
fn try_macro<T: io::Read + io::Write>(s: &mut T) -> io::Result<()> {
try!(s.write(b"test"));
r#try!(s.write(b"test"));
let mut buf = [0u8; 4];
try!(s.read(&mut buf));
r#try!(s.read(&mut buf));
Ok(())
}

@ -1,8 +1,8 @@
error: handle written amount returned or use `Write::write_all` instead
--> $DIR/unused_io_amount.rs:7:5
|
LL | try!(s.write(b"test"));
| ^^^^^^^^^^^^^^^^^^^^^^^
LL | r#try!(s.write(b"test"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::unused-io-amount` implied by `-D warnings`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
@ -10,8 +10,8 @@ LL | try!(s.write(b"test"));
error: handle read amount returned or use `Read::read_exact` instead
--> $DIR/unused_io_amount.rs:9:5
|
LL | try!(s.read(&mut buf));
| ^^^^^^^^^^^^^^^^^^^^^^^
LL | r#try!(s.read(&mut buf));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)