Skip to content

Commit b0466bb

Browse files
authored
Merge pull request #223 from dtolnay/arc
Infer Sync+Send bound for Arc<Self> methods with default body
2 parents 9ed6489 + 066f06e commit b0466bb

File tree

2 files changed

+45
-11
lines changed

2 files changed

+45
-11
lines changed

src/expand.rs

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ use std::mem;
99
use syn::punctuated::Punctuated;
1010
use syn::visit_mut::{self, VisitMut};
1111
use syn::{
12-
parse_quote, parse_quote_spanned, Attribute, Block, FnArg, GenericParam, Generics, Ident,
13-
ImplItem, Lifetime, LifetimeDef, Pat, PatIdent, Receiver, ReturnType, Signature, Stmt, Token,
14-
TraitItem, Type, TypePath, WhereClause,
12+
parse_quote, parse_quote_spanned, Attribute, Block, FnArg, GenericArgument, GenericParam,
13+
Generics, Ident, ImplItem, Lifetime, LifetimeDef, Pat, PatIdent, PathArguments, Receiver,
14+
ReturnType, Signature, Stmt, Token, TraitItem, Type, TypePath, WhereClause,
1515
};
1616

1717
impl ToTokens for Item {
@@ -229,23 +229,46 @@ fn transform_sig(
229229
.push(parse_quote_spanned!(default_span=> 'async_trait));
230230

231231
if has_self {
232-
let bounds = match sig.inputs.iter().next() {
232+
let bounds: &[InferredBound] = match sig.inputs.iter().next() {
233233
Some(FnArg::Receiver(Receiver {
234234
reference: Some(_),
235235
mutability: None,
236236
..
237-
})) => [InferredBound::Sync],
237+
})) => &[InferredBound::Sync],
238238
Some(FnArg::Typed(arg))
239-
if match (arg.pat.as_ref(), arg.ty.as_ref()) {
240-
(Pat::Ident(pat), Type::Reference(ty)) => {
241-
pat.ident == "self" && ty.mutability.is_none()
242-
}
239+
if match arg.pat.as_ref() {
240+
Pat::Ident(pat) => pat.ident == "self",
243241
_ => false,
244242
} =>
245243
{
246-
[InferredBound::Sync]
244+
match arg.ty.as_ref() {
245+
// self: &Self
246+
Type::Reference(ty) if ty.mutability.is_none() => &[InferredBound::Sync],
247+
// self: Arc<Self>
248+
Type::Path(ty)
249+
if {
250+
let segment = ty.path.segments.last().unwrap();
251+
segment.ident == "Arc"
252+
&& match &segment.arguments {
253+
PathArguments::AngleBracketed(arguments) => {
254+
arguments.args.len() == 1
255+
&& match &arguments.args[0] {
256+
GenericArgument::Type(Type::Path(arg)) => {
257+
arg.path.is_ident("Self")
258+
}
259+
_ => false,
260+
}
261+
}
262+
_ => false,
263+
}
264+
} =>
265+
{
266+
&[InferredBound::Sync, InferredBound::Send]
267+
}
268+
_ => &[InferredBound::Send],
269+
}
247270
}
248-
_ => [InferredBound::Send],
271+
_ => &[InferredBound::Send],
249272
};
250273

251274
let bounds = bounds.iter().filter_map(|bound| {

tests/test.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,3 +1450,14 @@ pub mod issue204 {
14501450
async fn g(arg: *const impl Trait);
14511451
}
14521452
}
1453+
1454+
// https://github.com/dtolnay/async-trait/issues/210
1455+
pub mod issue210 {
1456+
use async_trait::async_trait;
1457+
use std::sync::Arc;
1458+
1459+
#[async_trait]
1460+
pub trait Trait {
1461+
async fn f(self: Arc<Self>) {}
1462+
}
1463+
}

0 commit comments

Comments
 (0)