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:
commit
fc0fb0328b
24 changed files with 615 additions and 51 deletions
28
src/test/compile-fail/E0621-does-not-trigger-for-closures.rs
Normal file
28
src/test/compile-fail/E0621-does-not-trigger-for-closures.rs
Normal 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() {}
|
||||
|
|
@ -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() { }
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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 () { }
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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() { }
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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() { }
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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() { }
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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)
|
||||
|
||||
19
src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs
Normal file
19
src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs
Normal 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() { }
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue