Skip to content

Commit

Permalink
Merge pull request #282 from dtolnay/impltrait
Browse files Browse the repository at this point in the history
Support impl Trait in return type
  • Loading branch information
dtolnay authored Jan 3, 2025
2 parents 7d8519d + 3af8236 commit 1cab7e4
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
rust: [nightly, beta, stable, 1.70.0, 1.56.0]
rust: [nightly, beta, stable, 1.75.0, 1.70.0, 1.56.0]
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ proc-macro = true
[dependencies]
proc-macro2 = "1.0.74"
quote = "1.0.35"
syn = { version = "2.0.46", default-features = false, features = ["full", "parsing", "printing", "proc-macro", "visit-mut"] }
syn = { version = "2.0.46", default-features = false, features = ["clone-impls", "full", "parsing", "printing", "proc-macro", "visit-mut"] }

[dev-dependencies]
futures = "0.3.30"
Expand Down
21 changes: 20 additions & 1 deletion src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use syn::visit_mut::{self, VisitMut};
use syn::{
parse_quote, parse_quote_spanned, Attribute, Block, FnArg, GenericArgument, GenericParam,
Generics, Ident, ImplItem, Lifetime, LifetimeParam, Pat, PatIdent, PathArguments, Receiver,
ReturnType, Signature, Token, TraitItem, Type, TypePath, WhereClause,
ReturnType, Signature, Token, TraitItem, Type, TypeInfer, TypePath, WhereClause,
};

impl ToTokens for Item {
Expand Down Expand Up @@ -410,6 +410,8 @@ fn transform_block(context: Context, sig: &mut Signature, block: &mut Block) {
quote!(#(#decls)* { #(#stmts)* })
}
} else {
let mut ret = ret.clone();
replace_impl_trait_with_infer(&mut ret);
quote! {
if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::<#ret> {
#[allow(unreachable_code)]
Expand Down Expand Up @@ -475,3 +477,20 @@ fn where_clause_or_default(clause: &mut Option<WhereClause>) -> &mut WhereClause
predicates: Punctuated::new(),
})
}

fn replace_impl_trait_with_infer(ty: &mut Type) {
struct ReplaceImplTraitWithInfer;

impl VisitMut for ReplaceImplTraitWithInfer {
fn visit_type_mut(&mut self, ty: &mut Type) {
if let Type::ImplTrait(impl_trait) = ty {
*ty = Type::Infer(TypeInfer {
underscore_token: Token![_](impl_trait.impl_token.span),
});
}
visit_mut::visit_type_mut(self, ty);
}
}

ReplaceImplTraitWithInfer.visit_type_mut(ty);
}
22 changes: 22 additions & 0 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1661,3 +1661,25 @@ pub mod issue277 {

fn g(_: &mut &()) {}
}

// https://github.com/dtolnay/async-trait/issues/281
#[rustversion::since(1.75)]
pub mod issue281 {
use async_trait::async_trait;

#[async_trait]
pub trait Trait {
type Error;
async fn method(&self) -> Result<impl AsRef<str> + Send + Sync, Self::Error>;
}

pub struct T;

#[async_trait]
impl Trait for T {
type Error = ();
async fn method(&self) -> Result<impl AsRef<str> + Send + Sync, Self::Error> {
Ok("Hello World")
}
}
}

0 comments on commit 1cab7e4

Please sign in to comment.