Skip to content

Commit 1cab7e4

Browse files
authored
Merge pull request #282 from dtolnay/impltrait
Support impl Trait in return type
2 parents 7d8519d + 3af8236 commit 1cab7e4

File tree

4 files changed

+44
-3
lines changed

4 files changed

+44
-3
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
strategy:
2525
fail-fast: false
2626
matrix:
27-
rust: [nightly, beta, stable, 1.70.0, 1.56.0]
27+
rust: [nightly, beta, stable, 1.75.0, 1.70.0, 1.56.0]
2828
timeout-minutes: 45
2929
steps:
3030
- uses: actions/checkout@v4

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ proc-macro = true
1818
[dependencies]
1919
proc-macro2 = "1.0.74"
2020
quote = "1.0.35"
21-
syn = { version = "2.0.46", default-features = false, features = ["full", "parsing", "printing", "proc-macro", "visit-mut"] }
21+
syn = { version = "2.0.46", default-features = false, features = ["clone-impls", "full", "parsing", "printing", "proc-macro", "visit-mut"] }
2222

2323
[dev-dependencies]
2424
futures = "0.3.30"

src/expand.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use syn::visit_mut::{self, VisitMut};
1212
use syn::{
1313
parse_quote, parse_quote_spanned, Attribute, Block, FnArg, GenericArgument, GenericParam,
1414
Generics, Ident, ImplItem, Lifetime, LifetimeParam, Pat, PatIdent, PathArguments, Receiver,
15-
ReturnType, Signature, Token, TraitItem, Type, TypePath, WhereClause,
15+
ReturnType, Signature, Token, TraitItem, Type, TypeInfer, TypePath, WhereClause,
1616
};
1717

1818
impl ToTokens for Item {
@@ -410,6 +410,8 @@ fn transform_block(context: Context, sig: &mut Signature, block: &mut Block) {
410410
quote!(#(#decls)* { #(#stmts)* })
411411
}
412412
} else {
413+
let mut ret = ret.clone();
414+
replace_impl_trait_with_infer(&mut ret);
413415
quote! {
414416
if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::<#ret> {
415417
#[allow(unreachable_code)]
@@ -475,3 +477,20 @@ fn where_clause_or_default(clause: &mut Option<WhereClause>) -> &mut WhereClause
475477
predicates: Punctuated::new(),
476478
})
477479
}
480+
481+
fn replace_impl_trait_with_infer(ty: &mut Type) {
482+
struct ReplaceImplTraitWithInfer;
483+
484+
impl VisitMut for ReplaceImplTraitWithInfer {
485+
fn visit_type_mut(&mut self, ty: &mut Type) {
486+
if let Type::ImplTrait(impl_trait) = ty {
487+
*ty = Type::Infer(TypeInfer {
488+
underscore_token: Token![_](impl_trait.impl_token.span),
489+
});
490+
}
491+
visit_mut::visit_type_mut(self, ty);
492+
}
493+
}
494+
495+
ReplaceImplTraitWithInfer.visit_type_mut(ty);
496+
}

tests/test.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,3 +1661,25 @@ pub mod issue277 {
16611661

16621662
fn g(_: &mut &()) {}
16631663
}
1664+
1665+
// https://github.com/dtolnay/async-trait/issues/281
1666+
#[rustversion::since(1.75)]
1667+
pub mod issue281 {
1668+
use async_trait::async_trait;
1669+
1670+
#[async_trait]
1671+
pub trait Trait {
1672+
type Error;
1673+
async fn method(&self) -> Result<impl AsRef<str> + Send + Sync, Self::Error>;
1674+
}
1675+
1676+
pub struct T;
1677+
1678+
#[async_trait]
1679+
impl Trait for T {
1680+
type Error = ();
1681+
async fn method(&self) -> Result<impl AsRef<str> + Send + Sync, Self::Error> {
1682+
Ok("Hello World")
1683+
}
1684+
}
1685+
}

0 commit comments

Comments
 (0)