diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index b54f0ef361a8d..d210b9493d1e2 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -148,6 +148,8 @@ declare_features! ( /// below (it has to be checked before expansion possibly makes /// macros disappear). (active, allow_internal_unstable, "1.0.0", None, None), + /// Allows using anonymous lifetimes in argument-position impl-trait. + (active, anonymous_lifetime_in_impl_trait, "1.63.0", None, None), /// Allows identifying the `compiler_builtins` crate. (active, compiler_builtins, "1.13.0", None, None), /// Outputs useful `assert!` messages diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 557dbecfabe09..7968852908204 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1677,7 +1677,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break None; } - Scope::Binder { ref lifetimes, scope_type, s, .. } => { + Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => { if let Some(&def) = lifetimes.get(®ion_def_id) { break Some(def.shifted(late_depth)); } @@ -1685,6 +1685,21 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { BinderScopeType::Normal => late_depth += 1, BinderScopeType::Concatenating => {} } + // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in + // regular fns. + if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin + && let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name + && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner) + && !self.tcx.features().anonymous_lifetime_in_impl_trait + { + rustc_session::parse::feature_err( + &self.tcx.sess.parse_sess, + sym::anonymous_lifetime_in_impl_trait, + lifetime_ref.span, + "anonymous lifetimes in `impl Trait` are unstable", + ).emit(); + return; + } scope = s; } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9b6967621f1dc..10a24a4c53441 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -341,6 +341,7 @@ symbols! { always, and, and_then, + anonymous_lifetime_in_impl_trait, any, append_const_msg, arbitrary_enum_discriminant, diff --git a/src/test/ui/generic-associated-types/issue-95305.rs b/src/test/ui/generic-associated-types/issue-95305.rs index 78d4bb913b873..e2f1710fa281c 100644 --- a/src/test/ui/generic-associated-types/issue-95305.rs +++ b/src/test/ui/generic-associated-types/issue-95305.rs @@ -3,7 +3,7 @@ // at some point in the future. #![feature(generic_associated_types)] - +#![feature(anonymous_lifetime_in_impl_trait)] trait Foo { type Item<'a>; } diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs new file mode 100644 index 0000000000000..fe291e021bc54 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs @@ -0,0 +1,21 @@ +// edition:2021 +// gate-test-anonymous_lifetime_in_impl_trait +// Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`. + +fn f(_: impl Iterator) {} +//~^ ERROR anonymous lifetimes in `impl Trait` are unstable + +fn g(x: impl Iterator) -> Option<&'_ ()> { x.next() } +//~^ ERROR anonymous lifetimes in `impl Trait` are unstable +//~| ERROR missing lifetime specifier + +// Anonymous lifetimes in async fn are already allowed. +// This is understood as `fn foo<'_1>(_: impl Iterator) {}`. +async fn h(_: impl Iterator) {} + +// Anonymous lifetimes in async fn are already allowed. +// But that lifetime does not participate in resolution. +async fn i(x: impl Iterator) -> Option<&'_ ()> { x.next() } +//~^ ERROR missing lifetime specifier + +fn main() {} diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr new file mode 100644 index 0000000000000..9adc9679eee47 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -0,0 +1,44 @@ +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:5:31 + | +LL | fn f(_: impl Iterator) {} + | ^^ + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable + +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime-gated.rs:8:50 + | +LL | fn g(x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'static` lifetime + | +LL | fn g(x: impl Iterator) -> Option<&'static ()> { x.next() } + | ~~~~~~~ + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:8:31 + | +LL | fn g(x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ^^ + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable + +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime-gated.rs:18:56 + | +LL | async fn i(x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'static` lifetime + | +LL | async fn i(x: impl Iterator) -> Option<&'static ()> { x.next() } + | ~~~~~~~ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0106, E0658. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime.rs b/src/test/ui/suggestions/impl-trait-missing-lifetime.rs index 2ef0f5a4853f9..dcc716f56b705 100644 --- a/src/test/ui/suggestions/impl-trait-missing-lifetime.rs +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime.rs @@ -1,3 +1,7 @@ +// edition:2021 + +#![feature(anonymous_lifetime_in_impl_trait)] + // This is understood as `fn foo<'_1>(_: impl Iterator) {}`. fn f(_: impl Iterator) {} @@ -5,4 +9,11 @@ fn f(_: impl Iterator) {} fn g(x: impl Iterator) -> Option<&'_ ()> { x.next() } //~^ ERROR missing lifetime specifier +// This is understood as `fn foo<'_1>(_: impl Iterator) {}`. +async fn h(_: impl Iterator) {} + +// But that lifetime does not participate in resolution. +async fn i(x: impl Iterator) -> Option<&'_ ()> { x.next() } +//~^ ERROR missing lifetime specifier + fn main() {} diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr b/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr index a09ef8121d78f..d3c64cb466d74 100644 --- a/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/impl-trait-missing-lifetime.rs:5:50 + --> $DIR/impl-trait-missing-lifetime.rs:9:50 | LL | fn g(x: impl Iterator) -> Option<&'_ ()> { x.next() } | ^^ expected named lifetime parameter @@ -10,6 +10,18 @@ help: consider using the `'static` lifetime LL | fn g(x: impl Iterator) -> Option<&'static ()> { x.next() } | ~~~~~~~ -error: aborting due to previous error +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime.rs:16:56 + | +LL | async fn i(x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'static` lifetime + | +LL | async fn i(x: impl Iterator) -> Option<&'static ()> { x.next() } + | ~~~~~~~ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0106`.