Skip to content

Commit c3ef648

Browse files
authored
Merge pull request #201 from dtolnay/impltrait
Add 'async_trait lifetime to impl Trait arguments
2 parents 9a323ed + 1e2a850 commit c3ef648

File tree

4 files changed

+42
-3
lines changed

4 files changed

+42
-3
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ proc-macro = true
1717
[dependencies]
1818
proc-macro2 = "1.0"
1919
quote = "1.0"
20-
syn = { version = "1.0.84", features = ["full", "visit-mut"] }
20+
syn = { version = "1.0.96", features = ["full", "visit-mut"] }
2121

2222
[dev-dependencies]
2323
futures = "0.3"

src/expand.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::lifetime::CollectLifetimes;
1+
use crate::lifetime::{AddLifetimeToImplTrait, CollectLifetimes};
22
use crate::parse::Item;
33
use crate::receiver::{has_self_in_block, has_self_in_sig, mut_pat, ReplaceSelf};
44
use proc_macro2::TokenStream;
@@ -283,6 +283,7 @@ fn transform_sig(
283283
let m = mut_pat(&mut arg.pat);
284284
arg.pat = parse_quote!(#m #positional);
285285
}
286+
AddLifetimeToImplTrait.visit_type_mut(&mut arg.ty);
286287
}
287288
}
288289
}

src/lifetime.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use proc_macro2::Span;
22
use syn::visit_mut::{self, VisitMut};
3-
use syn::{GenericArgument, Lifetime, Receiver, TypeReference};
3+
use syn::{
4+
parse_quote_spanned, Expr, GenericArgument, Lifetime, Receiver, TypeImplTrait, TypeReference,
5+
};
46

57
pub struct CollectLifetimes {
68
pub elided: Vec<Lifetime>,
@@ -62,3 +64,22 @@ impl VisitMut for CollectLifetimes {
6264
visit_mut::visit_generic_argument_mut(self, gen);
6365
}
6466
}
67+
68+
pub struct AddLifetimeToImplTrait;
69+
70+
impl VisitMut for AddLifetimeToImplTrait {
71+
fn visit_type_impl_trait_mut(&mut self, ty: &mut TypeImplTrait) {
72+
let span = ty.impl_token.span;
73+
let lifetime = parse_quote_spanned!(span=> 'async_trait);
74+
ty.bounds.insert(0, lifetime);
75+
if let Some(punct) = ty.bounds.pairs_mut().next().unwrap().punct_mut() {
76+
punct.span = span;
77+
}
78+
}
79+
80+
fn visit_expr_mut(&mut self, _e: &mut Expr) {
81+
// Do not recurse into impl Traits inside of an array length expression.
82+
//
83+
// fn outer(arg: [u8; { fn inner(_: impl Trait) {}; 0 }]);
84+
}
85+
}

tests/test.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,23 @@ pub mod issue169 {
13741374
pub fn test(_t: &dyn Trait) {}
13751375
}
13761376

1377+
// https://github.com/dtolnay/async-trait/issues/177
1378+
pub mod issue177 {
1379+
use async_trait::async_trait;
1380+
1381+
#[async_trait]
1382+
pub trait Trait {
1383+
async fn foo(&self, _callback: impl FnMut(&str) + Send) {}
1384+
}
1385+
1386+
pub struct Struct;
1387+
1388+
#[async_trait]
1389+
impl Trait for Struct {
1390+
async fn foo(&self, _callback: impl FnMut(&str) + Send) {}
1391+
}
1392+
}
1393+
13771394
// https://github.com/dtolnay/async-trait/issues/183
13781395
pub mod issue183 {
13791396
#![deny(clippy::shadow_same)]

0 commit comments

Comments
 (0)