Skip to content

Implement 2024-edition lifetime capture rules RFC #116952

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1571,8 +1571,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
Vec::new()
}
hir::OpaqueTyOrigin::FnReturn(..) => {
if let FnDeclKind::Impl | FnDeclKind::Trait =
fn_kind.expect("expected RPITs to be lowered with a FnKind")
if matches!(
fn_kind.expect("expected RPITs to be lowered with a FnKind"),
FnDeclKind::Impl | FnDeclKind::Trait
) || self.tcx.features().lifetime_capture_rules_2024
|| span.at_least_rust_2024()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the RFC:

The stabilization of the 2024 lifetime capture rules in this RFC is contingent on the stabilization of TAIT or some other solution for precise capturing that will allow all code that is allowed under Rust 2021 to be expressed, in some cases with syntactic changes, in Rust 2024.

So until it is stabilized, the feature should be mandatory, even for edition 2024:

Suggested change
|| span.at_least_rust_2024()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RFC says that we're doing this in Rust 2024. It would make sense to me for this to land in Rust 2024 in nightly without a feature flag.

It does have a dependency, as noted. So if we run into a wall, it would need to be reverted and pulled out of Rust 2024 before stabilization. But that's true of many things we have penciled in for Rust 2024. There are various walls that we could run into and need to pull out other things. This RFC is just very specific about what that wall is.

We're fairly committed to this being stabilized in Rust 2024, so it's likely we'll find a way to avoid it running into this wall. If we fail at that, then we'll need to revert this. But it's better for now to just plan for this going in.

{
// return-position impl trait in trait was decided to capture all
// in-scope lifetimes, which we collect for all opaques during resolution.
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ declare_features! (
(internal, intrinsics, "1.0.0", None, None),
/// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
(internal, lang_items, "1.0.0", None, None),
/// Changes `impl Trait` to capture all lifetimes in scope.
(unstable, lifetime_capture_rules_2024, "CURRENT_RUSTC_VERSION", None, None),
/// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
(unstable, link_cfg, "1.14.0", None, None),
/// Allows the `multiple_supertrait_upcastable` lint.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,7 @@ symbols! {
lib,
libc,
lifetime,
lifetime_capture_rules_2024,
lifetimes,
likely,
line,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn foo(x: &Vec<i32>) -> impl Sized {
x
//~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
--> $DIR/feature-gate-lifetime-capture-rules-2024.rs:2:5
|
LL | fn foo(x: &Vec<i32>) -> impl Sized {
| --------- ---------- opaque type defined here
| |
| hidden type `&Vec<i32>` captures the anonymous lifetime defined here
LL | x
| ^
|
help: to declare that `impl Sized` captures `'_`, you can add an explicit `'_` lifetime bound
|
LL | fn foo(x: &Vec<i32>) -> impl Sized + '_ {
| ++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0700`.
14 changes: 14 additions & 0 deletions tests/ui/impl-trait/implicit-capture-late.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// known-bug: #117647

#![feature(lifetime_capture_rules_2024)]
#![feature(rustc_attrs)]
#![allow(internal_features)]
#![rustc_variance_of_opaques]

use std::ops::Deref;

fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
Box::new(x)
}

fn main() {}
9 changes: 9 additions & 0 deletions tests/ui/impl-trait/implicit-capture-late.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
--> $DIR/implicit-capture-late.rs:10:36
|
LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
| ^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0657`.
26 changes: 26 additions & 0 deletions tests/ui/impl-trait/variance.e2024.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error: [*, o]
--> $DIR/variance.rs:14:36
|
LL | fn not_captured_early<'a: 'a>() -> impl Sized {}
| ^^^^^^^^^^

error: [*, o]
--> $DIR/variance.rs:19:32
|
LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: [o]
--> $DIR/variance.rs:21:40
|
LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
| ^^^^^^^^^^

error: [o]
--> $DIR/variance.rs:26:36
|
LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 4 previous errors

26 changes: 26 additions & 0 deletions tests/ui/impl-trait/variance.new.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error: [*, o]
--> $DIR/variance.rs:14:36
|
LL | fn not_captured_early<'a: 'a>() -> impl Sized {}
| ^^^^^^^^^^

error: [*, o]
--> $DIR/variance.rs:19:32
|
LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: [o]
--> $DIR/variance.rs:21:40
|
LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
| ^^^^^^^^^^

error: [o]
--> $DIR/variance.rs:26:36
|
LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 4 previous errors

Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
error: [*]
--> $DIR/variance.rs:8:36
--> $DIR/variance.rs:14:36
|
LL | fn not_captured_early<'a: 'a>() -> impl Sized {}
| ^^^^^^^^^^

error: [*, o]
--> $DIR/variance.rs:10:32
--> $DIR/variance.rs:19:32
|
LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: []
--> $DIR/variance.rs:12:40
--> $DIR/variance.rs:21:40
|
LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
| ^^^^^^^^^^

error: [o]
--> $DIR/variance.rs:14:36
--> $DIR/variance.rs:26:36
|
LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
16 changes: 14 additions & 2 deletions tests/ui/impl-trait/variance.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
// revisions: old new e2024
//[e2024] edition: 2024
//[e2024] compile-flags: -Z unstable-options

#![cfg_attr(new, feature(lifetime_capture_rules_2024))]

#![feature(rustc_attrs)]
#![allow(internal_features)]
#![rustc_variance_of_opaques]

trait Captures<'a> {}
impl<T> Captures<'_> for T {}

fn not_captured_early<'a: 'a>() -> impl Sized {} //~ [*]
fn not_captured_early<'a: 'a>() -> impl Sized {}
//[old]~^ [*]
//[new]~^^ [*, o]
//[e2024]~^^^ [*, o]

fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ [*, o]

fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} //~ []
fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
//[old]~^ []
//[new]~^^ [o]
//[e2024]~^^^ [o]

fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ [o]

Expand Down