Skip to content

Commit a971212

Browse files
committed
Auto merge of #127672 - compiler-errors:precise-capturing, r=spastorino
Stabilize opaque type precise capturing (RFC 3617) This PR partially stabilizes opaque type *precise capturing*, which was specified in [RFC 3617](rust-lang/rfcs#3617), and whose syntax was amended by FCP in [#125836](#125836). This feature, as stabilized here, gives us a way to explicitly specify the generic lifetime parameters that an RPIT-like opaque type captures. This solves the problem of overcapturing, for lifetime parameters in these opaque types, and will allow the Lifetime Capture Rules 2024 ([RFC 3498](rust-lang/rfcs#3498)) to be fully stabilized for RPIT in Rust 2024. ### What are we stabilizing? This PR stabilizes the use of a `use<'a, T>` bound in return-position impl Trait opaque types. Such a bound fully specifies the set of generic parameters captured by the RPIT opaque type, entirely overriding the implicit default behavior. E.g.: ```rust fn does_not_capture<'a, 'b>() -> impl Sized + use<'a> {} // ~~~~~~~~~~~~~~~~~~~~ // This RPIT opaque type does not capture `'b`. ``` The way we would suggest thinking of `impl Trait` types *without* an explicit `use<..>` bound is that the `use<..>` bound has been *elided*, and that the bound is filled in automatically by the compiler according to the edition-specific capture rules. All non-`'static` lifetime parameters, named (i.e. non-APIT) type parameters, and const parameters in scope are valid to name, including an elided lifetime if such a lifetime would also be valid in an outlives bound, e.g.: ```rust fn elided(x: &u8) -> impl Sized + use<'_> { x } ``` Lifetimes must be listed before type and const parameters, but otherwise the ordering is not relevant to the `use<..>` bound. Captured parameters may not be duplicated. For now, only one `use<..>` bound may appear in a bounds list. It may appear anywhere within the bounds list. ### How does this differ from the RFC? This stabilization differs from the RFC in one respect: the RFC originally specified `use<'a, T>` as syntactically part of the RPIT type itself, e.g.: ```rust fn capture<'a>() -> impl use<'a> Sized {} ``` However, settling on the final syntax was left as an open question. T-lang later decided via FCP in [#125836](#125836) to treat `use<..>` as a syntactic bound instead, e.g.: ```rust fn capture<'a>() -> impl Sized + use<'a> {} ``` ### What aren't we stabilizing? The key goal of this PR is to stabilize the parts of *precise capturing* that are needed to enable the migration to Rust 2024. There are some capabilities of *precise capturing* that the RFC specifies but that we're not stabilizing here, as these require further work on the type system. We hope to lift these limitations later. The limitations that are part of this PR were specified in the [RFC's stabilization strategy](https://rust-lang.github.io/rfcs/3617-precise-capturing.html#stabilization-strategy). #### Not capturing type or const parameters The RFC addresses the overcapturing of type and const parameters; that is, it allows for them to not be captured in opaque types. We're not stabilizing that in this PR. Since all in scope generic type and const parameters are implicitly captured in all editions, this is not needed for the migration to Rust 2024. For now, when using `use<..>`, all in scope type and const parameters must be nameable (i.e., APIT cannot be used) and included as arguments. For example, this is an error because `T` is in scope and not included as an argument: ```rust fn test<T>() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all type parameters in scope in `use<...>` ``` This is due to certain current limitations in the type system related to how generic parameters are represented as captured (i.e. bivariance) and how inference operates. We hope to relax this in the future, and this stabilization is forward compatible with doing so. #### Precise capturing for return-position impl Trait **in trait** (RPITIT) The RFC specifies precise capturing for RPITIT. We're not stabilizing that in this PR. Since RPITIT already adheres to the Lifetime Capture Rules 2024, this isn't needed for the migration to Rust 2024. The effect of this is that the anonymous associated types created by RPITITs must continue to capture all of the lifetime parameters in scope, e.g.: ```rust trait Foo<'a> { fn test() -> impl Sized + use<Self>; //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } ``` To allow this involves a meaningful amount of type system work related to adding variance to GATs or reworking how generics are represented in RPITITs. We plan to do this work separately from the stabilization. See: - #124029 Supporting precise capturing for RPITIT will also require us to implement a new algorithm for detecting refining capture behavior. This may involve looking through type parameters to detect cases where the impl Trait type in an implementation captures fewer lifetimes than the corresponding RPITIT in the trait definition, e.g.: ```rust trait Foo { fn rpit() -> impl Sized + use<Self>; } impl<'a> Foo for &'a () { // This is "refining" due to not capturing `'a` which // is implied by the trait's `use<Self>`. fn rpit() -> impl Sized + use<>; // This is not "refining". fn rpit() -> impl Sized + use<'a>; } ``` This stabilization is forward compatible with adding support for this later. ### The technical details This bound is purely syntactical and does not lower to a [`Clause`](https://doc.rust-lang.org/1.79.0/nightly-rustc/rustc_middle/ty/type.ClauseKind.html) in the type system. For the purposes of the type system (and for the types team's curiosity regarding this stabilization), we have no current need to represent this as a `ClauseKind`. Since opaques already capture a variable set of lifetimes depending on edition and their syntactical position (e.g. RPIT vs RPITIT), a `use<..>` bound is just a way to explicitly rather than implicitly specify that set of lifetimes, and this only affects opaque type lowering from AST to HIR. ### FCP plan While there's much discussion of the type system here, the feature in this PR is implemented internally as a transformation that happens before lowering to the type system layer. We already support impl Trait types partially capturing the in scope lifetimes; we just currently only expose that implicitly. So, in my (errs's) view as a types team member, there's nothing for types to weigh in on here with respect to the implementation being stabilized, and I'd suggest a lang-only proposed FCP (though we'll of course CC the team below). ### Authorship and acknowledgments This stabilization report was coauthored by compiler-errors and TC. TC would like to acknowledge the outstanding and speedy work that compiler-errors has done to make this feature happen. compiler-errors thanks TC for authoring the RFC, for all of his involvement in this feature's development, and pushing the Rust 2024 edition forward. ### Open items We're doing some things in parallel here. In signaling the intention to stabilize, we want to uncover any latent issues so we can be sure they get addressed. We want to give the maximum time for discussion here to happen by starting it while other remaining miscellaneous work proceeds. That work includes: - [x] Look into `syn` support. - dtolnay/syn#1677 - dtolnay/syn#1707 - [x] Look into `rustfmt` support. - #126754 - [x] Look into `rust-analyzer` support. - rust-lang/rust-analyzer#17598 - rust-lang/rust-analyzer#17676 - [x] Look into `rustdoc` support. - #127228 - #127632 - #127658 - [x] Suggest this feature to RfL (a known nightly user). - [x] Add a chapter to the edition guide. - rust-lang/edition-guide#316 - [x] Update the Reference. - rust-lang/reference#1577 ### (Selected) implementation history * rust-lang/rfcs#3498 * rust-lang/rfcs#3617 * #123468 * #125836 * #126049 * #126753 Closes #123432. cc `@rust-lang/lang` `@rust-lang/types` `@rustbot` labels +T-lang +I-lang-nominated +A-impl-trait +F-precise_capturing Tracking: - #123432 ---- For the compiler reviewer, I'll leave some inline comments about diagnostics fallout :^) r? compiler
2 parents fdf61d4 + 84044cd commit a971212

File tree

79 files changed

+194
-320
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+194
-320
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

-1
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
556556
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
557557
gate_all!(postfix_match, "postfix match is experimental");
558558
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
559-
gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
560559
gate_all!(global_registration, "global registration is experimental");
561560
gate_all!(return_type_notation, "return type notation is experimental");
562561

compiler/rustc_feature/src/accepted.rs

+2
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ declare_features! (
309309
(accepted, param_attrs, "1.39.0", Some(60406)),
310310
/// Allows parentheses in patterns.
311311
(accepted, pattern_parentheses, "1.31.0", Some(51087)),
312+
/// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
313+
(accepted, precise_capturing, "CURRENT_RUSTC_VERSION", Some(123432)),
312314
/// Allows procedural macros in `proc-macro` crates.
313315
(accepted, proc_macro, "1.29.0", Some(38356)),
314316
/// Allows multi-segment paths in attributes and derives.

compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,6 @@ declare_features! (
561561
(unstable, patchable_function_entry, "1.81.0", Some(123115)),
562562
/// Allows postfix match `expr.match { ... }`
563563
(unstable, postfix_match, "1.79.0", Some(121618)),
564-
/// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
565-
(unstable, precise_capturing, "1.79.0", Some(123432)),
566564
/// Allows macro attributes on expressions, statements and non-inline modules.
567565
(unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
568566
/// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.

compiler/rustc_hir/src/hir.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2773,7 +2773,6 @@ impl PreciseCapturingArg<'_> {
27732773
/// resolution to. Lifetimes don't have this problem, and for them, it's actually
27742774
/// kind of detrimental to use a custom node type versus just using [`Lifetime`],
27752775
/// since resolve_bound_vars operates on `Lifetime`s.
2776-
// FIXME(precise_capturing): Investigate storing this as a path instead?
27772776
#[derive(Debug, Clone, Copy, HashStable_Generic)]
27782777
pub struct PreciseCapturingNonLifetimeArg {
27792778
pub hir_id: HirId,

compiler/rustc_lint/src/impl_trait_overcaptures.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ declare_lint! {
2727
/// ### Example
2828
///
2929
/// ```rust,compile_fail
30-
/// # #![feature(precise_capturing)]
31-
/// # #![allow(incomplete_features)]
3230
/// # #![deny(impl_trait_overcaptures)]
3331
/// # use std::fmt::Display;
3432
/// let mut x = vec![];
@@ -56,7 +54,6 @@ declare_lint! {
5654
pub IMPL_TRAIT_OVERCAPTURES,
5755
Allow,
5856
"`impl Trait` will capture more lifetimes than possibly intended in edition 2024",
59-
@feature_gate = precise_capturing;
6057
//@future_incompatible = FutureIncompatibleInfo {
6158
// reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
6259
// reference: "<FIXME>",
@@ -75,8 +72,7 @@ declare_lint! {
7572
/// ### Example
7673
///
7774
/// ```rust,compile_fail
78-
/// # #![feature(precise_capturing, lifetime_capture_rules_2024)]
79-
/// # #![allow(incomplete_features)]
75+
/// # #![feature(lifetime_capture_rules_2024)]
8076
/// # #![deny(impl_trait_redundant_captures)]
8177
/// fn test<'a>(x: &'a i32) -> impl Sized + use<'a> { x }
8278
/// ```
@@ -90,7 +86,6 @@ declare_lint! {
9086
pub IMPL_TRAIT_REDUNDANT_CAPTURES,
9187
Warn,
9288
"redundant precise-capturing `use<...>` syntax on an `impl Trait`",
93-
@feature_gate = precise_capturing;
9489
}
9590

9691
declare_lint_pass!(

compiler/rustc_parse/src/parser/ty.rs

-1
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,6 @@ impl<'a> Parser<'a> {
851851
// lifetimes and ident params (including SelfUpper). These are validated later
852852
// for order, duplication, and whether they actually reference params.
853853
let use_span = self.prev_token.span;
854-
self.psess.gated_spans.gate(sym::precise_capturing, use_span);
855854
let (args, args_span) = self.parse_precise_capturing_args()?;
856855
GenericBound::Use(args, use_span.to(args_span))
857856
} else {

compiler/rustc_trait_selection/src/error_reporting/infer/region.rs

+4-18
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol};
1717
use rustc_type_ir::Upcast as _;
1818

1919
use super::nice_region_error::find_anon_type;
20-
use super::{nice_region_error, ObligationCauseAsDiagArg};
21-
use crate::error_reporting::infer::ObligationCauseExt as _;
20+
use super::ObligationCauseAsDiagArg;
21+
use crate::error_reporting::infer::ObligationCauseExt;
2222
use crate::error_reporting::TypeErrCtxt;
2323
use crate::errors::{
2424
self, note_and_explain, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound,
@@ -1212,22 +1212,8 @@ pub fn unexpected_hidden_region_diagnostic<'a, 'tcx>(
12121212
hidden_region,
12131213
"",
12141214
);
1215-
if let Some(reg_info) = tcx.is_suitable_region(generic_param_scope, hidden_region) {
1216-
if infcx.tcx.features().precise_capturing {
1217-
suggest_precise_capturing(tcx, opaque_ty_key.def_id, hidden_region, &mut err);
1218-
} else {
1219-
let fn_returns = tcx.return_type_impl_or_dyn_traits(reg_info.def_id);
1220-
nice_region_error::suggest_new_region_bound(
1221-
tcx,
1222-
&mut err,
1223-
fn_returns,
1224-
hidden_region.to_string(),
1225-
None,
1226-
format!("captures `{hidden_region}`"),
1227-
None,
1228-
Some(reg_info.def_id),
1229-
)
1230-
}
1215+
if let Some(_) = tcx.is_suitable_region(generic_param_scope, hidden_region) {
1216+
suggest_precise_capturing(tcx, opaque_ty_key.def_id, hidden_region, &mut err);
12311217
}
12321218
}
12331219
ty::RePlaceholder(_) => {

tests/rustdoc-json/impl-trait-precise-capturing.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![feature(precise_capturing)]
2-
31
//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[0]" \"\'a\"
42
//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[1]" \"T\"
53
//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[2]" \"N\"

tests/rustdoc/impl-trait-precise-capturing.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//@ aux-build:precise-capturing.rs
22

33
#![crate_name = "foo"]
4-
#![feature(precise_capturing)]
54

65
extern crate precise_capturing;
76

tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ LL | | (a, b)
2626
LL | | }
2727
| |_^
2828
|
29-
help: to declare that `impl Trait<'a>` captures `'b`, you can add an explicit `'b` lifetime bound
29+
help: add a `use<...>` bound to explicitly capture `'b`
3030
|
31-
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
32-
| ++++
31+
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + use<'a, 'b> {
32+
| +++++++++++++
3333

3434
error: aborting due to 2 previous errors
3535

tests/ui/borrowck/alias-liveness/opaque-type-param.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ LL | fn foo<'a>(s: &'a str) -> impl Trait + 'static {
77
| hidden type `impl Trait + 'static` captures the lifetime `'a` as defined here
88
LL | bar(s)
99
| ^^^^^^
10+
|
11+
help: add a `use<...>` bound to explicitly capture `'a`
12+
|
13+
LL | fn foo<'a>(s: &'a str) -> impl Trait + 'static + use<'a> {
14+
| +++++++++
1015

1116
error: aborting due to 1 previous error
1217

tests/ui/const-generics/generic_const_exprs/issue-109141.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ LL | fn a(&self) -> impl Iterator {
3030
LL | self.0.iter_mut()
3131
| ^^^^^^^^^^^^^^^^^
3232
|
33-
help: to declare that `impl Iterator` captures `'_`, you can add an explicit `'_` lifetime bound
33+
help: add a `use<...>` bound to explicitly capture `'_`
3434
|
35-
LL | fn a(&self) -> impl Iterator + '_ {
36-
| ++++
35+
LL | fn a(&self) -> impl Iterator + use<'_> {
36+
| +++++++++
3737

3838
error: aborting due to 3 previous errors
3939

tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ LL | fn foo(x: &Vec<i32>) -> impl Sized {
88
LL | x
99
| ^
1010
|
11-
help: to declare that `impl Sized` captures `'_`, you can add an explicit `'_` lifetime bound
11+
help: add a `use<...>` bound to explicitly capture `'_`
1212
|
13-
LL | fn foo(x: &Vec<i32>) -> impl Sized + '_ {
14-
| ++++
13+
LL | fn foo(x: &Vec<i32>) -> impl Sized + use<'_> {
14+
| +++++++++
1515

1616
error: aborting due to 1 previous error
1717

tests/ui/feature-gates/feature-gate-precise-capturing.rs

-4
This file was deleted.

tests/ui/feature-gates/feature-gate-precise-capturing.stderr

-13
This file was deleted.

tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ LL | fn step2<'a, 'b: 'a>() -> impl Sized + 'a {
88
LL | step1::<'a, 'b>()
99
| ^^^^^^^^^^^^^^^^^
1010
|
11-
help: to declare that `impl Sized + 'a` captures `'b`, you can add an explicit `'b` lifetime bound
11+
help: add a `use<...>` bound to explicitly capture `'b`
1212
|
13-
LL | fn step2<'a, 'b: 'a>() -> impl Sized + 'a + 'b {
14-
| ++++
13+
LL | fn step2<'a, 'b: 'a>() -> impl Sized + 'a + use<'a, 'b> {
14+
| +++++++++++++
1515

1616
error: aborting due to 1 previous error
1717

tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ LL | fn hide<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
88
LL | x
99
| ^
1010
|
11-
help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound
11+
help: add a `use<...>` bound to explicitly capture `'b`
1212
|
13-
LL | fn hide<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a + 'b {
14-
| ++++
13+
LL | fn hide<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a + use<'a, 'b, T> {
14+
| ++++++++++++++++
1515

1616
error: aborting due to 1 previous error
1717

tests/ui/impl-trait/call_method_ambiguous.next.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0282]: type annotations needed
2-
--> $DIR/call_method_ambiguous.rs:28:13
2+
--> $DIR/call_method_ambiguous.rs:26:13
33
|
44
LL | let mut iter = foo(n - 1, m);
55
| ^^^^^^^^

tests/ui/impl-trait/call_method_ambiguous.rs

-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
//@[next] compile-flags: -Znext-solver
33
//@[current] run-pass
44

5-
#![feature(precise_capturing)]
6-
75
trait Get {
86
fn get(&mut self) -> u32;
97
}

tests/ui/impl-trait/hidden-lifetimes.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
88
LL | x
99
| ^
1010
|
11-
help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound
11+
help: add a `use<...>` bound to explicitly capture `'b`
1212
|
13-
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b {
14-
| ++++
13+
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + use<'a, 'b, T> {
14+
| ++++++++++++++++
1515

1616
error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds
1717
--> $DIR/hidden-lifetimes.rs:46:5
@@ -23,10 +23,10 @@ LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl S
2323
LL | x
2424
| ^
2525
|
26-
help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound
26+
help: add a `use<...>` bound to explicitly capture `'b`
2727
|
28-
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a + 'b {
29-
| ++++
28+
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a + use<'a, 'b, T> {
29+
| ++++++++++++++++
3030

3131
error: aborting due to 2 previous errors
3232

tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![feature(precise_capturing)]
2-
31
use std::future::Future;
42
use std::pin::Pin;
53

tests/ui/impl-trait/in-trait/cannot-capture-intersection.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0700]: hidden type for `impl Future<Output = i32>` captures lifetime that does not appear in bounds
2-
--> $DIR/cannot-capture-intersection.rs:24:9
2+
--> $DIR/cannot-capture-intersection.rs:22:9
33
|
44
LL | fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> {
55
| ------------------------- opaque type defined here

tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ LL | fn elided(x: &i32) -> impl Copy { x }
77
| | opaque type defined here
88
| hidden type `&i32` captures the anonymous lifetime defined here
99
|
10-
help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound
10+
help: add a `use<...>` bound to explicitly capture `'_`
1111
|
12-
LL | fn elided(x: &i32) -> impl Copy + '_ { x }
13-
| ++++
12+
LL | fn elided(x: &i32) -> impl Copy + use<'_> { x }
13+
| +++++++++
1414

1515
error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear in bounds
1616
--> $DIR/must_outlive_least_region_or_bound.rs:6:44
@@ -21,10 +21,10 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
2121
| | opaque type defined here
2222
| hidden type `&'a i32` captures the lifetime `'a` as defined here
2323
|
24-
help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound
24+
help: add a `use<...>` bound to explicitly capture `'a`
2525
|
26-
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
27-
| ++++
26+
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + use<'a> { x }
27+
| +++++++++
2828

2929
error: lifetime may not live long enough
3030
--> $DIR/must_outlive_least_region_or_bound.rs:9:46
@@ -108,10 +108,10 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
108108
LL | move |_| println!("{}", y)
109109
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
110110
|
111-
help: to declare that `impl Fn(&'a u32)` captures `'b`, you can add an explicit `'b` lifetime bound
111+
help: add a `use<...>` bound to explicitly capture `'b`
112112
|
113-
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b {
114-
| ++++
113+
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + use<'a, 'b> {
114+
| +++++++++++++
115115

116116
error[E0310]: the parameter type `T` may not live long enough
117117
--> $DIR/must_outlive_least_region_or_bound.rs:47:5

tests/ui/impl-trait/nested-return-type4.stderr

+3-7
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,10 @@ LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized
88
LL | async move { let _s = s; }
99
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1010
|
11-
help: to declare that `impl Future<Output = impl Sized>` captures `'s`, you can add an explicit `'s` lifetime bound
11+
help: add a `use<...>` bound to explicitly capture `'s`
1212
|
13-
LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> + 's {
14-
| ++++
15-
help: to declare that `impl Sized` captures `'s`, you can add an explicit `'s` lifetime bound
16-
|
17-
LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized + 's> {
18-
| ++++
13+
LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> + use<'s> {
14+
| +++++++++
1915

2016
error: aborting due to 1 previous error
2117

tests/ui/impl-trait/precise-capturing/apit.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![feature(precise_capturing)]
2-
31
fn hello(_: impl Sized + use<>) {}
42
//~^ ERROR `use<...>` precise capturing syntax not allowed in argument-position `impl Trait`
53

tests/ui/impl-trait/precise-capturing/apit.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: `use<...>` precise capturing syntax not allowed in argument-position `impl Trait`
2-
--> $DIR/apit.rs:3:26
2+
--> $DIR/apit.rs:1:26
33
|
44
LL | fn hello(_: impl Sized + use<>) {}
55
| ^^^^^

tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![feature(precise_capturing)]
2-
31
fn no_elided_lt() -> impl Sized + use<'_> {}
42
//~^ ERROR missing lifetime specifier
53
//~| ERROR expected lifetime parameter in `use<...>` precise captures list, found `'_`

tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0106]: missing lifetime specifier
2-
--> $DIR/bad-lifetimes.rs:3:39
2+
--> $DIR/bad-lifetimes.rs:1:39
33
|
44
LL | fn no_elided_lt() -> impl Sized + use<'_> {}
55
| ^^ expected named lifetime parameter
@@ -11,21 +11,21 @@ LL | fn no_elided_lt() -> impl Sized + use<'static> {}
1111
| ~~~~~~~
1212

1313
error[E0261]: use of undeclared lifetime name `'missing`
14-
--> $DIR/bad-lifetimes.rs:10:37
14+
--> $DIR/bad-lifetimes.rs:8:37
1515
|
1616
LL | fn missing_lt() -> impl Sized + use<'missing> {}
1717
| - ^^^^^^^^ undeclared lifetime
1818
| |
1919
| help: consider introducing lifetime `'missing` here: `<'missing>`
2020

2121
error: expected lifetime parameter in `use<...>` precise captures list, found `'_`
22-
--> $DIR/bad-lifetimes.rs:3:39
22+
--> $DIR/bad-lifetimes.rs:1:39
2323
|
2424
LL | fn no_elided_lt() -> impl Sized + use<'_> {}
2525
| ^^
2626

2727
error: expected lifetime parameter in `use<...>` precise captures list, found `'static`
28-
--> $DIR/bad-lifetimes.rs:7:36
28+
--> $DIR/bad-lifetimes.rs:5:36
2929
|
3030
LL | fn static_lt() -> impl Sized + use<'static> {}
3131
| ^^^^^^^

0 commit comments

Comments
 (0)