Auto merge of #90446 - cjgillot:late-elided, r=jackh726

Lint elided lifetimes in path during lifetime resolution.

The lifetime elision lint is known to be brittle and can be redundant with later lifetime resolution errors. This PR aims to remove the redundancy by performing the lint after lifetime resolution.

This PR proposes to carry the information that an elision should be linted against by using a special `LifetimeName`. I am not certain this is the best solution, but it is certainly the easiest.

Fixes https://github.com/rust-lang/rust/issues/60199
Fixes https://github.com/rust-lang/rust/issues/55768
Fixes https://github.com/rust-lang/rust/issues/63110
Fixes https://github.com/rust-lang/rust/issues/71957
This commit is contained in:
bors 2021-12-01 23:22:43 +00:00
commit 76938d64a4
13 changed files with 401 additions and 241 deletions

View file

@ -5,23 +5,24 @@
#![deny(elided_lifetimes_in_paths)]
//~^ NOTE the lint level is defined here
use std::cell::{RefCell, Ref};
use std::cell::{Ref, RefCell};
struct Foo<'a> { x: &'a u32 }
struct Foo<'a> {
x: &'a u32,
}
fn foo(x: &Foo<'_>) {
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
}
fn bar(x: &Foo<'_>) {}
struct Wrapped<'a>(&'a str);
struct WrappedWithBow<'a> {
gift: &'a str
gift: &'a str,
}
struct MatchedSet<'a, 'b> {
@ -31,22 +32,34 @@ struct MatchedSet<'a, 'b> {
fn wrap_gift(gift: &str) -> Wrapped<'_> {
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
Wrapped(gift)
}
fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow<'_> {
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
WrappedWithBow { gift }
}
fn inspect_matched_set(set: MatchedSet<'_, '_>) {
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected 2 lifetime parameters
//~| HELP consider using the `'_` lifetime
println!("{} {}", set.one, set.another);
}
// Verify that the lint does not fire, because the added `'_` wouldn't be resolved correctly.
fn match_sets() -> MatchedSet<'static, 'static> {
//~^ ERROR missing lifetime specifiers
//~| NOTE expected 2 lifetime parameters
//~| HELP this function's return type contains a borrowed value
//~| HELP consider using the `'static` lifetime
MatchedSet { one: "one", another: "another" }
}
macro_rules! autowrapper {
($type_name:ident, $fn_name:ident, $lt:lifetime) => {
struct $type_name<$lt> {
@ -55,7 +68,11 @@ macro_rules! autowrapper {
fn $fn_name(gift: &str) -> $type_name<'_> {
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
//~| ERROR hidden lifetime parameters in types are deprecated
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
$type_name { gift }
}
}
@ -65,19 +82,34 @@ autowrapper!(Autowrapped, autowrap_gift, 'a);
//~^ NOTE in this expansion of autowrapper!
//~| NOTE in this expansion of autowrapper!
// Verify that rustfix does not try to apply the fix twice.
autowrapper!(AutowrappedAgain, autowrap_gift_again, 'a);
//~^ NOTE in this expansion of autowrapper!
//~| NOTE in this expansion of autowrapper!
macro_rules! anytuple_ref_ty {
($($types:ty),*) => {
Ref<'_, ($($types),*)>
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
}
}
#[allow(elided_lifetimes_in_paths)]
mod blah {
struct Thing<'a>(&'a i32);
struct Bar<T>(T);
fn foo(b: Bar<Thing>) {}
}
fn main() {
let honesty = RefCell::new((4, 'e'));
let loyalty: Ref<'_, (u32, char)> = honesty.borrow();
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
let generosity = Ref::map(loyalty, |t| &t.0);
let laughter = RefCell::new((true, "magic"));

View file

@ -5,23 +5,24 @@
#![deny(elided_lifetimes_in_paths)]
//~^ NOTE the lint level is defined here
use std::cell::{RefCell, Ref};
use std::cell::{Ref, RefCell};
struct Foo<'a> { x: &'a u32 }
struct Foo<'a> {
x: &'a u32,
}
fn foo(x: &Foo) {
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
}
fn bar(x: &Foo<'_>) {}
struct Wrapped<'a>(&'a str);
struct WrappedWithBow<'a> {
gift: &'a str
gift: &'a str,
}
struct MatchedSet<'a, 'b> {
@ -31,22 +32,34 @@ struct MatchedSet<'a, 'b> {
fn wrap_gift(gift: &str) -> Wrapped {
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
Wrapped(gift)
}
fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow {
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
WrappedWithBow { gift }
}
fn inspect_matched_set(set: MatchedSet) {
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected 2 lifetime parameters
//~| HELP consider using the `'_` lifetime
println!("{} {}", set.one, set.another);
}
// Verify that the lint does not fire, because the added `'_` wouldn't be resolved correctly.
fn match_sets() -> MatchedSet {
//~^ ERROR missing lifetime specifiers
//~| NOTE expected 2 lifetime parameters
//~| HELP this function's return type contains a borrowed value
//~| HELP consider using the `'static` lifetime
MatchedSet { one: "one", another: "another" }
}
macro_rules! autowrapper {
($type_name:ident, $fn_name:ident, $lt:lifetime) => {
struct $type_name<$lt> {
@ -55,7 +68,11 @@ macro_rules! autowrapper {
fn $fn_name(gift: &str) -> $type_name {
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
//~| ERROR hidden lifetime parameters in types are deprecated
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
$type_name { gift }
}
}
@ -65,19 +82,34 @@ autowrapper!(Autowrapped, autowrap_gift, 'a);
//~^ NOTE in this expansion of autowrapper!
//~| NOTE in this expansion of autowrapper!
// Verify that rustfix does not try to apply the fix twice.
autowrapper!(AutowrappedAgain, autowrap_gift_again, 'a);
//~^ NOTE in this expansion of autowrapper!
//~| NOTE in this expansion of autowrapper!
macro_rules! anytuple_ref_ty {
($($types:ty),*) => {
Ref<($($types),*)>
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
}
}
#[allow(elided_lifetimes_in_paths)]
mod blah {
struct Thing<'a>(&'a i32);
struct Bar<T>(T);
fn foo(b: Bar<Thing>) {}
}
fn main() {
let honesty = RefCell::new((4, 'e'));
let loyalty: Ref<(u32, char)> = honesty.borrow();
//~^ ERROR hidden lifetime parameters in types are deprecated
//~| HELP indicate the anonymous lifetime
//~| NOTE expected named lifetime parameter
//~| HELP consider using the `'_` lifetime
let generosity = Ref::map(loyalty, |t| &t.0);
let laughter = RefCell::new((true, "magic"));

View file

@ -1,60 +1,120 @@
error: hidden lifetime parameters in types are deprecated
--> $DIR/elided-lifetimes.rs:13:12
--> $DIR/elided-lifetimes.rs:14:12
|
LL | fn foo(x: &Foo) {
| ^^^- help: indicate the anonymous lifetime: `<'_>`
| ^^^ expected named lifetime parameter
|
note: the lint level is defined here
--> $DIR/elided-lifetimes.rs:5:9
|
LL | #![deny(elided_lifetimes_in_paths)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider using the `'_` lifetime
|
LL | fn foo(x: &Foo<'_>) {
| ~~~~~~~
error: hidden lifetime parameters in types are deprecated
--> $DIR/elided-lifetimes.rs:32:29
--> $DIR/elided-lifetimes.rs:33:29
|
LL | fn wrap_gift(gift: &str) -> Wrapped {
| ^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
| ^^^^^^^ expected named lifetime parameter
|
help: consider using the `'_` lifetime
|
LL | fn wrap_gift(gift: &str) -> Wrapped<'_> {
| ~~~~~~~~~~~
error: hidden lifetime parameters in types are deprecated
--> $DIR/elided-lifetimes.rs:38:38
--> $DIR/elided-lifetimes.rs:40:38
|
LL | fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow {
| ^^^^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
| ^^^^^^^^^^^^^^ expected named lifetime parameter
|
help: consider using the `'_` lifetime
|
LL | fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow<'_> {
| ~~~~~~~~~~~~~~~~~~
error: hidden lifetime parameters in types are deprecated
--> $DIR/elided-lifetimes.rs:44:29
--> $DIR/elided-lifetimes.rs:47:29
|
LL | fn inspect_matched_set(set: MatchedSet) {
| ^^^^^^^^^^- help: indicate the anonymous lifetimes: `<'_, '_>`
| ^^^^^^^^^^ expected 2 lifetime parameters
|
help: consider using the `'_` lifetime
|
LL | fn inspect_matched_set(set: MatchedSet<'_, '_>) {
| ~~~~~~~~~~~~~~~~~~
error[E0106]: missing lifetime specifiers
--> $DIR/elided-lifetimes.rs:55:20
|
LL | fn match_sets() -> MatchedSet {
| ^^^^^^^^^^ expected 2 lifetime parameters
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
|
LL | fn match_sets() -> MatchedSet<'static, 'static> {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: hidden lifetime parameters in types are deprecated
--> $DIR/elided-lifetimes.rs:56:36
--> $DIR/elided-lifetimes.rs:69:36
|
LL | fn $fn_name(gift: &str) -> $type_name {
| ^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
| ^^^^^^^^^^ expected named lifetime parameter
...
LL | autowrapper!(Autowrapped, autowrap_gift, 'a);
| -------------------------------------------- in this macro invocation
|
= note: this error originates in the macro `autowrapper` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider using the `'_` lifetime
|
LL | fn $fn_name(gift: &str) -> $type_name<'_> {
| ~~~~~~~~~~~~~~
error: hidden lifetime parameters in types are deprecated
--> $DIR/elided-lifetimes.rs:78:18
--> $DIR/elided-lifetimes.rs:69:36
|
LL | fn $fn_name(gift: &str) -> $type_name {
| ^^^^^^^^^^ expected named lifetime parameter
...
LL | autowrapper!(AutowrappedAgain, autowrap_gift_again, 'a);
| ------------------------------------------------------- in this macro invocation
|
= note: this error originates in the macro `autowrapper` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider using the `'_` lifetime
|
LL | fn $fn_name(gift: &str) -> $type_name<'_> {
| ~~~~~~~~~~~~~~
error: hidden lifetime parameters in types are deprecated
--> $DIR/elided-lifetimes.rs:109:22
|
LL | let loyalty: Ref<(u32, char)> = honesty.borrow();
| ^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Ref<'_, (u32, char)>`
| ^ expected named lifetime parameter
|
help: consider using the `'_` lifetime
|
LL | let loyalty: Ref<'_, (u32, char)> = honesty.borrow();
| +++
error: hidden lifetime parameters in types are deprecated
--> $DIR/elided-lifetimes.rs:70:9
--> $DIR/elided-lifetimes.rs:92:13
|
LL | Ref<($($types),*)>
| ^^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Ref<'_, ($($types),*)>`
| ^ expected named lifetime parameter
...
LL | let yellow: anytuple_ref_ty!(bool, &str) = laughter.borrow();
| ---------------------------- in this macro invocation
|
= note: this error originates in the macro `anytuple_ref_ty` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider using the `'_` lifetime
|
LL | Ref<'_, ($($types),*)>
| +++
error: aborting due to 7 previous errors
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0106`.

View file

@ -2,9 +2,13 @@ warning: hidden lifetime parameters in types are deprecated
--> $DIR/allowed-by-default-lint.rs:9:12
|
LL | fn foo(x: &Foo) {}
| ^^^- help: indicate the anonymous lifetime: `<'_>`
| ^^^ expected named lifetime parameter
|
= note: requested on the command line with `--force-warn elided-lifetimes-in-paths`
help: consider using the `'_` lifetime
|
LL | fn foo(x: &Foo<'_>) {}
| ~~~~~~~
warning: 1 warning emitted

View file

@ -1,7 +1,6 @@
// check-pass
#![feature(lint_reasons)]
#![warn(elided_lifetimes_in_paths,
//~^ NOTE the lint level is defined here
reason = "explicit anonymous lifetimes aid reasoning about ownership")]
@ -20,8 +19,9 @@ pub struct CheaterDetectionMechanism {}
impl fmt::Debug for CheaterDetectionMechanism {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
//~^ WARN hidden lifetime parameters in types are deprecated
//~| NOTE expected named lifetime parameter
//~| NOTE explicit anonymous lifetimes aid
//~| HELP indicate the anonymous lifetime
//~| HELP consider using the `'_` lifetime
fmt.debug_struct("CheaterDetectionMechanism").finish()
}
}

View file

@ -1,15 +1,19 @@
warning: hidden lifetime parameters in types are deprecated
--> $DIR/reasons.rs:21:29
--> $DIR/reasons.rs:20:29
|
LL | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
| ^^^^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
| ^^^^^^^^^^^^^^ expected named lifetime parameter
|
= note: explicit anonymous lifetimes aid reasoning about ownership
note: the lint level is defined here
--> $DIR/reasons.rs:5:9
--> $DIR/reasons.rs:4:9
|
LL | #![warn(elided_lifetimes_in_paths,
| ^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider using the `'_` lifetime
|
LL | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
| ~~~~~~~~~~~~~~~~~~
warning: variable `Social_exchange_psychology` should have a snake case name
--> $DIR/reasons.rs:30:9
@ -20,7 +24,7 @@ LL | let Social_exchange_psychology = CheaterDetectionMechanism {};
= note: people shouldn't have to change their usual style habits
to contribute to our project
note: the lint level is defined here
--> $DIR/reasons.rs:9:5
--> $DIR/reasons.rs:8:5
|
LL | nonstandard_style,
| ^^^^^^^^^^^^^^^^^