From 6a202f5708d34f8fec6b0bd24d8166652ac8df35 Mon Sep 17 00:00:00 2001 From: Caio Date: Sun, 21 Apr 2024 18:54:54 -0300 Subject: [PATCH] Stabilize anonymous_lifetime_in_impl_trait --- .../src/collect/resolve_bound_vars.rs | 36 ++++- tests/ui/impl-trait/impl-trait-lifetimes.rs | 60 +++++++++ .../ui/impl-trait/impl-trait-lifetimes.stderr | 43 ++++++ ...artial-anonymous-lifetime-in-impl-trait.rs | 33 +++++ ...al-anonymous-lifetime-in-impl-trait.stderr | 23 ++++ .../impl-trait-missing-lifetime-gated.rs | 21 ++- .../impl-trait-missing-lifetime-gated.stderr | 125 +++--------------- 7 files changed, 225 insertions(+), 116 deletions(-) create mode 100644 tests/ui/impl-trait/impl-trait-lifetimes.rs create mode 100644 tests/ui/impl-trait/impl-trait-lifetimes.stderr create mode 100644 tests/ui/impl-trait/partial-anonymous-lifetime-in-impl-trait.rs create mode 100644 tests/ui/impl-trait/partial-anonymous-lifetime-in-impl-trait.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index a5f038d383d88..dca47d6f7853d 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1168,9 +1168,16 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { && let hir::LifetimeName::Param(param_id) = lifetime_ref.res && let Some(generics) = self.tcx.hir().get_generics(self.tcx.local_parent(param_id)) - && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id) + && let Some((param, pred)) = generics + .params + .iter() + .position(|param| param.def_id == param_id) + .and_then(|idx| { + Some((generics.params.get(idx)?, generics.predicates.get(idx)?)) + }) && param.is_elided_lifetime() && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async() + && is_gat(pred) && !self.tcx.features().anonymous_lifetime_in_impl_trait { let mut diag: rustc_errors::Diag<'_> = rustc_session::parse::feature_err( @@ -2106,3 +2113,30 @@ pub fn deny_non_region_late_bound( *arg = ResolvedArg::Error(guar); } } + +fn is_gat(predicate: &hir::WherePredicate<'_>) -> bool { + let hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { bounds, .. }) = predicate + else { + return false; + }; + for bound in *bounds { + let hir::GenericBound::Trait(poly_trait_ref, _) = bound else { + continue; + }; + + for segment in poly_trait_ref.trait_ref.path.segments { + let Some(generic_args) = segment.args else { + continue; + }; + if !generic_args.args.is_empty() { + continue; + } + for binding in generic_args.bindings { + if !binding.gen_args.args.is_empty() { + return true; + } + } + } + } + false +} diff --git a/tests/ui/impl-trait/impl-trait-lifetimes.rs b/tests/ui/impl-trait/impl-trait-lifetimes.rs new file mode 100644 index 0000000000000..996c9c30ac779 --- /dev/null +++ b/tests/ui/impl-trait/impl-trait-lifetimes.rs @@ -0,0 +1,60 @@ +trait Foo { + fn foo(&self, _: T) { } +} + +trait FooBar<'a> { + type Item; +} + +mod foo { + fn fun(t: impl crate::Foo<&u32>, n: u32) { + t.foo(&n); + //~^ ERROR `n` does not live long enough + } +} + +mod fun { + fn fun(t: impl Fn(&u32), n: u32) { + t(&n); + } +} + +mod iterator_fun { + fn fun(t: impl Iterator, n: u32) { + for elem in t { + elem(&n); + } + } +} + +mod iterator_foo { + fn fun(t: impl Iterator>, n: u32) { + for elem in t { + elem.foo(&n); + //~^ ERROR `n` does not live long enough + } + } +} + +mod placeholder { + trait Placeholder<'a> { + fn foo(&self, _: &'a u32) {} + } + + fn fun(t: impl Placeholder<'_>, n: u32) { + t.foo(&n); + //~^ ERROR `n` does not live long enough + } +} + +mod stabilized { + trait InTrait { + fn in_trait(&self) -> impl Iterator; + } + + fn foo1(_: impl Iterator) {} + fn foo2<'b>(_: impl crate::FooBar<'b, Item = &u32>) {} +} + +fn main() { +} diff --git a/tests/ui/impl-trait/impl-trait-lifetimes.stderr b/tests/ui/impl-trait/impl-trait-lifetimes.stderr new file mode 100644 index 0000000000000..535b8c897a498 --- /dev/null +++ b/tests/ui/impl-trait/impl-trait-lifetimes.stderr @@ -0,0 +1,43 @@ +error[E0597]: `n` does not live long enough + --> $DIR/impl-trait-lifetimes.rs:11:15 + | +LL | fn fun(t: impl crate::Foo<&u32>, n: u32) { + | - has type `t` - binding `n` declared here +LL | t.foo(&n); + | ------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `n` is borrowed for `'1` +LL | +LL | } + | - `n` dropped here while still borrowed + +error[E0597]: `n` does not live long enough + --> $DIR/impl-trait-lifetimes.rs:33:22 + | +LL | fn fun(t: impl Iterator>, n: u32) { + | - binding `n` declared here +LL | for elem in t { +LL | elem.foo(&n); + | ^^ borrowed value does not live long enough +... +LL | } + | - `n` dropped here while still borrowed + +error[E0597]: `n` does not live long enough + --> $DIR/impl-trait-lifetimes.rs:45:15 + | +LL | fn fun(t: impl Placeholder<'_>, n: u32) { + | - has type `t` - binding `n` declared here +LL | t.foo(&n); + | ------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `n` is borrowed for `'1` +LL | +LL | } + | - `n` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/impl-trait/partial-anonymous-lifetime-in-impl-trait.rs b/tests/ui/impl-trait/partial-anonymous-lifetime-in-impl-trait.rs new file mode 100644 index 0000000000000..a8dfa5ca2aac2 --- /dev/null +++ b/tests/ui/impl-trait/partial-anonymous-lifetime-in-impl-trait.rs @@ -0,0 +1,33 @@ +// Incremental stabilization of `non-generic associated types` for non-generic associated types. + +mod stabilized { + trait FooBar<'a> { + type Item; + } + + fn foo0(x: impl Iterator) { + } + + fn foo1<'b>(_: impl FooBar<'b, Item = &u32>) { + } +} + +mod not_stabilized { + trait FooBar<'a> { + type Item; + } + + trait LendingIterator { + type Item<'a> + where + Self: 'a; + } + + fn foo0(_: impl LendingIterator = &u32>) {} + //~^ ERROR `'_` cannot be used here + //~| ERROR anonymous lifetimes in `impl Trait` are unstable + + fn foo1(_: impl FooBar<'_, Item = &u32>) {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/partial-anonymous-lifetime-in-impl-trait.stderr b/tests/ui/impl-trait/partial-anonymous-lifetime-in-impl-trait.stderr new file mode 100644 index 0000000000000..0cd107d8e596a --- /dev/null +++ b/tests/ui/impl-trait/partial-anonymous-lifetime-in-impl-trait.stderr @@ -0,0 +1,23 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/partial-anonymous-lifetime-in-impl-trait.rs:26:42 + | +LL | fn foo0(_: impl LendingIterator = &u32>) {} + | ^^ `'_` is a reserved lifetime name + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/partial-anonymous-lifetime-in-impl-trait.rs:26:49 + | +LL | fn foo0(_: impl LendingIterator = &u32>) {} + | ^ expected named lifetime parameter + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: consider introducing a named lifetime parameter + | +LL | fn foo0<'a>(_: impl LendingIterator = &'a u32>) {} + | ++++ ++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0637, E0658. +For more information about an error, try `rustc --explain E0637`. diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs index 735efe89cba5b..0ece352759de0 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs @@ -1,13 +1,13 @@ //@ edition:2021 // gate-test-anonymous_lifetime_in_impl_trait + // Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`. mod elided { fn f(_: impl Iterator) {} - //~^ ERROR anonymous lifetimes in `impl Trait` are unstable fn g(mut x: impl Iterator) -> Option<&()> { x.next() } - //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + //~^ ERROR lifetime may not live long //~| ERROR missing lifetime specifier // Anonymous lifetimes in async fn are already allowed. @@ -17,16 +17,15 @@ mod elided { // Anonymous lifetimes in async fn are already allowed. // But that lifetime does not participate in resolution. async fn i(mut x: impl Iterator) -> Option<&()> { x.next() } - //~^ ERROR missing lifetime specifier - //~| ERROR lifetime may not live long enough + //~^ ERROR lifetime may not live long + //~| ERROR missing lifetime specifier } mod underscore { fn f(_: impl Iterator) {} - //~^ ERROR anonymous lifetimes in `impl Trait` are unstable fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } - //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + //~^ ERROR lifetime may not live long //~| ERROR missing lifetime specifier // Anonymous lifetimes in async fn are already allowed. @@ -36,18 +35,17 @@ mod underscore { // Anonymous lifetimes in async fn are already allowed. // But that lifetime does not participate in resolution. async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } - //~^ ERROR missing lifetime specifier - //~| ERROR lifetime may not live long enough + //~^ ERROR lifetime may not live long + //~| ERROR missing lifetime specifier } mod alone_in_path { trait Foo<'a> { fn next(&mut self) -> Option<&'a ()>; } fn f(_: impl Foo) {} - //~^ ERROR anonymous lifetimes in `impl Trait` are unstable fn g(mut x: impl Foo) -> Option<&()> { x.next() } - //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + //~^ ERROR lifetime may not live long //~| ERROR missing lifetime specifier } @@ -55,10 +53,9 @@ mod in_path { trait Foo<'a, T> { fn next(&mut self) -> Option<&'a T>; } fn f(_: impl Foo<()>) {} - //~^ ERROR anonymous lifetimes in `impl Trait` are unstable fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } - //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + //~^ ERROR lifetime may not live long //~| ERROR missing lifetime specifier } diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index 61a2925f582b2..f506cd13bd4c2 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -41,7 +41,7 @@ LL + async fn i(mut x: impl Iterator) -> Option<()> { x.next() } | error[E0106]: missing lifetime specifier - --> $DIR/impl-trait-missing-lifetime-gated.rs:28:58 + --> $DIR/impl-trait-missing-lifetime-gated.rs:27:58 | LL | fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } | ^^ expected named lifetime parameter @@ -62,7 +62,7 @@ LL + fn g(mut x: impl Iterator) -> Option<()> { x.next() } | error[E0106]: missing lifetime specifier - --> $DIR/impl-trait-missing-lifetime-gated.rs:38:64 + --> $DIR/impl-trait-missing-lifetime-gated.rs:37:64 | LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } | ^^ expected named lifetime parameter @@ -83,7 +83,7 @@ LL + async fn i(mut x: impl Iterator) -> Option<()> { x.next( | error[E0106]: missing lifetime specifier - --> $DIR/impl-trait-missing-lifetime-gated.rs:49:37 + --> $DIR/impl-trait-missing-lifetime-gated.rs:47:37 | LL | fn g(mut x: impl Foo) -> Option<&()> { x.next() } | ^ expected named lifetime parameter @@ -104,7 +104,7 @@ LL + fn g(mut x: impl Foo) -> Option<()> { x.next() } | error[E0106]: missing lifetime specifier - --> $DIR/impl-trait-missing-lifetime-gated.rs:60:41 + --> $DIR/impl-trait-missing-lifetime-gated.rs:57:41 | LL | fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } | ^ expected named lifetime parameter @@ -124,32 +124,6 @@ LL - fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } LL + fn g(mut x: impl Foo<()>) -> Option<()> { x.next() } | -error[E0658]: anonymous lifetimes in `impl Trait` are unstable - --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 - | -LL | fn f(_: impl Iterator) {} - | ^ expected named lifetime parameter - | - = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -help: consider introducing a named lifetime parameter - | -LL | fn f<'a>(_: impl Iterator) {} - | ++++ ++ - -error[E0658]: anonymous lifetimes in `impl Trait` are unstable - --> $DIR/impl-trait-missing-lifetime-gated.rs:9:39 - | -LL | fn g(mut x: impl Iterator) -> Option<&()> { x.next() } - | ^ expected named lifetime parameter - | - = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -help: consider introducing a named lifetime parameter - | -LL | fn g<'a>(mut x: impl Iterator) -> Option<&()> { x.next() } - | ++++ ++ - error: lifetime may not live long enough --> $DIR/impl-trait-missing-lifetime-gated.rs:19:67 | @@ -158,93 +132,38 @@ LL | async fn i(mut x: impl Iterator) -> Option<&()> { x.next() | | | return type `impl Future>` contains a lifetime `'1` -error[E0658]: anonymous lifetimes in `impl Trait` are unstable - --> $DIR/impl-trait-missing-lifetime-gated.rs:25:35 - | -LL | fn f(_: impl Iterator) {} - | ^^ expected named lifetime parameter - | - = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -help: consider introducing a named lifetime parameter - | -LL | fn f<'a>(_: impl Iterator) {} - | ++++ ~~ - -error[E0658]: anonymous lifetimes in `impl Trait` are unstable - --> $DIR/impl-trait-missing-lifetime-gated.rs:28:39 - | -LL | fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } - | ^^ expected named lifetime parameter - | - = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -help: consider introducing a named lifetime parameter - | -LL | fn g<'a>(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } - | ++++ ~~ - error: lifetime may not live long enough - --> $DIR/impl-trait-missing-lifetime-gated.rs:38:73 + --> $DIR/impl-trait-missing-lifetime-gated.rs:37:73 | LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } | ----------------------------------------------------------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` | | | return type `impl Future>` contains a lifetime `'1` -error[E0658]: anonymous lifetimes in `impl Trait` are unstable - --> $DIR/impl-trait-missing-lifetime-gated.rs:46:18 - | -LL | fn f(_: impl Foo) {} - | ^^^ expected named lifetime parameter - | - = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -help: consider introducing a named lifetime parameter +error: lifetime may not live long enough + --> $DIR/impl-trait-missing-lifetime-gated.rs:9:61 | -LL | fn f<'a>(_: impl Foo<'a>) {} - | ++++ ++++ +LL | fn g(mut x: impl Iterator) -> Option<&()> { x.next() } + | ----- has type `x` ^^^^^^^^ returning this value requires that `'1` must outlive `'static` -error[E0658]: anonymous lifetimes in `impl Trait` are unstable - --> $DIR/impl-trait-missing-lifetime-gated.rs:49:22 - | -LL | fn g(mut x: impl Foo) -> Option<&()> { x.next() } - | ^^^ expected named lifetime parameter - | - = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -help: consider introducing a named lifetime parameter +error: lifetime may not live long enough + --> $DIR/impl-trait-missing-lifetime-gated.rs:27:67 | -LL | fn g<'a>(mut x: impl Foo<'a>) -> Option<&()> { x.next() } - | ++++ ++++ +LL | fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ----- has type `x` ^^^^^^^^ returning this value requires that `'1` must outlive `'static` -error[E0658]: anonymous lifetimes in `impl Trait` are unstable - --> $DIR/impl-trait-missing-lifetime-gated.rs:57:22 - | -LL | fn f(_: impl Foo<()>) {} - | ^ expected named lifetime parameter - | - = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -help: consider introducing a named lifetime parameter +error: lifetime may not live long enough + --> $DIR/impl-trait-missing-lifetime-gated.rs:47:44 | -LL | fn f<'a>(_: impl Foo<'a, ()>) {} - | ++++ +++ +LL | fn g(mut x: impl Foo) -> Option<&()> { x.next() } + | ----- has type `x` ^^^^^^^^ returning this value requires that `'1` must outlive `'static` -error[E0658]: anonymous lifetimes in `impl Trait` are unstable - --> $DIR/impl-trait-missing-lifetime-gated.rs:60:26 +error: lifetime may not live long enough + --> $DIR/impl-trait-missing-lifetime-gated.rs:57:48 | LL | fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } - | ^ expected named lifetime parameter - | - = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -help: consider introducing a named lifetime parameter - | -LL | fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() } - | ++++ +++ + | ----- has type `x` ^^^^^^^^ returning this value requires that `'1` must outlive `'static` -error: aborting due to 16 previous errors +error: aborting due to 12 previous errors -Some errors have detailed explanations: E0106, E0658. -For more information about an error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0106`.