Skip to content

2024 impl_trait_overcaptures false negative, plus bad suggestion in 2024 #132809

Closed
@ehuss

Description

@ehuss

The 2024 migration for actix-web-lab@0.23.0 failed to detect a situation where an impl trait needs some kind of capture. The following error occurs after updating to 2024:

error[E0515]: cannot return value referencing local data `this`
   --> examples/from_fn.rs:100:26
    |
100 |             async move { Self::mw_cb(&this, req, next).await }
    |                          ^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^
    |                          |           |
    |                          |           `this` is borrowed here
    |                          returns a value referencing data owned by the current function
    |
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
   --> examples/from_fn.rs:100:26
    |
100 |             async move { Self::mw_cb(&this, req, next).await }
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a precise capturing bound to avoid overcapturing
    |
72  |     ) -> Result<ServiceResponse<impl MessageBody + use<impl MessageBody + 'static>>, Error> {
    |

I would expect impl_trait_overcaptures to migrate this, or if migration isn't possible to at least generate a warning.

Additionally, the suggestion provided in this error message is not valid syntax. use<> cannot have impl MessageBody.

I believe this is an example of APIT migration. That is, the following change I think is a suggestion it could provide:

--- a/examples/from_fn.rs
+++ b/examples/from_fn.rs
@@ -65,11 +65,11 @@ async fn timeout_10secs(
 struct MyMw(bool);

 impl MyMw {
-    async fn mw_cb(
+    async fn mw_cb<T: MessageBody + 'static>(
         &self,
         req: ServiceRequest,
-        next: Next<impl MessageBody + 'static>,
-    ) -> Result<ServiceResponse<impl MessageBody>, Error> {
+        next: Next<T>,
+    ) -> Result<ServiceResponse<impl MessageBody + use<T>>, Error> {
         let mut res = match self.0 {
             true => req.into_response("short-circuited").map_into_right_body(),
             false => next.call(req).await?.map_into_left_body(),

Here the impl trait gets lifted to have a named type parameter which can then be used in the use<> bound.

Or...There might be other suggestions, I don't know. The offending code involves some tricky async-block stuff.

Meta

rustc --version --verbose:

rustc 1.84.0-nightly (59cec72a5 2024-11-08)
binary: rustc
commit-hash: 59cec72a57af178767a7b8e7f624b06cc50f1087
commit-date: 2024-11-08
host: aarch64-unknown-linux-gnu
release: 1.84.0-nightly
LLVM version: 19.1.3

Metadata

Metadata

Labels

A-edition-2024Area: The 2024 editionA-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.C-bugCategory: This is a bug.D-editionDiagnostics: An error or lint that should account for edition differences.D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.L-false-negativeLint: False negative (should have fired but didn't).L-impl_trait_overcapturesLint: impl_trait_overcapturesT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions