dtolnay / async-trait

Type erasure for async trait methods
Apache License 2.0
1.84k stars 85 forks source link

Nested `_` and `..` patterns under 2018 edition can trigger rust_2021_compatibility warning #234

Closed dtolnay closed 1 year ago

dtolnay commented 1 year ago

The code generated by async-trait should never exhibit edition sensitive behavior differences. The fact that async-trait involves the use of move closures internally is an implementation detail. If the behavior is sensitive to edition of the caller's crate, that is a bug in async-trait.

#![warn(rust_2021_compatibility)]

use async_trait::async_trait;

pub struct Droppable;

impl Drop for Droppable {
    fn drop(&mut self) {}
}

pub struct Tuple<T, U>(T, U);

#[async_trait]
pub trait Trait {
    async fn create(arg: Tuple<Droppable, i32>);
}

pub struct Struct;
#[async_trait]
impl Trait for Struct {
    async fn create(Tuple(_, _int): Tuple<Droppable, i32>) {}
}
warning: changes to closure capture in Rust 2021 will affect drop order
  --> src/main.rs:22:60
   |
22 |     async fn create(Tuple(_, _int): Tuple<Droppable, i32>) {}
   |                     --------------                         ^-
   |                     |                                       |
   |                     |                                       in Rust 2018, `__arg0` is dropped here, but in Rust 2021, only `__arg0.1` will be dropped here as part of the closure
   |                     in Rust 2018, this closure captures all of `__arg0`, but in Rust 2021, it will only capture `__arg0.1`
   |
   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
  --> src/main.rs:1:9
   |
1  | #![warn(rust_2021_compatibility)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^
   = note: `#[warn(rust_2021_incompatible_closure_captures)]` implied by `#[warn(rust_2021_compatibility)]`
help: add a dummy let to cause `__arg0` to be fully captured
   |
22 |     async fn create(Tuple(_, _int): Tuple<Droppable, i32>) { let _ = &__arg0;}
   |                                                              ++++++++++++++++
#[async_trait]
impl Trait for Struct {
    async fn create(Tuple { 1: _int, .. }: Tuple<Droppable, i32>) {}
}
warning: changes to closure capture in Rust 2021 will affect drop order
  --> src/main.rs:22:67
   |
22 |     async fn create(Tuple { 1: _int, .. }: Tuple<Droppable, i32>) {}
   |                     ---------------------                         ^-
   |                     |                                              |
   |                     |                                              in Rust 2018, `__arg0` is dropped here, but in Rust 2021, only `__arg0.1` will be dropped here as part of the closure
   |                     in Rust 2018, this closure captures all of `__arg0`, but in Rust 2021, it will only capture `__arg0.1`
   |
   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
  --> src/main.rs:1:9
   |
1  | #![warn(rust_2021_compatibility)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^
   = note: `#[warn(rust_2021_incompatible_closure_captures)]` implied by `#[warn(rust_2021_compatibility)]`
help: add a dummy let to cause `__arg0` to be fully captured
   |
22 |     async fn create(Tuple { 1: _int, .. }: Tuple<Droppable, i32>) { let _ = &__arg0;}
   |                                                                     ++++++++++++++++