Skip to content

Remove lifetime_capture_rules_2024 feature #136787

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 1 commit into from
Feb 22, 2025
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
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/removed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ declare_features! (
Some("removed as it caused some confusion and discussion was inactive for years")),
/// Lazily evaluate constants. This allows constants to depend on type parameters.
(removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")),
/// Changes `impl Trait` to capture all lifetimes in scope.
(removed, lifetime_capture_rules_2024, "1.76.0", None, Some("unnecessary -- use edition 2024 instead")),
/// Allows using the `#[link_args]` attribute.
(removed, link_args, "1.53.0", Some(29596),
Some("removed in favor of using `-C link-arg=ARG` on command line, \
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,6 @@ declare_features! (
(internal, intrinsics, "1.0.0", None),
/// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
(internal, lang_items, "1.0.0", None),
/// Changes `impl Trait` to capture all lifetimes in scope.
(unstable, lifetime_capture_rules_2024, "1.76.0", None),
/// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
(internal, link_cfg, "1.14.0", None),
/// Allows using `?Trait` trait bounds in more contexts.
Expand Down
33 changes: 12 additions & 21 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,21 +305,15 @@ fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVaria
}

/// Whether this opaque always captures lifetimes in scope.
/// Right now, this is all RPITIT and TAITs, and when `lifetime_capture_rules_2024`
/// is enabled. We don't check the span of the edition, since this is done
/// on a per-opaque basis to account for nested opaques.
fn opaque_captures_all_in_scope_lifetimes<'tcx>(
tcx: TyCtxt<'tcx>,
opaque: &'tcx hir::OpaqueTy<'tcx>,
) -> bool {
/// Right now, this is all RPITIT and TAITs, and when the opaque
/// is coming from a span corresponding to edition 2024.
fn opaque_captures_all_in_scope_lifetimes<'tcx>(opaque: &'tcx hir::OpaqueTy<'tcx>) -> bool {
match opaque.origin {
// if the opaque has the `use<...>` syntax, the user is telling us that they only want
// to account for those lifetimes, so do not try to be clever.
_ if opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) => false,
hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => true,
_ if tcx.features().lifetime_capture_rules_2024() || opaque.span.at_least_rust_2024() => {
true
}
_ if opaque.span.at_least_rust_2024() => true,
hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
}
}
Expand Down Expand Up @@ -519,8 +513,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
let captures = RefCell::new(FxIndexMap::default());

let capture_all_in_scope_lifetimes =
opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque);
if capture_all_in_scope_lifetimes {
let lifetime_ident = |def_id: LocalDefId| {
let name = self.tcx.item_name(def_id.to_def_id());
Expand Down Expand Up @@ -2273,7 +2266,7 @@ fn is_late_bound_map(
}

let mut appears_in_output =
AllCollector { tcx, has_fully_capturing_opaque: false, regions: Default::default() };
AllCollector { has_fully_capturing_opaque: false, regions: Default::default() };
intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output);
if appears_in_output.has_fully_capturing_opaque {
appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id));
Expand All @@ -2286,7 +2279,7 @@ fn is_late_bound_map(
// Subtle point: because we disallow nested bindings, we can just
// ignore binders here and scrape up all names we see.
let mut appears_in_where_clause =
AllCollector { tcx, has_fully_capturing_opaque: true, regions: Default::default() };
AllCollector { has_fully_capturing_opaque: true, regions: Default::default() };
appears_in_where_clause.visit_generics(generics);
debug!(?appears_in_where_clause.regions);

Expand Down Expand Up @@ -2452,23 +2445,21 @@ fn is_late_bound_map(
}
}

struct AllCollector<'tcx> {
tcx: TyCtxt<'tcx>,
struct AllCollector {
has_fully_capturing_opaque: bool,
regions: FxHashSet<LocalDefId>,
}

impl<'v> Visitor<'v> for AllCollector<'v> {
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
impl<'tcx> Visitor<'tcx> for AllCollector {
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
self.regions.insert(def_id);
}
}

fn visit_opaque_ty(&mut self, opaque: &'v hir::OpaqueTy<'v>) {
fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
if !self.has_fully_capturing_opaque {
self.has_fully_capturing_opaque =
opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
self.has_fully_capturing_opaque = opaque_captures_all_in_scope_lifetimes(opaque);
}
intravisit::walk_opaque_ty(self, opaque);
}
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_lint/src/impl_trait_overcaptures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ declare_lint! {
///
/// ### Example
///
/// ```rust,compile_fail
/// # #![feature(lifetime_capture_rules_2024)]
/// ```rust,edition2024,compile_fail
/// # #![deny(impl_trait_redundant_captures)]
/// fn test<'a>(x: &'a i32) -> impl Sized + use<'a> { x }
/// ```
Expand Down Expand Up @@ -268,8 +267,7 @@ where
&& parent == self.parent_def_id
{
let opaque_span = self.tcx.def_span(opaque_def_id);
let new_capture_rules = opaque_span.at_least_rust_2024()
|| self.tcx.features().lifetime_capture_rules_2024();
let new_capture_rules = opaque_span.at_least_rust_2024();
if !new_capture_rules
&& !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..)))
{
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/impl-trait/implicit-capture-late.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//@ known-bug: #117647
//@ edition: 2024

#![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>> {
fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> { //~ ['a: o]
//~^ ERROR cannot capture higher-ranked lifetime
Box::new(x)
}

Expand Down
6 changes: 3 additions & 3 deletions tests/ui/impl-trait/implicit-capture-late.stderr
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
--> $DIR/implicit-capture-late.rs:10:55
--> $DIR/implicit-capture-late.rs:9:55
|
LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
| ^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/implicit-capture-late.rs:10:36
--> $DIR/implicit-capture-late.rs:9:36
|
LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
| ^^

error: ['a: o]
--> $DIR/implicit-capture-late.rs:10:55
--> $DIR/implicit-capture-late.rs:9:55
|
LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
| ^^^^^^^^^^^
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/impl-trait/precise-capturing/higher-ranked.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
//@ check-pass
//@ edition: 2024

// Show how precise captures allow us to skip capturing a higher-ranked lifetime

#![feature(lifetime_capture_rules_2024)]

trait Trait<'a> {
type Item;
}
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/impl-trait/precise-capturing/outlives.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
//@ check-pass
//@ edition: 2024

// Show that precise captures allow us to skip a lifetime param for outlives

#![feature(lifetime_capture_rules_2024)]

fn hello<'a: 'a, 'b: 'b>() -> impl Sized + use<'a> { }

fn outlives<'a, T: 'a>(_: T) {}
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/impl-trait/variance.e2024.stderr
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
error: ['a: *, 'a: o]
--> $DIR/variance.rs:13:36
--> $DIR/variance.rs:11:36
|
LL | fn not_captured_early<'a: 'a>() -> impl Sized {}
| ^^^^^^^^^^

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

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

error: ['a: o]
--> $DIR/variance.rs:25:36
--> $DIR/variance.rs:21:36
|
LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
26 changes: 0 additions & 26 deletions tests/ui/impl-trait/variance.new.stderr

This file was deleted.

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

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

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

error: ['a: o]
--> $DIR/variance.rs:25:36
--> $DIR/variance.rs:21:36
|
LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
10 changes: 3 additions & 7 deletions tests/ui/impl-trait/variance.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//@ revisions: old new e2024
//@ revisions: old e2024
//@[e2024] edition: 2024

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

#![feature(rustc_attrs)]
#![allow(internal_features)]
#![rustc_variance_of_opaques]
Expand All @@ -12,15 +10,13 @@ impl<T> Captures<'_> for T {}

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

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

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

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

Expand Down
Loading