Rollup merge of #42669 - gaurikholkar:master, r=nikomatsakis

Adding diagnostic code 0611 for lifetime errors with one named, one anonymous lifetime parameter

This is a fix for #42517
Note that this only handles the above case for **function declarations** and **traits**.
`impl items` and `closures` will be handled in a later PR.
Example
```
fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
    if x > y { x } else { y }
}
```
now displays the following error message. ui tests have been added for the same.
```
error[E0611]: explicit lifetime required in the type of `x`
11 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
   |                     ^ consider changing the type of `x` to `&'a i32`
12 |     if x > y { x } else { y }
   |                  - lifetime `'a` required
```
#42516
r? @nikomatsakis
This commit is contained in:
Guillaume Gomez 2017-06-30 22:44:43 +02:00 committed by GitHub
commit fc0fb0328b
24 changed files with 615 additions and 51 deletions

View file

@ -0,0 +1,28 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that we give the generic E0495 when one of the free regions is
// bound in a closure (rather than suggesting a change to the signature
// of the closure, which is not specified in `foo` but rather in `invoke`).
// FIXME - This might be better as a UI test, but the finer details
// of the error seem to vary on different machines.
fn invoke<'a, F>(x: &'a i32, f: F) -> &'a i32
where F: FnOnce(&'a i32, &i32) -> &'a i32
{
let y = 22;
f(x, &y)
}
fn foo<'a>(x: &'a i32) {
invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495
}
fn main() {}

View file

@ -0,0 +1,15 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
if x > y { x } else { y }
}
fn main() { }

View file

@ -0,0 +1,10 @@
error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16
|
11 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
| - consider changing the type of `x` to `&'a i32`
12 | if x > y { x } else { y }
| ^ lifetime `'a` required
error: aborting due to previous error(s)

View file

@ -0,0 +1,15 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 {
if x > y { x } else { y }
}
fn main () { }

View file

@ -0,0 +1,10 @@
error[E0621]: explicit lifetime required in parameter type
--> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27
|
11 | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 {
| ------ consider changing type to `(&'a i32, &'a i32)`
12 | if x > y { x } else { y }
| ^ lifetime `'a` required
error: aborting due to previous error(s)

View file

@ -0,0 +1,18 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Foo {
fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
if x > y { x } else { y }
}
}
fn main() { }

View file

@ -0,0 +1,10 @@
error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15
|
13 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
| - consider changing the type of `x` to `&'a i32`
14 | if x > y { x } else { y }
| ^ lifetime `'a` required
error: aborting due to previous error(s)

View file

@ -0,0 +1,24 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Foo {
field: i32
}
impl Foo {
fn foo<'a>(&'a self, x: &i32) -> &i32 {
if true { &self.field } else { x }
}
}
fn main() { }

View file

@ -0,0 +1,11 @@
error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36
|
16 | fn foo<'a>(&'a self, x: &i32) -> &i32 {
| - consider changing the type of `x` to `&'a i32`
17 |
18 | if true { &self.field } else { x }
| ^ lifetime `'a` required
error: aborting due to previous error(s)

View file

@ -0,0 +1,27 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Foo {
fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
}
impl Foo for () {
fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
if x > y { x } else { y }
}
}
fn main() {}

View file

@ -0,0 +1,27 @@
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:20
|
21 | if x > y { x } else { y }
| ^
|
note: ...the reference is valid for the lifetime 'a as defined on the method body at 19:5...
--> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5
|
19 | / fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
20 | |
21 | | if x > y { x } else { y }
22 | |
23 | | }
| |_____^
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 19:5
--> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5
|
19 | / fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
20 | |
21 | | if x > y { x } else { y }
22 | |
23 | | }
| |_____^
error: aborting due to previous error(s)

View file

@ -1,23 +1,10 @@
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
error[E0621]: explicit lifetime required in the type of `y`
--> $DIR/ex1-return-one-existing-name-if-else.rs:12:27
|
11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
| - consider changing the type of `y` to `&'a i32`
12 | if x > y { x } else { y }
| ^
|
note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:1...
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
12 | | if x > y { x } else { y }
13 | | }
| |_^
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:1
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
12 | | if x > y { x } else { y }
13 | | }
| |_^
| ^ lifetime `'a` required
error: aborting due to previous error(s)

View file

@ -0,0 +1,24 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Foo {
field: i32
}
impl Foo {
fn foo<'a>(&self, x: &'a i32) -> &i32 {
x
}
}
fn main() { }

View file

@ -0,0 +1,27 @@
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5
|
18 | x
| ^
|
note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3...
--> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3
|
16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 {
17 | |
18 | | x
19 | |
20 | | }
| |___^
note: ...but the borrowed content is only valid for the lifetime 'a as defined on the method body at 16:3
--> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3
|
16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 {
17 | |
18 | | x
19 | |
20 | | }
| |___^
error: aborting due to previous error(s)

View file

@ -0,0 +1,23 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Foo {
field: i32,
}
impl Foo {
fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
if true { x } else { self }
}
}
fn main() {}

View file

@ -0,0 +1,27 @@
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30
|
18 | if true { x } else { self }
| ^^^^
|
note: ...the reference is valid for the lifetime 'a as defined on the method body at 16:5...
--> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5
|
16 | / fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
17 | |
18 | | if true { x } else { self }
19 | |
20 | | }
| |_____^
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 16:5
--> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5
|
16 | / fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
17 | |
18 | | if true { x } else { self }
19 | |
20 | | }
| |_____^
error: aborting due to previous error(s)

View file

@ -0,0 +1,19 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Ref<'a, T: 'a> {
data: &'a T
}
fn foo<'a>(x: Ref<i32>, y: &mut Vec<Ref<'a, i32>>) {
y.push(x);
}
fn main() { }

View file

@ -0,0 +1,10 @@
error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/ex2a-push-one-existing-name-2.rs:16:12
|
15 | fn foo<'a>(x: Ref<i32>, y: &mut Vec<Ref<'a, i32>>) {
| - consider changing the type of `x` to `Ref<'a, i32>`
16 | y.push(x);
| ^ lifetime `'a` required
error: aborting due to previous error(s)

View file

@ -1,25 +1,10 @@
error[E0308]: mismatched types
error[E0621]: explicit lifetime required in the type of `y`
--> $DIR/ex2a-push-one-existing-name.rs:16:12
|
15 | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
| - consider changing the type of `y` to `Ref<'a, i32>`
16 | x.push(y);
| ^ lifetime mismatch
|
= note: expected type `Ref<'a, _>`
found type `Ref<'_, _>`
note: the anonymous lifetime #2 defined on the function body at 15:1...
--> $DIR/ex2a-push-one-existing-name.rs:15:1
|
15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:1
--> $DIR/ex2a-push-one-existing-name.rs:15:1
|
15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
| ^ lifetime `'a` required
error: aborting due to previous error(s)