diff -Nru rust-async-trait-0.1.24/build.rs rust-async-trait-0.1.56/build.rs --- rust-async-trait-0.1.24/build.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/build.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,29 @@ +use std::env; +use std::process::Command; +use std::str; + +fn main() { + let compiler = match rustc_minor_version() { + Some(compiler) => compiler, + None => return, + }; + + if compiler < 45 { + println!("cargo:rustc-cfg=no_span_mixed_site"); + } + + if compiler < 47 { + println!("cargo:rustc-cfg=self_span_hack"); + } +} + +fn rustc_minor_version() -> Option { + let rustc = env::var_os("RUSTC")?; + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = str::from_utf8(&output.stdout).ok()?; + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + pieces.next()?.parse().ok() +} diff -Nru rust-async-trait-0.1.24/Cargo.toml rust-async-trait-0.1.56/Cargo.toml --- rust-async-trait-0.1.24/Cargo.toml 2020-02-04 07:21:43.000000000 +0000 +++ rust-async-trait-0.1.56/Cargo.toml 1970-01-01 00:00:01.000000000 +0000 @@ -3,26 +3,31 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" +rust-version = "1.39" name = "async-trait" -version = "0.1.24" +version = "0.1.56" authors = ["David Tolnay "] description = "Type erasure for async trait methods" documentation = "https://docs.rs/async-trait" readme = "README.md" +keywords = ["async"] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/async-trait" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [lib] proc-macro = true + [dependencies.proc-macro2] version = "1.0" @@ -30,16 +35,24 @@ version = "1.0" [dependencies.syn] -version = "1.0" -features = ["full", "visit-mut"] +version = "1.0.96" +features = [ + "full", + "visit-mut", +] + +[dev-dependencies.futures] +version = "0.3" + [dev-dependencies.rustversion] version = "1.0" +[dev-dependencies.tracing] +version = "0.1.14" + +[dev-dependencies.tracing-attributes] +version = "0.1.14" + [dev-dependencies.trybuild] -version = "1.0.19" +version = "1.0.49" features = ["diff"] - -[features] -support_old_nightly = [] -[badges.travis-ci] -repository = "dtolnay/async-trait" diff -Nru rust-async-trait-0.1.24/Cargo.toml.orig rust-async-trait-0.1.56/Cargo.toml.orig --- rust-async-trait-0.1.24/Cargo.toml.orig 2020-02-04 07:21:32.000000000 +0000 +++ rust-async-trait-0.1.56/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -1,32 +1,30 @@ [package] name = "async-trait" -version = "0.1.24" +version = "0.1.56" authors = ["David Tolnay "] edition = "2018" +rust-version = "1.39" license = "MIT OR Apache-2.0" description = "Type erasure for async trait methods" repository = "https://github.com/dtolnay/async-trait" documentation = "https://docs.rs/async-trait" readme = "README.md" +keywords = ["async"] [lib] proc-macro = true -[badges] -travis-ci = { repository = "dtolnay/async-trait" } - [dependencies] proc-macro2 = "1.0" quote = "1.0" -syn = { version = "1.0", features = ["full", "visit-mut"] } +syn = { version = "1.0.96", features = ["full", "visit-mut"] } [dev-dependencies] +futures = "0.3" rustversion = "1.0" -trybuild = { version = "1.0.19", features = ["diff"] } +tracing = "0.1.14" +tracing-attributes = "0.1.14" +trybuild = { version = "1.0.49", features = ["diff"] } -[features] -# Alternative implementation that produces worse error messages but potentially -# works on old nightlies without https://github.com/rust-lang/rust/pull/61775 in -# some cases where the default implementation does not. This feature is semver -# exempt and might get removed without notice in any patch version. -support_old_nightly = [] +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff -Nru rust-async-trait-0.1.24/.cargo_vcs_info.json rust-async-trait-0.1.56/.cargo_vcs_info.json --- rust-async-trait-0.1.24/.cargo_vcs_info.json 2020-02-04 07:21:43.000000000 +0000 +++ rust-async-trait-0.1.56/.cargo_vcs_info.json 1970-01-01 00:00:01.000000000 +0000 @@ -1,5 +1,6 @@ { "git": { - "sha1": "fe1f0ee75dec3bcea621cf31d26a26cd58115705" - } -} + "sha1": "0cc3e8a9d054888abab3f5caba8f93e68fe4fda8" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru rust-async-trait-0.1.24/.clippy.toml rust-async-trait-0.1.56/.clippy.toml --- rust-async-trait-0.1.24/.clippy.toml 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/.clippy.toml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1 @@ +msrv = "1.39.0" diff -Nru rust-async-trait-0.1.24/debian/cargo-checksum.json rust-async-trait-0.1.56/debian/cargo-checksum.json --- rust-async-trait-0.1.24/debian/cargo-checksum.json 2020-02-08 18:01:10.000000000 +0000 +++ rust-async-trait-0.1.56/debian/cargo-checksum.json 2022-07-02 17:35:07.000000000 +0000 @@ -1 +1 @@ -{"package":"750b1c38a1dfadd108da0f01c08f4cdc7ff1bb39b325f9c82cc972361780a6e1","files":{}} +{"package":"96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716","files":{}} diff -Nru rust-async-trait-0.1.24/debian/changelog rust-async-trait-0.1.56/debian/changelog --- rust-async-trait-0.1.24/debian/changelog 2020-02-08 18:01:10.000000000 +0000 +++ rust-async-trait-0.1.56/debian/changelog 2022-07-02 17:35:07.000000000 +0000 @@ -1,3 +1,13 @@ +rust-async-trait (0.1.56-1) unstable; urgency=medium + + * Package async-trait 0.1.56 from crates.io using debcargo 2.5.0 (Closes: 1014217) + + [ Fabian Grünbichler ] + * Team upload. + * Package async-trait 0.1.30 from crates.io using debcargo 2.4.2 + + -- Peter Michael Green Sat, 02 Jul 2022 17:35:07 +0000 + rust-async-trait (0.1.24-1) unstable; urgency=medium * Team upload. diff -Nru rust-async-trait-0.1.24/debian/compat rust-async-trait-0.1.56/debian/compat --- rust-async-trait-0.1.24/debian/compat 2020-02-08 18:01:10.000000000 +0000 +++ rust-async-trait-0.1.56/debian/compat 2022-07-02 17:35:07.000000000 +0000 @@ -1 +1 @@ -11 +12 diff -Nru rust-async-trait-0.1.24/debian/control rust-async-trait-0.1.56/debian/control --- rust-async-trait-0.1.24/debian/control 2020-02-08 18:01:10.000000000 +0000 +++ rust-async-trait-0.1.56/debian/control 2022-07-02 17:35:07.000000000 +0000 @@ -1,22 +1,23 @@ Source: rust-async-trait Section: rust Priority: optional -Build-Depends: debhelper (>= 11), - dh-cargo (>= 18), +Build-Depends: debhelper (>= 12), + dh-cargo (>= 25), cargo:native , rustc:native , libstd-rust-dev , librust-proc-macro2-1+default-dev , librust-quote-1+default-dev , - librust-syn-1+default-dev , - librust-syn-1+full-dev , - librust-syn-1+visit-mut-dev + librust-syn-1+default-dev (>= 1.0.96-~~) , + librust-syn-1+full-dev (>= 1.0.96-~~) , + librust-syn-1+visit-mut-dev (>= 1.0.96-~~) Maintainer: Debian Rust Maintainers Uploaders: Fabian Grünbichler -Standards-Version: 4.2.0 +Standards-Version: 4.5.1 Vcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/async-trait] Vcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/async-trait +Rules-Requires-Root: no Package: librust-async-trait-dev Architecture: any @@ -25,21 +26,17 @@ ${misc:Depends}, librust-proc-macro2-1+default-dev, librust-quote-1+default-dev, - librust-syn-1+default-dev, - librust-syn-1+full-dev, - librust-syn-1+visit-mut-dev + librust-syn-1+default-dev (>= 1.0.96-~~), + librust-syn-1+full-dev (>= 1.0.96-~~), + librust-syn-1+visit-mut-dev (>= 1.0.96-~~) Provides: librust-async-trait+default-dev (= ${binary:Version}), - librust-async-trait+support-old-nightly-dev (= ${binary:Version}), librust-async-trait-0-dev (= ${binary:Version}), librust-async-trait-0+default-dev (= ${binary:Version}), - librust-async-trait-0+support-old-nightly-dev (= ${binary:Version}), librust-async-trait-0.1-dev (= ${binary:Version}), librust-async-trait-0.1+default-dev (= ${binary:Version}), - librust-async-trait-0.1+support-old-nightly-dev (= ${binary:Version}), - librust-async-trait-0.1.24-dev (= ${binary:Version}), - librust-async-trait-0.1.24+default-dev (= ${binary:Version}), - librust-async-trait-0.1.24+support-old-nightly-dev (= ${binary:Version}) + librust-async-trait-0.1.56-dev (= ${binary:Version}), + librust-async-trait-0.1.56+default-dev (= ${binary:Version}) Description: Type erasure for async trait methods - Rust source code This package contains the source for the Rust async-trait crate, packaged by debcargo for use with cargo and dh-cargo. diff -Nru rust-async-trait-0.1.24/debian/copyright rust-async-trait-0.1.56/debian/copyright --- rust-async-trait-0.1.24/debian/copyright 2020-02-08 18:01:10.000000000 +0000 +++ rust-async-trait-0.1.56/debian/copyright 2022-07-02 17:35:07.000000000 +0000 @@ -9,7 +9,7 @@ Files: debian/* Copyright: - 2020 Debian Rust Maintainers + 2020-2022 Debian Rust Maintainers 2020 Fabian Grünbichler License: MIT or Apache-2.0 diff -Nru rust-async-trait-0.1.24/debian/copyright.debcargo.hint rust-async-trait-0.1.56/debian/copyright.debcargo.hint --- rust-async-trait-0.1.24/debian/copyright.debcargo.hint 2020-02-08 18:01:10.000000000 +0000 +++ rust-async-trait-0.1.56/debian/copyright.debcargo.hint 2022-07-02 17:35:07.000000000 +0000 @@ -14,8 +14,8 @@ Files: debian/* Copyright: - 2020 Debian Rust Maintainers - 2020 Fabian Grünbichler + 2020-2022 Debian Rust Maintainers + 2020-2022 Fabian Grünbichler License: MIT or Apache-2.0 License: Apache-2.0 diff -Nru rust-async-trait-0.1.24/debian/tests/control rust-async-trait-0.1.56/debian/tests/control --- rust-async-trait-0.1.24/debian/tests/control 2020-02-08 18:01:10.000000000 +0000 +++ rust-async-trait-0.1.56/debian/tests/control 2022-07-02 17:35:07.000000000 +0000 @@ -1,7 +1,14 @@ -Test-Command: /usr/share/cargo/bin/cargo-auto-test async-trait 0.1.24 --all-targets --all-features -Depends: dh-cargo (>= 18), librust-rustversion-1+default-dev, librust-trybuild-1+default-dev (>= 1.0.19-~~), librust-trybuild-1+diff-dev (>= 1.0.19-~~), @ +Test-Command: /usr/share/cargo/bin/cargo-auto-test async-trait 0.1.56 --all-targets --all-features +Features: test-name=rust-async-trait:@ +Depends: dh-cargo (>= 18), librust-futures-0.3+default-dev, librust-rustversion-1+default-dev, librust-tracing-0.1+default-dev (>= 0.1.14-~~), librust-tracing-attributes-0.1+default-dev (>= 0.1.14-~~), librust-trybuild-1+default-dev (>= 1.0.49-~~), librust-trybuild-1+diff-dev (>= 1.0.49-~~), @ Restrictions: allow-stderr, skip-not-installable -Test-Command: /usr/share/cargo/bin/cargo-auto-test async-trait 0.1.24 --all-targets --no-default-features -Depends: dh-cargo (>= 18), librust-rustversion-1+default-dev, librust-trybuild-1+default-dev (>= 1.0.19-~~), librust-trybuild-1+diff-dev (>= 1.0.19-~~), librust-async-trait-dev +Test-Command: /usr/share/cargo/bin/cargo-auto-test async-trait 0.1.56 --all-targets +Features: test-name=librust-async-trait-dev:default +Depends: dh-cargo (>= 18), librust-futures-0.3+default-dev, librust-rustversion-1+default-dev, librust-tracing-0.1+default-dev (>= 0.1.14-~~), librust-tracing-attributes-0.1+default-dev (>= 0.1.14-~~), librust-trybuild-1+default-dev (>= 1.0.49-~~), librust-trybuild-1+diff-dev (>= 1.0.49-~~), @ +Restrictions: allow-stderr, skip-not-installable + +Test-Command: /usr/share/cargo/bin/cargo-auto-test async-trait 0.1.56 --all-targets --no-default-features +Features: test-name=librust-async-trait-dev: +Depends: dh-cargo (>= 18), librust-futures-0.3+default-dev, librust-rustversion-1+default-dev, librust-tracing-0.1+default-dev (>= 0.1.14-~~), librust-tracing-attributes-0.1+default-dev (>= 0.1.14-~~), librust-trybuild-1+default-dev (>= 1.0.49-~~), librust-trybuild-1+diff-dev (>= 1.0.49-~~), @ Restrictions: allow-stderr, skip-not-installable diff -Nru rust-async-trait-0.1.24/debian/watch rust-async-trait-0.1.56/debian/watch --- rust-async-trait-0.1.24/debian/watch 2020-02-08 18:01:10.000000000 +0000 +++ rust-async-trait-0.1.56/debian/watch 2022-07-02 17:35:07.000000000 +0000 @@ -2,4 +2,3 @@ opts=filenamemangle=s/.*\/(.*)\/download/async-trait-$1\.tar\.gz/g,\ uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\d*)$/$1~$2/ \ https://qa.debian.org/cgi-bin/fakeupstream.cgi?upstream=crates.io/async-trait .*/crates/async-trait/@ANY_VERSION@/download - diff -Nru rust-async-trait-0.1.24/.github/workflows/ci.yml rust-async-trait-0.1.56/.github/workflows/ci.yml --- rust-async-trait-0.1.24/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/.github/workflows/ci.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,65 @@ +name: CI + +on: + push: + pull_request: + schedule: [cron: "40 1 * * *"] + +env: + RUSTFLAGS: -Dwarnings + +jobs: + test: + name: Rust ${{matrix.rust}} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [beta, stable, 1.45.0] + include: + - rust: nightly + rustflags: --cfg async_trait_nightly_testing + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + - run: cargo test + env: + RUSTFLAGS: ${{matrix.rustflags}} ${{env.RUSTFLAGS}} + + msrv: + name: Rust 1.39.0 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@1.39.0 + - run: cargo check + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@clippy + - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic + + miri: + name: Miri + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri test + env: + MIRIFLAGS: -Zmiri-strict-provenance + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --exit-code 1 diff -Nru rust-async-trait-0.1.24/README.md rust-async-trait-0.1.56/README.md --- rust-async-trait-0.1.24/README.md 2020-01-24 20:23:20.000000000 +0000 +++ rust-async-trait-0.1.56/README.md 1973-11-29 21:33:09.000000000 +0000 @@ -1,16 +1,14 @@ Async trait methods =================== -[![Build Status](https://api.travis-ci.com/dtolnay/async-trait.svg?branch=master)](https://travis-ci.com/dtolnay/async-trait) -[![Latest Version](https://img.shields.io/crates/v/async-trait.svg)](https://crates.io/crates/async-trait) -[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/async-trait) - -The async/await language feature is on track for an initial round of -stabilizations in Rust 1.39 (tracking issue: [rust-lang/rust#62149]), but this -does not include support for async fn in traits. Trying to include an async fn -in a trait produces the following error: - -[rust-lang/rust#62149]: https://github.com/rust-lang/rust/issues/62149 +[github](https://github.com/dtolnay/async-trait) +[crates.io](https://crates.io/crates/async-trait) +[docs.rs](https://docs.rs/async-trait) +[build status](https://github.com/dtolnay/async-trait/actions?query=branch%3Amaster) + +The initial round of stabilizations for the async/await language feature in Rust +1.39 did not include support for async fn in traits. Trying to include an async +fn in a trait produces the following error: ```rust trait MyTrait { @@ -105,18 +103,18 @@ ## Explanation Async fns get transformed into methods that return `Pin>` and delegate to a private async freestanding function. +'async_trait>>` and delegate to a private async freestanding function. For example the `impl Advertisement for AutoplayingVideo` above would be expanded as: ```rust impl Advertisement for AutoplayingVideo { - fn run<'async>( - &'async self, - ) -> Pin + Send + 'async>> + fn run<'async_trait>( + &'async_trait self, + ) -> Pin + Send + 'async_trait>> where - Self: Sync + 'async, + Self: Sync + 'async_trait, { async fn run(_self: &AutoplayingVideo) { /* the original method body */ @@ -219,7 +217,7 @@ For traits that need to be object safe and need to have default implementations for some async methods, there are two resolutions. Either you can add Send and/or Sync as supertraits (Send if there are `&mut self` methods with default -implementations, Sync if there are `&self` methods with default implementions) +implementations, Sync if there are `&self` methods with default implementations) to constrain all implementors of the trait such that the default implementations are applicable to them: diff -Nru rust-async-trait-0.1.24/src/expand.rs rust-async-trait-0.1.56/src/expand.rs --- rust-async-trait-0.1.24/src/expand.rs 2020-02-04 07:21:26.000000000 +0000 +++ rust-async-trait-0.1.56/src/expand.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,17 +1,16 @@ -use crate::lifetime::{has_async_lifetime, CollectLifetimes}; +use crate::lifetime::{AddLifetimeToImplTrait, CollectLifetimes}; use crate::parse::Item; -use crate::receiver::{ - has_self_in_block, has_self_in_sig, has_self_in_where_predicate, ReplaceReceiver, -}; +use crate::receiver::{has_self_in_block, has_self_in_sig, mut_pat, ReplaceSelf}; use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote, quote_spanned, ToTokens}; +use std::collections::BTreeSet as Set; use std::mem; use syn::punctuated::Punctuated; -use syn::visit_mut::VisitMut; +use syn::visit_mut::{self, VisitMut}; use syn::{ - parse_quote, Block, FnArg, GenericParam, Generics, Ident, ImplItem, Lifetime, Pat, PatIdent, - Path, Receiver, ReturnType, Signature, Token, TraitItem, Type, TypeParam, TypeParamBound, - WhereClause, + parse_quote, parse_quote_spanned, Attribute, Block, FnArg, GenericParam, Generics, Ident, + ImplItem, Lifetime, LifetimeDef, Pat, PatIdent, Receiver, ReturnType, Signature, Stmt, Token, + TraitItem, Type, TypeParamBound, TypePath, WhereClause, }; impl ToTokens for Item { @@ -26,29 +25,28 @@ #[derive(Clone, Copy)] enum Context<'a> { Trait { - name: &'a Ident, generics: &'a Generics, supertraits: &'a Supertraits, }, Impl { impl_generics: &'a Generics, - receiver: &'a Type, - as_trait: &'a Path, + associated_type_impl_traits: &'a Set, }, } impl Context<'_> { - fn lifetimes<'a>(&'a self, used: &'a [Lifetime]) -> impl Iterator { + fn lifetimes<'a>(&'a self, used: &'a [Lifetime]) -> impl Iterator { let generics = match self { Context::Trait { generics, .. } => generics, Context::Impl { impl_generics, .. } => impl_generics, }; - generics.params.iter().filter(move |param| { + generics.params.iter().filter_map(move |param| { if let GenericParam::Lifetime(param) = param { - used.contains(¶m.lifetime) - } else { - false + if used.contains(¶m.lifetime) { + return Some(param); + } } + None }) } } @@ -59,7 +57,6 @@ match input { Item::Trait(input) => { let context = Context::Trait { - name: &input.ident, generics: &input.generics, supertraits: &input.supertraits, }; @@ -69,9 +66,13 @@ if sig.asyncness.is_some() { let block = &mut method.default; let mut has_self = has_self_in_sig(sig); + method.attrs.push(parse_quote!(#[must_use])); if let Some(block) = block { has_self |= has_self_in_block(block); - transform_block(context, sig, block, has_self, is_local); + transform_block(context, sig, block); + method.attrs.push(lint_suppress_with_body()); + } else { + method.attrs.push(lint_suppress_without_body()); } let has_default = method.default.is_some(); transform_sig(context, sig, has_self, has_default, is_local); @@ -80,10 +81,25 @@ } } Item::Impl(input) => { + let mut lifetimes = CollectLifetimes::new("'impl", input.impl_token.span); + lifetimes.visit_type_mut(&mut *input.self_ty); + lifetimes.visit_path_mut(&mut input.trait_.as_mut().unwrap().1); + let params = &input.generics.params; + let elided = lifetimes.elided; + input.generics.params = parse_quote!(#(#elided,)* #params); + + let mut associated_type_impl_traits = Set::new(); + for inner in &input.items { + if let ImplItem::Type(assoc) = inner { + if let Type::ImplTrait(_) = assoc.ty { + associated_type_impl_traits.insert(assoc.ident.clone()); + } + } + } + let context = Context::Impl { impl_generics: &input.generics, - receiver: &input.self_ty, - as_trait: &input.trait_.as_ref().unwrap().1, + associated_type_impl_traits: &associated_type_impl_traits, }; for inner in &mut input.items { if let ImplItem::Method(method) = inner { @@ -91,8 +107,9 @@ if sig.asyncness.is_some() { let block = &mut method.block; let has_self = has_self_in_sig(sig) || has_self_in_block(block); - transform_block(context, sig, block, has_self, is_local); + transform_block(context, sig, block); transform_sig(context, sig, has_self, false, is_local); + method.attrs.push(lint_suppress_with_body()); } } } @@ -100,6 +117,28 @@ } } +fn lint_suppress_with_body() -> Attribute { + parse_quote! { + #[allow( + clippy::let_unit_value, + clippy::no_effect_underscore_binding, + clippy::shadow_same, + clippy::type_complexity, + clippy::type_repetition_in_bounds, + clippy::used_underscore_binding + )] + } +} + +fn lint_suppress_without_body() -> Attribute { + parse_quote! { + #[allow( + clippy::type_complexity, + clippy::type_repetition_in_bounds + )] + } +} + // Input: // async fn f(&self, x: &T) -> Ret; // @@ -127,7 +166,13 @@ ReturnType::Type(_, ret) => quote!(#ret), }; - let mut lifetimes = CollectLifetimes::new(); + let default_span = sig + .ident + .span() + .join(sig.paren_token.span) + .unwrap_or_else(|| sig.ident.span()); + + let mut lifetimes = CollectLifetimes::new("'life", default_span); for arg in sig.inputs.iter_mut() { match arg { FnArg::Receiver(arg) => lifetimes.visit_receiver_mut(arg), @@ -135,59 +180,91 @@ } } - let where_clause = sig - .generics - .where_clause - .get_or_insert_with(|| WhereClause { - where_token: Default::default(), - predicates: Punctuated::new(), - }); - for param in sig - .generics - .params - .iter() - .chain(context.lifetimes(&lifetimes.explicit)) - { + for param in &mut sig.generics.params { match param { GenericParam::Type(param) => { - let param = ¶m.ident; - where_clause + let param_name = ¶m.ident; + let span = match param.colon_token.take() { + Some(colon_token) => colon_token.span, + None => param_name.span(), + }; + let bounds = mem::replace(&mut param.bounds, Punctuated::new()); + where_clause_or_default(&mut sig.generics.where_clause) .predicates - .push(parse_quote!(#param: 'async_trait)); + .push(parse_quote_spanned!(span=> #param_name: 'async_trait + #bounds)); } GenericParam::Lifetime(param) => { - let param = ¶m.lifetime; - where_clause + let param_name = ¶m.lifetime; + let span = match param.colon_token.take() { + Some(colon_token) => colon_token.span, + None => param_name.span(), + }; + let bounds = mem::replace(&mut param.bounds, Punctuated::new()); + where_clause_or_default(&mut sig.generics.where_clause) .predicates - .push(parse_quote!(#param: 'async_trait)); + .push(parse_quote_spanned!(span=> #param: 'async_trait + #bounds)); } GenericParam::Const(_) => {} } } + + for param in context.lifetimes(&lifetimes.explicit) { + let param = ¶m.lifetime; + let span = param.span(); + where_clause_or_default(&mut sig.generics.where_clause) + .predicates + .push(parse_quote_spanned!(span=> #param: 'async_trait)); + } + + if sig.generics.lt_token.is_none() { + sig.generics.lt_token = Some(Token![<](sig.ident.span())); + } + if sig.generics.gt_token.is_none() { + sig.generics.gt_token = Some(Token![>](sig.paren_token.span)); + } + for elided in lifetimes.elided { sig.generics.params.push(parse_quote!(#elided)); - where_clause + where_clause_or_default(&mut sig.generics.where_clause) .predicates - .push(parse_quote!(#elided: 'async_trait)); + .push(parse_quote_spanned!(elided.span()=> #elided: 'async_trait)); } - sig.generics.params.push(parse_quote!('async_trait)); + + sig.generics + .params + .push(parse_quote_spanned!(default_span=> 'async_trait)); + if has_self { - let bound: Ident = match sig.inputs.iter().next() { + let bound_span = sig.ident.span(); + let bound = match sig.inputs.iter().next() { Some(FnArg::Receiver(Receiver { reference: Some(_), mutability: None, .. - })) => parse_quote!(Sync), - _ => parse_quote!(Send), + })) => Ident::new("Sync", bound_span), + Some(FnArg::Typed(arg)) + if match (arg.pat.as_ref(), arg.ty.as_ref()) { + (Pat::Ident(pat), Type::Reference(ty)) => { + pat.ident == "self" && ty.mutability.is_none() + } + _ => false, + } => + { + Ident::new("Sync", bound_span) + } + _ => Ident::new("Send", bound_span), }; + let assume_bound = match context { Context::Trait { supertraits, .. } => !has_default || has_bound(supertraits, &bound), Context::Impl { .. } => true, }; + + let where_clause = where_clause_or_default(&mut sig.generics.where_clause); where_clause.predicates.push(if assume_bound || is_local { - parse_quote!(Self: 'async_trait) + parse_quote_spanned!(bound_span=> Self: 'async_trait) } else { - parse_quote!(Self: ::core::marker::#bound + 'async_trait) + parse_quote_spanned!(bound_span=> Self: ::core::marker::#bound + 'async_trait) }); } @@ -202,20 +279,22 @@ ident.by_ref = None; ident.mutability = None; } else { - let positional = positional_arg(i); - *arg.pat = parse_quote!(#positional); + let positional = positional_arg(i, &arg.pat); + let m = mut_pat(&mut arg.pat); + arg.pat = parse_quote!(#m #positional); } + AddLifetimeToImplTrait.visit_type_mut(&mut arg.ty); } } } + let ret_span = sig.ident.span(); let bounds = if is_local { - quote!('async_trait) + quote_spanned!(ret_span=> 'async_trait) } else { - quote!(::core::marker::Send + 'async_trait) + quote_spanned!(ret_span=> ::core::marker::Send + 'async_trait) }; - - sig.output = parse_quote! { + sig.output = parse_quote_spanned! {ret_span=> -> ::core::pin::Pin + #bounds >> @@ -223,220 +302,168 @@ } // Input: -// async fn f(&self, x: &T) -> Ret { -// self + x +// async fn f(&self, x: &T, (a, b): (A, B)) -> Ret { +// self + x + a + b // } // // Output: -// async fn f(_self: &AsyncTrait, x: &T) -> Ret { -// _self + x -// } -// Box::pin(async_trait_method::(self, x)) -fn transform_block( - context: Context, - sig: &mut Signature, - block: &mut Block, - has_self: bool, - is_local: bool, -) { - if cfg!(feature = "support_old_nightly") { - let brace = block.brace_token; - *block = parse_quote!({ - Box::pin(async move #block) - }); - block.brace_token = brace; - return; +// Box::pin(async move { +// let ___ret: Ret = { +// let __self = self; +// let x = x; +// let (a, b) = __arg1; +// +// __self + x + a + b +// }; +// +// ___ret +// }) +fn transform_block(context: Context, sig: &mut Signature, block: &mut Block) { + if let Some(Stmt::Item(syn::Item::Verbatim(item))) = block.stmts.first() { + if block.stmts.len() == 1 && item.to_string() == ";" { + return; + } } - let inner = format_ident!("__{}", sig.ident); - let args = sig.inputs.iter().enumerate().map(|(i, arg)| match arg { - FnArg::Receiver(_) => quote!(self), - FnArg::Typed(arg) => { - if let Pat::Ident(PatIdent { ident, .. }) = &*arg.pat { - quote!(#ident) - } else { - positional_arg(i).into_token_stream() + let mut self_span = None; + let decls = sig + .inputs + .iter() + .enumerate() + .map(|(i, arg)| match arg { + FnArg::Receiver(Receiver { + self_token, + mutability, + .. + }) => { + let ident = Ident::new("__self", self_token.span); + self_span = Some(self_token.span); + quote!(let #mutability #ident = #self_token;) } - } - }); - - let mut standalone = sig.clone(); - standalone.ident = inner.clone(); - - let generics = match context { - Context::Trait { generics, .. } => generics, - Context::Impl { impl_generics, .. } => impl_generics, - }; - - let mut outer_generics = generics.clone(); - if !has_self { - if let Some(mut where_clause) = outer_generics.where_clause { - where_clause.predicates = where_clause - .predicates - .into_iter() - .filter_map(|mut pred| { - if has_self_in_where_predicate(&mut pred) { - None + FnArg::Typed(arg) => { + if let Pat::Ident(PatIdent { + ident, mutability, .. + }) = &*arg.pat + { + if ident == "self" { + self_span = Some(ident.span()); + let prefixed = Ident::new("__self", ident.span()); + quote!(let #mutability #prefixed = #ident;) } else { - Some(pred) + quote!(let #mutability #ident = #ident;) } - }) - .collect(); - outer_generics.where_clause = Some(where_clause); - } - } - - let fn_generics = mem::replace(&mut standalone.generics, outer_generics); - standalone.generics.params.extend(fn_generics.params); - if let Some(where_clause) = fn_generics.where_clause { - standalone - .generics - .make_where_clause() - .predicates - .extend(where_clause.predicates); - } + } else { + let pat = &arg.pat; + let ident = positional_arg(i, pat); + if let Pat::Wild(_) = **pat { + quote!(let #ident = #ident;) + } else { + quote!(let #pat = #ident;) + } + } + } + }) + .collect::>(); - if has_async_lifetime(&mut standalone, block) { - standalone.generics.params.push(parse_quote!('async_trait)); + if let Some(span) = self_span { + let mut replace_self = ReplaceSelf(span); + replace_self.visit_block_mut(block); } - let mut types = standalone - .generics - .type_params() - .map(|param| param.ident.clone()) - .collect::>(); - - let mut self_bound = None::; - match standalone.inputs.iter_mut().next() { - Some( - arg @ FnArg::Receiver(Receiver { - reference: Some(_), .. - }), - ) => { - let (lifetime, mutability, self_token) = match arg { - FnArg::Receiver(Receiver { - reference: Some((_, lifetime)), - mutability, - self_token, - .. - }) => (lifetime, mutability, self_token), - _ => unreachable!(), - }; - let under_self = Ident::new("_self", self_token.span); - match context { - Context::Trait { .. } => { - self_bound = Some(match mutability { - Some(_) => parse_quote!(::core::marker::Send), - None => parse_quote!(::core::marker::Sync), - }); - *arg = parse_quote! { - #under_self: &#lifetime #mutability AsyncTrait - }; - } - Context::Impl { receiver, .. } => { - *arg = parse_quote! { - #under_self: &#lifetime #mutability #receiver - }; - } - } - } - Some(arg @ FnArg::Receiver(_)) => { - let (self_token, mutability) = match arg { - FnArg::Receiver(Receiver { - self_token, - mutability, - .. - }) => (self_token, mutability), - _ => unreachable!(), - }; - let under_self = Ident::new("_self", self_token.span); - match context { - Context::Trait { .. } => { - self_bound = Some(parse_quote!(::core::marker::Send)); - *arg = parse_quote! { - #mutability #under_self: AsyncTrait - }; - } - Context::Impl { receiver, .. } => { - *arg = parse_quote! { - #mutability #under_self: #receiver - }; + let stmts = &block.stmts; + let let_ret = match &mut sig.output { + ReturnType::Default => quote_spanned! {block.brace_token.span=> + #(#decls)* + let _: () = { #(#stmts)* }; + }, + ReturnType::Type(_, ret) => { + if contains_associated_type_impl_trait(context, ret) { + if decls.is_empty() { + quote!(#(#stmts)*) + } else { + quote!(#(#decls)* { #(#stmts)* }) } - } - } - Some(FnArg::Typed(arg)) => { - if let Pat::Ident(arg) = &mut *arg.pat { - if arg.ident == "self" { - arg.ident = Ident::new("_self", arg.ident.span()); + } else { + quote_spanned! {block.brace_token.span=> + if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::<#ret> { + return __ret; + } + #(#decls)* + let __ret: #ret = { #(#stmts)* }; + #[allow(unreachable_code)] + __ret } } } - _ => {} - } - - if let Context::Trait { name, generics, .. } = context { - if has_self { - let (_, generics, _) = generics.split_for_impl(); - let mut self_param: TypeParam = parse_quote!(AsyncTrait: ?Sized + #name #generics); - if !is_local { - self_param.bounds.extend(self_bound); - } - standalone - .generics - .params - .push(GenericParam::Type(self_param)); - types.push(Ident::new("Self", Span::call_site())); - } - } - - if let Some(where_clause) = &mut standalone.generics.where_clause { - // Work around an input bound like `where Self::Output: Send` expanding - // to `where ::Output: Send` which is illegal syntax because - // `where` is reserved for future use... :( - where_clause.predicates.insert(0, parse_quote!((): Sized)); - } - - let mut replace = match context { - Context::Trait { .. } => ReplaceReceiver::with(parse_quote!(AsyncTrait)), - Context::Impl { - receiver, as_trait, .. - } => ReplaceReceiver::with_as_trait(receiver.clone(), as_trait.clone()), }; - replace.visit_signature_mut(&mut standalone); - replace.visit_block_mut(block); - - let mut generics = types; - let consts = standalone - .generics - .const_params() - .map(|param| param.ident.clone()); - generics.extend(consts); - - let brace = block.brace_token; - let box_pin = quote_spanned!(brace.span=> { - #[allow( - clippy::missing_docs_in_private_items, - clippy::type_repetition_in_bounds, - clippy::used_underscore_binding, - )] - #standalone #block - Box::pin(#inner::<#(#generics),*>(#(#args),*)) - }); - *block = parse_quote!(#box_pin); - block.brace_token = brace; + let box_pin = quote_spanned!(block.brace_token.span=> + Box::pin(async move { #let_ret }) + ); + block.stmts = parse_quote!(#box_pin); } -fn positional_arg(i: usize) -> Ident { - format_ident!("__arg{}", i) +fn positional_arg(i: usize, pat: &Pat) -> Ident { + let span: Span = syn::spanned::Spanned::span(pat); + #[cfg(not(no_span_mixed_site))] + let span = span.resolved_at(Span::mixed_site()); + format_ident!("__arg{}", i, span = span) } fn has_bound(supertraits: &Supertraits, marker: &Ident) -> bool { for bound in supertraits { if let TypeParamBound::Trait(bound) = bound { - if bound.path.is_ident(marker) { + if bound.path.is_ident(marker) + || bound.path.segments.len() == 3 + && (bound.path.segments[0].ident == "std" + || bound.path.segments[0].ident == "core") + && bound.path.segments[1].ident == "marker" + && bound.path.segments[2].ident == *marker + { return true; } } } false } + +fn contains_associated_type_impl_trait(context: Context, ret: &mut Type) -> bool { + struct AssociatedTypeImplTraits<'a> { + set: &'a Set, + contains: bool, + } + + impl<'a> VisitMut for AssociatedTypeImplTraits<'a> { + fn visit_type_path_mut(&mut self, ty: &mut TypePath) { + if ty.qself.is_none() + && ty.path.segments.len() == 2 + && ty.path.segments[0].ident == "Self" + && self.set.contains(&ty.path.segments[1].ident) + { + self.contains = true; + } + visit_mut::visit_type_path_mut(self, ty); + } + } + + match context { + Context::Trait { .. } => false, + Context::Impl { + associated_type_impl_traits, + .. + } => { + let mut visit = AssociatedTypeImplTraits { + set: associated_type_impl_traits, + contains: false, + }; + visit.visit_type_mut(ret); + visit.contains + } + } +} + +fn where_clause_or_default(clause: &mut Option) -> &mut WhereClause { + clause.get_or_insert_with(|| WhereClause { + where_token: Default::default(), + predicates: Punctuated::new(), + }) +} diff -Nru rust-async-trait-0.1.24/src/lib.rs rust-async-trait-0.1.56/src/lib.rs --- rust-async-trait-0.1.24/src/lib.rs 2019-12-04 09:17:59.000000000 +0000 +++ rust-async-trait-0.1.56/src/lib.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,11 +1,16 @@ -//!
Type erasure for async trait methods
+//! [![github]](https://github.com/dtolnay/async-trait) [![crates-io]](https://crates.io/crates/async-trait) [![docs-rs]](https://docs.rs/async-trait) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K +//! +//!
//! -//! The async/await language feature is on track for an initial round of -//! stabilizations in Rust 1.39 (tracking issue: [rust-lang/rust#62149]), but -//! this does not include support for async fn in traits. Trying to include an -//! async fn in a trait produces the following error: +//!
Type erasure for async trait methods
//! -//! [rust-lang/rust#62149]: https://github.com/rust-lang/rust/issues/62149 +//! The initial round of stabilizations for the async/await language feature in +//! Rust 1.39 did not include support for async fn in traits. Trying to include +//! an async fn in a trait produces the following error: //! //! ```compile_fail //! trait MyTrait { @@ -254,7 +259,7 @@ //! implementations for some async methods, there are two resolutions. Either //! you can add Send and/or Sync as supertraits (Send if there are `&mut self` //! methods with default implementations, Sync if there are `&self` methods with -//! default implementions) to constrain all implementors of the trait such that +//! default implementations) to constrain all implementors of the trait such that //! the default implementations are applicable to them: //! //! ``` @@ -298,6 +303,17 @@ //! let object = &value as &dyn ObjectSafe; //! ``` +#![allow( + clippy::default_trait_access, + clippy::doc_markdown, + clippy::if_not_else, + clippy::items_after_statements, + clippy::module_name_repetitions, + clippy::shadow_unrelated, + clippy::similar_names, + clippy::too_many_lines +)] + extern crate proc_macro; mod args; diff -Nru rust-async-trait-0.1.24/src/lifetime.rs rust-async-trait-0.1.56/src/lifetime.rs --- rust-async-trait-0.1.24/src/lifetime.rs 2019-09-16 04:18:07.000000000 +0000 +++ rust-async-trait-0.1.56/src/lifetime.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,57 +1,47 @@ -use proc_macro2::Span; +use proc_macro2::{Span, TokenStream}; +use std::mem; use syn::visit_mut::{self, VisitMut}; -use syn::{Block, GenericArgument, Item, Lifetime, Receiver, Signature, TypeReference}; - -pub fn has_async_lifetime(sig: &mut Signature, block: &mut Block) -> bool { - let mut visitor = HasAsyncLifetime(false); - visitor.visit_signature_mut(sig); - visitor.visit_block_mut(block); - visitor.0 -} - -struct HasAsyncLifetime(bool); - -impl VisitMut for HasAsyncLifetime { - fn visit_lifetime_mut(&mut self, life: &mut Lifetime) { - self.0 |= life.to_string() == "'async_trait"; - } - - fn visit_item_mut(&mut self, _: &mut Item) { - // Do not recurse into nested items. - } -} +use syn::{ + parse_quote_spanned, token, Expr, GenericArgument, Lifetime, Receiver, ReturnType, Type, + TypeBareFn, TypeImplTrait, TypeParen, TypePtr, TypeReference, +}; pub struct CollectLifetimes { pub elided: Vec, pub explicit: Vec, + pub name: &'static str, + pub default_span: Span, } impl CollectLifetimes { - pub fn new() -> Self { + pub fn new(name: &'static str, default_span: Span) -> Self { CollectLifetimes { elided: Vec::new(), explicit: Vec::new(), + name, + default_span, } } fn visit_opt_lifetime(&mut self, lifetime: &mut Option) { match lifetime { - None => *lifetime = Some(self.next_lifetime()), + None => *lifetime = Some(self.next_lifetime(None)), Some(lifetime) => self.visit_lifetime(lifetime), } } fn visit_lifetime(&mut self, lifetime: &mut Lifetime) { if lifetime.ident == "_" { - *lifetime = self.next_lifetime(); + *lifetime = self.next_lifetime(lifetime.span()); } else { self.explicit.push(lifetime.clone()); } } - fn next_lifetime(&mut self) -> Lifetime { - let name = format!("'life{}", self.elided.len()); - let life = Lifetime::new(&name, Span::call_site()); + fn next_lifetime>>(&mut self, span: S) -> Lifetime { + let name = format!("{}{}", self.name, self.elided.len()); + let span = span.into().unwrap_or(self.default_span); + let life = Lifetime::new(&name, span); self.elided.push(life.clone()); life } @@ -76,3 +66,50 @@ visit_mut::visit_generic_argument_mut(self, gen); } } + +pub struct AddLifetimeToImplTrait; + +impl VisitMut for AddLifetimeToImplTrait { + fn visit_type_impl_trait_mut(&mut self, ty: &mut TypeImplTrait) { + let span = ty.impl_token.span; + let lifetime = parse_quote_spanned!(span=> 'async_trait); + ty.bounds.insert(0, lifetime); + if let Some(punct) = ty.bounds.pairs_mut().next().unwrap().punct_mut() { + punct.span = span; + } + visit_mut::visit_type_impl_trait_mut(self, ty); + } + + fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) { + parenthesize_impl_trait(&mut ty.elem, ty.and_token.span); + visit_mut::visit_type_reference_mut(self, ty); + } + + fn visit_type_ptr_mut(&mut self, ty: &mut TypePtr) { + parenthesize_impl_trait(&mut ty.elem, ty.star_token.span); + visit_mut::visit_type_ptr_mut(self, ty); + } + + fn visit_type_bare_fn_mut(&mut self, ty: &mut TypeBareFn) { + if let ReturnType::Type(arrow, return_type) = &mut ty.output { + parenthesize_impl_trait(return_type, arrow.spans[0]); + } + visit_mut::visit_type_bare_fn_mut(self, ty); + } + + fn visit_expr_mut(&mut self, _e: &mut Expr) { + // Do not recurse into impl Traits inside of an array length expression. + // + // fn outer(arg: [u8; { fn inner(_: impl Trait) {}; 0 }]); + } +} + +fn parenthesize_impl_trait(elem: &mut Type, paren_span: Span) { + if let Type::ImplTrait(_) = *elem { + let placeholder = Type::Verbatim(TokenStream::new()); + *elem = Type::Paren(TypeParen { + paren_token: token::Paren(paren_span), + elem: Box::new(mem::replace(elem, placeholder)), + }); + } +} diff -Nru rust-async-trait-0.1.24/src/parse.rs rust-async-trait-0.1.56/src/parse.rs --- rust-async-trait-0.1.24/src/parse.rs 2019-10-13 18:16:30.000000000 +0000 +++ rust-async-trait-0.1.56/src/parse.rs 1973-11-29 21:33:09.000000000 +0000 @@ -2,14 +2,6 @@ use syn::parse::{Error, Parse, ParseStream, Result}; use syn::{Attribute, ItemImpl, ItemTrait, Token}; -pub struct Nothing; - -impl Parse for Nothing { - fn parse(_input: ParseStream) -> Result { - Ok(Nothing) - } -} - pub enum Item { Trait(ItemTrait), Impl(ItemImpl), diff -Nru rust-async-trait-0.1.24/src/receiver.rs rust-async-trait-0.1.56/src/receiver.rs --- rust-async-trait-0.1.24/src/receiver.rs 2020-02-04 04:26:32.000000000 +0000 +++ rust-async-trait-0.1.56/src/receiver.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,11 +1,9 @@ -use proc_macro2::{Group, TokenStream, TokenTree}; +use proc_macro2::{Group, Span, TokenStream, TokenTree}; use std::iter::FromIterator; -use std::mem; -use syn::punctuated::Punctuated; use syn::visit_mut::{self, VisitMut}; use syn::{ - parse_quote, Block, Error, ExprPath, ExprStruct, Ident, Item, Macro, Path, PathArguments, - QSelf, Receiver, Signature, Type, TypePath, WherePredicate, + Block, ExprPath, Ident, Item, Macro, Pat, PatIdent, PatPath, Path, Receiver, Signature, Token, + TypePath, }; pub fn has_self_in_sig(sig: &mut Signature) -> bool { @@ -14,18 +12,46 @@ visitor.0 } -pub fn has_self_in_where_predicate(where_predicate: &mut WherePredicate) -> bool { +pub fn has_self_in_block(block: &mut Block) -> bool { let mut visitor = HasSelf(false); - visitor.visit_where_predicate_mut(where_predicate); + visitor.visit_block_mut(block); visitor.0 } -pub fn has_self_in_block(block: &mut Block) -> bool { - let mut visitor = HasSelf(false); - visitor.visit_block_mut(block); +fn has_self_in_token_stream(tokens: TokenStream) -> bool { + tokens.into_iter().any(|tt| match tt { + TokenTree::Ident(ident) => ident == "Self", + TokenTree::Group(group) => has_self_in_token_stream(group.stream()), + _ => false, + }) +} + +pub fn mut_pat(pat: &mut Pat) -> Option { + let mut visitor = HasMutPat(None); + visitor.visit_pat_mut(pat); visitor.0 } +fn contains_fn(tokens: TokenStream) -> bool { + tokens.into_iter().any(|tt| match tt { + TokenTree::Ident(ident) => ident == "fn", + TokenTree::Group(group) => contains_fn(group.stream()), + _ => false, + }) +} + +struct HasMutPat(Option); + +impl VisitMut for HasMutPat { + fn visit_pat_ident_mut(&mut self, i: &mut PatIdent) { + if let Some(m) = i.mutability { + self.0 = Some(m); + } else { + visit_mut::visit_pat_ident_mut(self, i); + } + } +} + struct HasSelf(bool); impl VisitMut for HasSelf { @@ -34,6 +60,11 @@ visit_mut::visit_expr_path_mut(self, expr); } + fn visit_pat_path_mut(&mut self, pat: &mut PatPath) { + self.0 |= pat.path.segments[0].ident == "Self"; + visit_mut::visit_pat_path_mut(self, pat); + } + fn visit_type_path_mut(&mut self, ty: &mut TypePath) { self.0 |= ty.path.segments[0].ident == "Self"; visit_mut::visit_type_path_mut(self, ty); @@ -46,187 +77,103 @@ fn visit_item_mut(&mut self, _: &mut Item) { // Do not recurse into nested items. } -} -pub struct ReplaceReceiver { - pub with: Type, - pub as_trait: Option, -} - -impl ReplaceReceiver { - pub fn with(ty: Type) -> Self { - ReplaceReceiver { - with: ty, - as_trait: None, + fn visit_macro_mut(&mut self, mac: &mut Macro) { + if !contains_fn(mac.tokens.clone()) { + self.0 |= has_self_in_token_stream(mac.tokens.clone()); } } +} - pub fn with_as_trait(ty: Type, as_trait: Path) -> Self { - ReplaceReceiver { - with: ty, - as_trait: Some(as_trait), - } - } - - fn self_to_qself_type(&self, qself: &mut Option, path: &mut Path) { - let include_as_trait = true; - self.self_to_qself(qself, path, include_as_trait); - } - - fn self_to_qself_expr(&self, qself: &mut Option, path: &mut Path) { - let include_as_trait = false; - self.self_to_qself(qself, path, include_as_trait); - } - - fn self_to_qself(&self, qself: &mut Option, path: &mut Path, include_as_trait: bool) { - if path.leading_colon.is_some() { - return; - } - - let first = &path.segments[0]; - if first.ident != "Self" || !first.arguments.is_empty() { - return; - } - - if path.segments.len() == 1 { - self.self_to_expr_path(path); - return; - } - - *qself = Some(QSelf { - lt_token: Default::default(), - ty: Box::new(self.with.clone()), - position: 0, - as_token: None, - gt_token: Default::default(), - }); - - if include_as_trait && self.as_trait.is_some() { - let as_trait = self.as_trait.as_ref().unwrap().clone(); - path.leading_colon = as_trait.leading_colon; - qself.as_mut().unwrap().position = as_trait.segments.len(); - - let segments = mem::replace(&mut path.segments, as_trait.segments); - path.segments.push_punct(Default::default()); - path.segments.extend(segments.into_pairs().skip(1)); - } else { - path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap()); - - let segments = mem::replace(&mut path.segments, Punctuated::new()); - path.segments = segments.into_pairs().skip(1).collect(); - } - } - - fn self_to_expr_path(&self, path: &mut Path) { - if let Type::Path(with) = &self.with { - *path = with.path.clone(); - for segment in &mut path.segments { - if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments { - if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() { - bracketed.colon2_token = Some(Default::default()); +pub struct ReplaceSelf(pub Span); + +impl ReplaceSelf { + #[cfg_attr(not(self_span_hack), allow(clippy::unused_self))] + fn prepend_underscore_to_self(&self, ident: &mut Ident) -> bool { + let modified = ident == "self"; + if modified { + *ident = Ident::new("__self", ident.span()); + #[cfg(self_span_hack)] + ident.set_span(self.0); + } + modified + } + + fn visit_token_stream(&mut self, tokens: &mut TokenStream) -> bool { + let mut out = Vec::new(); + let mut modified = false; + visit_token_stream_impl(self, tokens.clone(), &mut modified, &mut out); + if modified { + *tokens = TokenStream::from_iter(out); + } + return modified; + + fn visit_token_stream_impl( + visitor: &mut ReplaceSelf, + tokens: TokenStream, + modified: &mut bool, + out: &mut Vec, + ) { + for tt in tokens { + match tt { + TokenTree::Ident(mut ident) => { + *modified |= visitor.prepend_underscore_to_self(&mut ident); + out.push(TokenTree::Ident(ident)); } + TokenTree::Group(group) => { + let mut content = group.stream(); + *modified |= visitor.visit_token_stream(&mut content); + let mut new = Group::new(group.delimiter(), content); + new.set_span(group.span()); + out.push(TokenTree::Group(new)); + } + other => out.push(other), } } - } else { - let span = path.segments[0].ident.span(); - let msg = "Self type of this impl is unsupported in expression position"; - let error = Error::new(span, msg).to_compile_error(); - *path = parse_quote!(::core::marker::PhantomData::<#error>); } } } -impl VisitMut for ReplaceReceiver { - // `Self` -> `Receiver` - fn visit_type_mut(&mut self, ty: &mut Type) { - if let Type::Path(node) = ty { - if node.qself.is_none() && node.path.is_ident("Self") { - *ty = self.with.clone(); - } else { - self.visit_type_path_mut(node); - } - } else { - visit_mut::visit_type_mut(self, ty); - } - } - - // `Self::Assoc` -> `::Assoc` - fn visit_type_path_mut(&mut self, ty: &mut TypePath) { - if ty.qself.is_none() { - self.self_to_qself_type(&mut ty.qself, &mut ty.path); +impl VisitMut for ReplaceSelf { + fn visit_ident_mut(&mut self, i: &mut Ident) { + self.prepend_underscore_to_self(i); + } + + fn visit_path_mut(&mut self, p: &mut Path) { + if p.segments.len() == 1 { + // Replace `self`, but not `self::function`. + self.visit_ident_mut(&mut p.segments[0].ident); + } + for segment in &mut p.segments { + self.visit_path_arguments_mut(&mut segment.arguments); } - visit_mut::visit_type_path_mut(self, ty); } - // `Self::method` -> `::method` - fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) { - if expr.qself.is_none() { - prepend_underscore_to_self(&mut expr.path.segments[0].ident); - self.self_to_qself_expr(&mut expr.qself, &mut expr.path); - } - visit_mut::visit_expr_path_mut(self, expr); - } - - fn visit_expr_struct_mut(&mut self, expr: &mut ExprStruct) { - if expr.path.is_ident("Self") { - self.self_to_expr_path(&mut expr.path); + fn visit_item_mut(&mut self, i: &mut Item) { + // Visit `macro_rules!` because locally defined macros can refer to + // `self`. + // + // Visit `futures::select` and similar select macros, which commonly + // appear syntactically like an item despite expanding to an expression. + // + // Otherwise, do not recurse into nested items. + if let Item::Macro(i) = i { + if i.mac.path.is_ident("macro_rules") + || i.mac.path.segments.last().unwrap().ident == "select" + { + self.visit_macro_mut(&mut i.mac); + } } - visit_mut::visit_expr_struct_mut(self, expr); } - fn visit_item_mut(&mut self, _: &mut Item) { - // Do not recurse into nested items. - } - - fn visit_macro_mut(&mut self, i: &mut Macro) { + fn visit_macro_mut(&mut self, mac: &mut Macro) { // We can't tell in general whether `self` inside a macro invocation // refers to the self in the argument list or a different self // introduced within the macro. Heuristic: if the macro input contains // `fn`, then `self` is more likely to refer to something other than the // outer function's self argument. - if !contains_fn(i.tokens.clone()) { - fold_token_stream(&mut i.tokens); + if !contains_fn(mac.tokens.clone()) { + self.visit_token_stream(&mut mac.tokens); } } } - -fn contains_fn(tokens: TokenStream) -> bool { - tokens.into_iter().any(|tt| match tt { - TokenTree::Ident(ident) => ident == "fn", - TokenTree::Group(group) => contains_fn(group.stream()), - _ => false, - }) -} - -fn fold_token_stream(tokens: &mut TokenStream) -> bool { - let mut out = Vec::new(); - let mut modified = false; - for tt in tokens.clone() { - match tt { - TokenTree::Ident(mut ident) => { - modified |= prepend_underscore_to_self(&mut ident); - out.push(TokenTree::Ident(ident)); - } - TokenTree::Group(group) => { - let mut content = group.stream(); - modified |= fold_token_stream(&mut content); - let mut new = Group::new(group.delimiter(), content); - new.set_span(group.span()); - out.push(TokenTree::Group(new)); - } - other => out.push(other), - } - } - if modified { - *tokens = TokenStream::from_iter(out); - } - modified -} - -fn prepend_underscore_to_self(ident: &mut Ident) -> bool { - let modified = ident == "self"; - if modified { - *ident = Ident::new("_self", ident.span()); - } - modified -} diff -Nru rust-async-trait-0.1.24/tests/compiletest.rs rust-async-trait-0.1.56/tests/compiletest.rs --- rust-async-trait-0.1.24/tests/compiletest.rs 2019-11-16 20:55:39.000000000 +0000 +++ rust-async-trait-0.1.56/tests/compiletest.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,4 +1,5 @@ #[rustversion::attr(not(nightly), ignore)] +#[cfg_attr(miri, ignore)] #[test] fn ui() { let t = trybuild::TestCases::new(); diff -Nru rust-async-trait-0.1.24/tests/executor/mod.rs rust-async-trait-0.1.56/tests/executor/mod.rs --- rust-async-trait-0.1.24/tests/executor/mod.rs 2019-09-16 03:01:30.000000000 +0000 +++ rust-async-trait-0.1.56/tests/executor/mod.rs 1973-11-29 21:33:09.000000000 +0000 @@ -4,6 +4,7 @@ use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; // Executor for a future that resolves immediately (test only). +#[allow(clippy::missing_panics_doc)] pub fn block_on_simple(mut fut: F) -> F::Output { unsafe fn clone(_null: *const ()) -> RawWaker { unimplemented!() diff -Nru rust-async-trait-0.1.24/tests/test.rs rust-async-trait-0.1.56/tests/test.rs --- rust-async-trait-0.1.24/tests/test.rs 2020-01-24 20:23:20.000000000 +0000 +++ rust-async-trait-0.1.56/tests/test.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,4 +1,16 @@ -#![cfg_attr(async_trait_nightly_testing, feature(specialization, const_generics))] +#![cfg_attr( + async_trait_nightly_testing, + feature(min_specialization, type_alias_impl_trait) +)] +#![allow( + clippy::let_underscore_drop, + clippy::let_unit_value, + clippy::missing_panics_doc, + clippy::missing_safety_doc, + clippy::needless_return, + clippy::trivially_copy_pass_by_ref, + clippy::unused_async +)] use async_trait::async_trait; @@ -148,6 +160,79 @@ #[async_trait] unsafe trait UnsafeTraitPrivate {} +pub async fn test_can_destruct() { + #[async_trait] + trait CanDestruct { + async fn f(&self, foos: (u8, u8, u8, u8)); + } + + #[async_trait] + impl CanDestruct for Struct { + async fn f(&self, (a, ref mut b, ref c, d): (u8, u8, u8, u8)) { + let _a: u8 = a; + let _b: &mut u8 = b; + let _c: &u8 = c; + let _d: u8 = d; + } + } +} + +pub async fn test_self_in_macro() { + #[async_trait] + trait Trait { + async fn a(self); + async fn b(&mut self); + async fn c(&self); + } + + #[async_trait] + impl Trait for String { + async fn a(self) { + println!("{}", self); + } + async fn b(&mut self) { + println!("{}", self); + } + async fn c(&self) { + println!("{}", self); + } + } +} + +pub async fn test_inference() { + #[async_trait] + pub trait Trait { + async fn f() -> Box> { + Box::new(std::iter::empty()) + } + } +} + +pub async fn test_internal_items() { + #[async_trait] + #[allow(dead_code, clippy::items_after_statements)] + pub trait Trait: Sized { + async fn f(self) { + struct Struct; + + impl Struct { + fn f(self) { + let _ = self; + } + } + } + } +} + +pub async fn test_unimplemented() { + #[async_trait] + pub trait Trait { + async fn f() { + unimplemented!() + } + } +} + // https://github.com/dtolnay/async-trait/issues/1 pub mod issue1 { use async_trait::async_trait; @@ -416,14 +501,163 @@ impl StaticWithWhereSelf for Struct {} } +// https://github.com/dtolnay/async-trait/issues/45 +pub mod issue45 { + use crate::executor; + use async_trait::async_trait; + use std::fmt::Debug; + use std::sync::atomic::{AtomicU64, Ordering}; + use std::sync::{Arc, Mutex}; + use tracing::event::Event; + use tracing::field::{Field, Visit}; + use tracing::span::{Attributes, Id, Record}; + use tracing::{info, instrument, subscriber, Metadata, Subscriber}; + + #[async_trait] + pub trait Parent { + async fn foo(&mut self, v: usize); + } + + #[async_trait] + pub trait Child { + async fn bar(&self); + } + + #[derive(Debug)] + struct Impl(usize); + + #[async_trait] + impl Parent for Impl { + #[instrument] + async fn foo(&mut self, v: usize) { + self.0 = v; + self.bar().await; + } + } + + #[async_trait] + impl Child for Impl { + // Let's check that tracing detects the renaming of the `self` variable + // too, as tracing::instrument is not going to be able to skip the + // `self` argument if it can't find it in the function signature. + #[instrument(skip(self))] + async fn bar(&self) { + info!(val = self.0); + } + } + + // A simple subscriber implementation to test the behavior of async-trait + // with tokio-rs/tracing. This implementation is not robust against race + // conditions, but it's not an issue here as we are only polling on a single + // future at a time. + #[derive(Debug)] + struct SubscriberInner { + current_depth: AtomicU64, + // We assert that nested functions work. If the fix were to break, we + // would see two top-level functions instead of `bar` nested in `foo`. + max_depth: AtomicU64, + max_span_id: AtomicU64, + // Name of the variable / value / depth when the event was recorded. + value: Mutex>, + } + + #[derive(Debug, Clone)] + struct TestSubscriber { + inner: Arc, + } + + impl TestSubscriber { + fn new() -> Self { + TestSubscriber { + inner: Arc::new(SubscriberInner { + current_depth: AtomicU64::new(0), + max_depth: AtomicU64::new(0), + max_span_id: AtomicU64::new(1), + value: Mutex::new(None), + }), + } + } + } + + struct U64Visitor(Option<(&'static str, u64)>); + + impl Visit for U64Visitor { + fn record_debug(&mut self, _field: &Field, _value: &dyn Debug) {} + + fn record_u64(&mut self, field: &Field, value: u64) { + self.0 = Some((field.name(), value)); + } + } + + impl Subscriber for TestSubscriber { + fn enabled(&self, _metadata: &Metadata) -> bool { + true + } + fn new_span(&self, _span: &Attributes) -> Id { + Id::from_u64(self.inner.max_span_id.fetch_add(1, Ordering::AcqRel)) + } + fn record(&self, _span: &Id, _values: &Record) {} + fn record_follows_from(&self, _span: &Id, _follows: &Id) {} + fn event(&self, event: &Event) { + let mut visitor = U64Visitor(None); + event.record(&mut visitor); + if let Some((s, v)) = visitor.0 { + let current_depth = self.inner.current_depth.load(Ordering::Acquire); + *self.inner.value.lock().unwrap() = Some((s, v, current_depth)); + } + } + fn enter(&self, _span: &Id) { + let old_depth = self.inner.current_depth.fetch_add(1, Ordering::AcqRel); + if old_depth + 1 > self.inner.max_depth.load(Ordering::Acquire) { + self.inner.max_depth.fetch_add(1, Ordering::AcqRel); + } + } + fn exit(&self, _span: &Id) { + self.inner.current_depth.fetch_sub(1, Ordering::AcqRel); + } + } + + #[test] + fn tracing() { + // Create the future outside of the subscriber, as no call to tracing + // should be made until the future is polled. + let mut struct_impl = Impl(0); + let fut = struct_impl.foo(5); + let subscriber = TestSubscriber::new(); + subscriber::with_default(subscriber.clone(), || executor::block_on_simple(fut)); + // Did we enter bar inside of foo? + assert_eq!(subscriber.inner.max_depth.load(Ordering::Acquire), 2); + // Have we exited all spans? + assert_eq!(subscriber.inner.current_depth.load(Ordering::Acquire), 0); + // Did we create only two spans? Note: spans start at 1, hence the -1. + assert_eq!(subscriber.inner.max_span_id.load(Ordering::Acquire) - 1, 2); + // Was the value recorded at the right depth i.e. in the right function? + // If so, was it the expected value? + assert_eq!(*subscriber.inner.value.lock().unwrap(), Some(("val", 5, 2))); + } +} + // https://github.com/dtolnay/async-trait/issues/46 pub mod issue46 { use async_trait::async_trait; - macro_rules! implement_commands { + macro_rules! implement_commands_workaround { ($tyargs:tt : $ty:tt) => { #[async_trait] - pub trait AsyncCommands: Sized { + pub trait AsyncCommands1: Sized { + async fn f<$tyargs: $ty>(&mut self, x: $tyargs) { + self.f(x).await + } + } + }; + } + + implement_commands_workaround!(K: Send); + + macro_rules! implement_commands { + ($tyargs:ident : $ty:ident) => { + #[async_trait] + pub trait AsyncCommands2: Sized { async fn f<$tyargs: $ty>(&mut self, x: $tyargs) { self.f(x).await } @@ -502,3 +736,717 @@ executor::block_on_simple(fut); } } + +// https://github.com/dtolnay/async-trait/issues/68 +pub mod issue68 { + #[rustversion::since(1.40)] // procedural macros cannot expand to macro definitions in 1.39. + #[async_trait::async_trait] + pub trait Example { + async fn method(&self) { + macro_rules! t { + () => {{ + let _: &Self = self; + }}; + } + t!(); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/73 +pub mod issue73 { + use async_trait::async_trait; + + #[async_trait] + pub trait Example { + const ASSOCIATED: &'static str; + + async fn associated(&self) { + println!("Associated:{}", Self::ASSOCIATED); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/81 +pub mod issue81 { + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + async fn handle(&self); + } + + pub enum Enum { + Variant, + } + + #[async_trait] + impl Trait for Enum { + async fn handle(&self) { + let Enum::Variant = self; + let Self::Variant = self; + } + } +} + +// https://github.com/dtolnay/async-trait/issues/83 +pub mod issue83 { + #![allow(clippy::needless_arbitrary_self_type)] + + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + async fn f(&self) {} + async fn g(self: &Self) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/85 +pub mod issue85 { + #![deny(non_snake_case)] + + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + #[allow(non_snake_case)] + async fn camelCase(); + } + + pub struct Struct; + + #[async_trait] + impl Trait for Struct { + async fn camelCase() {} + } +} + +// https://github.com/dtolnay/async-trait/issues/87 +pub mod issue87 { + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + async fn f(&self); + } + + pub enum Tuple { + V(), + } + + pub enum Struct { + V {}, + } + + #[async_trait] + impl Trait for Tuple { + async fn f(&self) { + let Tuple::V() = self; + let Self::V() = self; + let _ = Self::V; + let _ = Self::V(); + } + } + + #[async_trait] + impl Trait for Struct { + async fn f(&self) { + let Struct::V {} = self; + let Self::V {} = self; + let _ = Self::V {}; + } + } +} + +// https://github.com/dtolnay/async-trait/issues/89 +pub mod issue89 { + #![allow(bare_trait_objects)] + + use async_trait::async_trait; + + #[async_trait] + trait Trait { + async fn f(&self); + } + + #[async_trait] + impl Trait for Send + Sync { + async fn f(&self) {} + } + + #[async_trait] + impl Trait for dyn Fn(i8) + Send + Sync { + async fn f(&self) {} + } + + #[async_trait] + impl Trait for (dyn Fn(u8) + Send + Sync) { + async fn f(&self) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/92 +pub mod issue92 { + use async_trait::async_trait; + + macro_rules! mac { + ($($tt:tt)*) => { + $($tt)* + }; + } + + pub struct Struct { + _x: T, + } + + impl Struct { + const ASSOCIATED1: &'static str = "1"; + async fn associated1() {} + } + + #[async_trait] + pub trait Trait + where + mac!(Self): Send, + { + const ASSOCIATED2: &'static str; + type Associated2; + + #[allow(path_statements, clippy::no_effect)] + async fn associated2(&self) { + // trait items + mac!(let _: Self::Associated2;); + mac!(let _: ::Associated2;); + mac!(let _: ::Associated2;); + mac!(Self::ASSOCIATED2;); + mac!(::ASSOCIATED2;); + mac!(::ASSOCIATED2;); + mac!(let _ = Self::associated2(self);); + mac!(let _ = ::associated2(self);); + mac!(let _ = ::associated2(self);); + } + } + + #[async_trait] + impl Trait for Struct + where + mac!(Self): Send, + { + const ASSOCIATED2: &'static str = "2"; + type Associated2 = (); + + #[allow(path_statements, clippy::no_effect)] + async fn associated2(&self) { + // inherent items + mac!(Self::ASSOCIATED1;); + mac!(::ASSOCIATED1;); + mac!(let _ = Self::associated1();); + mac!(let _ = ::associated1();); + + // trait items + mac!(let _: ::Associated2;); + mac!(Self::ASSOCIATED2;); + mac!(::ASSOCIATED2;); + mac!(::ASSOCIATED2;); + mac!(let _ = Self::associated2(self);); + mac!(let _ = ::associated2(self);); + mac!(let _ = ::associated2(self);); + } + } + + pub struct Unit; + + #[async_trait] + impl Trait for Unit { + const ASSOCIATED2: &'static str = "2"; + type Associated2 = (); + + async fn associated2(&self) { + mac!(let Self: Self = *self;); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/92#issuecomment-683370136 +pub mod issue92_2 { + use async_trait::async_trait; + + macro_rules! mac { + ($($tt:tt)*) => { + $($tt)* + }; + } + + pub trait Trait1 { + fn func1(); + } + + #[async_trait] + pub trait Trait2: Trait1 { + async fn func2() { + mac!(Self::func1()); + + macro_rules! mac2 { + ($($tt:tt)*) => { + Self::func1(); + }; + } + mac2!(); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/104 +pub mod issue104 { + use async_trait::async_trait; + + #[async_trait] + trait T1 { + async fn id(&self) -> i32; + } + + macro_rules! impl_t1 { + ($ty:ty, $id:expr) => { + #[async_trait] + impl T1 for $ty { + async fn id(&self) -> i32 { + $id + } + } + }; + } + + struct Foo; + + impl_t1!(Foo, 1); +} + +// https://github.com/dtolnay/async-trait/issues/106 +pub mod issue106 { + use async_trait::async_trait; + use std::future::Future; + + #[async_trait] + pub trait ProcessPool: Send + Sync { + type ThreadPool; + + async fn spawn(&self, work: F) -> T + where + F: FnOnce(&Self::ThreadPool) -> Fut + Send, + Fut: Future + 'static; + } + + #[async_trait] + impl

ProcessPool for &P + where + P: ?Sized + ProcessPool, + { + type ThreadPool = P::ThreadPool; + + async fn spawn(&self, work: F) -> T + where + F: FnOnce(&Self::ThreadPool) -> Fut + Send, + Fut: Future + 'static, + { + (**self).spawn(work).await + } + } +} + +// https://github.com/dtolnay/async-trait/issues/110 +pub mod issue110 { + use async_trait::async_trait; + use std::marker::PhantomData; + + #[async_trait] + pub trait Loader { + async fn load(&self, key: &str); + } + + pub struct AwsEc2MetadataLoader<'a> { + marker: PhantomData<&'a ()>, + } + + #[async_trait] + impl Loader for AwsEc2MetadataLoader<'_> { + async fn load(&self, _key: &str) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/120 +pub mod issue120 { + #![deny(clippy::trivially_copy_pass_by_ref)] + + use async_trait::async_trait; + + #[async_trait] + trait Trait { + async fn f(&self); + } + + #[async_trait] + impl Trait for () { + async fn f(&self) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/123 +pub mod issue123 { + use async_trait::async_trait; + + #[async_trait] + trait Trait { + async fn f(&self) -> &str + where + T: 'async_trait, + { + "default" + } + } + + #[async_trait] + impl Trait for () {} +} + +// https://github.com/dtolnay/async-trait/issues/129 +pub mod issue129 { + use async_trait::async_trait; + + #[async_trait] + pub trait TestTrait { + async fn a(_b: u8, c: u8) -> u8 { + c + } + } + + pub struct TestStruct; + + #[async_trait] + impl TestTrait for TestStruct { + async fn a(_b: u8, c: u8) -> u8 { + c + } + } +} + +// https://github.com/dtolnay/async-trait/issues/134 +#[cfg(async_trait_nightly_testing)] +pub mod issue134 { + use async_trait::async_trait; + + #[async_trait] + trait TestTrait { + async fn run(self) + where + Self: Sized, + { + } + } + + pub struct TestStruct; + + #[async_trait] + impl TestTrait for TestStruct { + async fn run(self) + where + Self: Sized, + { + } + } +} + +// https://github.com/dtolnay/async-trait/pull/125#pullrequestreview-491880881 +pub mod drop_order { + use crate::executor; + use async_trait::async_trait; + use std::sync::atomic::{AtomicBool, Ordering}; + + struct Flagger<'a>(&'a AtomicBool); + + impl Drop for Flagger<'_> { + fn drop(&mut self) { + self.0.fetch_xor(true, Ordering::AcqRel); + } + } + + #[async_trait] + trait Trait { + async fn async_trait(_: Flagger<'_>, flag: &AtomicBool); + } + + struct Struct; + + #[async_trait] + impl Trait for Struct { + async fn async_trait(_: Flagger<'_>, flag: &AtomicBool) { + flag.fetch_or(true, Ordering::AcqRel); + } + } + + async fn standalone(_: Flagger<'_>, flag: &AtomicBool) { + flag.fetch_or(true, Ordering::AcqRel); + } + + #[async_trait] + trait SelfTrait { + async fn async_trait(self, flag: &AtomicBool); + } + + #[async_trait] + impl SelfTrait for Flagger<'_> { + async fn async_trait(self, flag: &AtomicBool) { + flag.fetch_or(true, Ordering::AcqRel); + } + } + + #[test] + fn test_drop_order() { + // 0 : 0 ^ 1 = 1 | 1 = 1 (if flagger then block) + // 0 : 0 | 1 = 1 ^ 1 = 0 (if block then flagger) + + let flag = AtomicBool::new(false); + executor::block_on_simple(standalone(Flagger(&flag), &flag)); + assert!(!flag.load(Ordering::Acquire)); + + executor::block_on_simple(Struct::async_trait(Flagger(&flag), &flag)); + assert!(!flag.load(Ordering::Acquire)); + + executor::block_on_simple(Flagger(&flag).async_trait(&flag)); + assert!(!flag.load(Ordering::Acquire)); + } +} + +// https://github.com/dtolnay/async-trait/issues/145 +pub mod issue145 { + #![deny(clippy::type_complexity)] + + use async_trait::async_trait; + + #[async_trait] + pub trait ManageConnection: Sized + Send + Sync + 'static { + type Connection: Send + 'static; + type Error: Send + 'static; + + async fn connect(&self) -> Result; + } +} + +// https://github.com/dtolnay/async-trait/issues/147 +pub mod issue147 { + #![deny(clippy::let_unit_value)] + + use async_trait::async_trait; + + pub struct MyType; + + #[async_trait] + pub trait MyTrait { + async fn x(); + async fn y() -> (); + async fn z(); + } + + #[async_trait] + impl MyTrait for MyType { + async fn x() {} + async fn y() -> () {} + async fn z() { + unimplemented!() + } + } +} + +// https://github.com/dtolnay/async-trait/issues/149 +pub mod issue149 { + use async_trait::async_trait; + + pub struct Thing; + pub trait Ret {} + impl Ret for Thing {} + + pub async fn ok() -> &'static dyn Ret { + return &Thing; + } + + #[async_trait] + pub trait Trait { + async fn fail() -> &'static dyn Ret { + return &Thing; + } + } +} + +// https://github.com/dtolnay/async-trait/issues/152 +#[cfg(async_trait_nightly_testing)] +pub mod issue152 { + use async_trait::async_trait; + + #[async_trait] + trait Trait { + type Assoc; + + async fn f(&self) -> Self::Assoc; + } + + struct Struct; + + #[async_trait] + impl Trait for Struct { + type Assoc = impl Sized; + + async fn f(&self) -> Self::Assoc {} + } +} + +// https://github.com/dtolnay/async-trait/issues/154 +pub mod issue154 { + #![deny(clippy::items_after_statements)] + + use async_trait::async_trait; + + #[async_trait] + pub trait MyTrait { + async fn f(&self); + } + + pub struct Struct; + + #[async_trait] + impl MyTrait for Struct { + async fn f(&self) { + const MAX: u16 = 128; + println!("{}", MAX); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/158 +pub mod issue158 { + use async_trait::async_trait; + + fn f() {} + + #[async_trait] + pub trait Trait { + async fn f(&self) { + self::f(); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/161 +#[allow(clippy::mut_mut)] +pub mod issue161 { + use async_trait::async_trait; + use futures::future::FutureExt; + use std::sync::Arc; + + #[async_trait] + pub trait Trait { + async fn f(self: Arc); + } + + pub struct MyStruct(bool); + + #[async_trait] + impl Trait for MyStruct { + async fn f(self: Arc) { + futures::select! { + _ = async { + println!("{}", self.0); + }.fuse() => {} + } + } + } +} + +// https://github.com/dtolnay/async-trait/issues/169 +#[deny(where_clauses_object_safety)] +pub mod issue169 { + use async_trait::async_trait; + + #[async_trait] + pub trait Trait: ::core::marker::Sync { + async fn f(&self) {} + } + + pub fn test(_t: &dyn Trait) {} +} + +// https://github.com/dtolnay/async-trait/issues/177 +pub mod issue177 { + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + async fn foo(&self, _callback: impl FnMut(&str) + Send) {} + } + + pub struct Struct; + + #[async_trait] + impl Trait for Struct { + async fn foo(&self, _callback: impl FnMut(&str) + Send) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/183 +pub mod issue183 { + #![deny(clippy::shadow_same)] + + use async_trait::async_trait; + + #[async_trait] + trait Foo { + async fn foo(_n: i32) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/199 +pub mod issue199 { + use async_trait::async_trait; + use std::cell::Cell; + + struct IncrementOnDrop<'a>(&'a Cell); + + impl<'a> Drop for IncrementOnDrop<'a> { + fn drop(&mut self) { + self.0.set(self.0.get() + 1); + } + } + + #[async_trait(?Send)] + trait Trait { + async fn f(counter: &Cell, arg: IncrementOnDrop<'_>); + } + + struct Struct; + + #[async_trait(?Send)] + impl Trait for Struct { + async fn f(counter: &Cell, _: IncrementOnDrop<'_>) { + assert_eq!(counter.get(), 0); // second arg not dropped yet + } + } + + #[test] + fn test() { + let counter = Cell::new(0); + let future = Struct::f(&counter, IncrementOnDrop(&counter)); + assert_eq!(counter.get(), 0); + drop(future); + assert_eq!(counter.get(), 1); + } +} + +// https://github.com/dtolnay/async-trait/issues/204 +pub mod issue204 { + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + async fn f(arg: &impl Trait); + async fn g(arg: *const impl Trait); + } +} diff -Nru rust-async-trait-0.1.24/tests/ui/arg-implementation-detail.rs rust-async-trait-0.1.56/tests/ui/arg-implementation-detail.rs --- rust-async-trait-0.1.24/tests/ui/arg-implementation-detail.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/arg-implementation-detail.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,22 @@ +use async_trait::async_trait; + +pub struct Struct; + +#[async_trait] +pub trait Trait { + async fn f((_a, _b): (Struct, Struct)) { + // Expands to something like: + // + // fn f(__arg0: (Struct, Struct)) -> … { + // Box::pin(async move { + // let (_a, _b) = __arg0; + // … + // }) + // } + // + // but user's code must not be allowed to name that temporary argument: + let _ = __arg0; + } +} + +fn main() {} diff -Nru rust-async-trait-0.1.24/tests/ui/arg-implementation-detail.stderr rust-async-trait-0.1.56/tests/ui/arg-implementation-detail.stderr --- rust-async-trait-0.1.24/tests/ui/arg-implementation-detail.stderr 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/arg-implementation-detail.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,5 @@ +error[E0425]: cannot find value `__arg0` in this scope + --> tests/ui/arg-implementation-detail.rs:18:17 + | +18 | let _ = __arg0; + | ^^^^^^ not found in this scope diff -Nru rust-async-trait-0.1.24/tests/ui/bare-trait-object.rs rust-async-trait-0.1.56/tests/ui/bare-trait-object.rs --- rust-async-trait-0.1.24/tests/ui/bare-trait-object.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/bare-trait-object.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,15 @@ +#![deny(bare_trait_objects)] + +use async_trait::async_trait; + +#[async_trait] +trait Trait { + async fn f(&self); +} + +#[async_trait] +impl Trait for Send + Sync { + async fn f(&self) {} +} + +fn main() {} diff -Nru rust-async-trait-0.1.24/tests/ui/bare-trait-object.stderr rust-async-trait-0.1.56/tests/ui/bare-trait-object.stderr --- rust-async-trait-0.1.24/tests/ui/bare-trait-object.stderr 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/bare-trait-object.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,18 @@ +error: trait objects without an explicit `dyn` are deprecated + --> tests/ui/bare-trait-object.rs:11:16 + | +11 | impl Trait for Send + Sync { + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/bare-trait-object.rs:1:9 + | +1 | #![deny(bare_trait_objects)] + | ^^^^^^^^^^^^^^^^^^ + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +11 - impl Trait for Send + Sync { +11 + impl Trait for dyn Send + Sync { + | diff -Nru rust-async-trait-0.1.24/tests/ui/consider-restricting.rs rust-async-trait-0.1.56/tests/ui/consider-restricting.rs --- rust-async-trait-0.1.24/tests/ui/consider-restricting.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/consider-restricting.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,26 @@ +// https://github.com/rust-lang/rust/issues/93828 + +use async_trait::async_trait; + +pub trait IntoUrl {} + +#[async_trait] +pub trait ClientExt { + async fn publish(&self, url: T); +} + +struct Client; + +#[async_trait] +impl ClientExt for Client { + async fn publish(&self, url: T) {} +} + +struct Client2; + +#[async_trait] +impl ClientExt for Client2 { + async fn publish(&self, url: T) {} +} + +fn main() {} diff -Nru rust-async-trait-0.1.24/tests/ui/consider-restricting.stderr rust-async-trait-0.1.56/tests/ui/consider-restricting.stderr --- rust-async-trait-0.1.24/tests/ui/consider-restricting.stderr 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/consider-restricting.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,33 @@ +error: future cannot be sent between threads safely + --> tests/ui/consider-restricting.rs:16:49 + | +16 | async fn publish(&self, url: T) {} + | ^^ future created by async block is not `Send` + | +note: captured value is not `Send` + --> tests/ui/consider-restricting.rs:16:41 + | +16 | async fn publish(&self, url: T) {} + | ^^^ has type `T` which is not `Send` + = note: required for the cast to the object type `dyn Future + Send` +help: consider further restricting this bound + | +16 | async fn publish(&self, url: T) {} + | +++++++++++++++++++ + +error: future cannot be sent between threads safely + --> tests/ui/consider-restricting.rs:23:40 + | +23 | async fn publish(&self, url: T) {} + | ^^ future created by async block is not `Send` + | +note: captured value is not `Send` + --> tests/ui/consider-restricting.rs:23:32 + | +23 | async fn publish(&self, url: T) {} + | ^^^ has type `T` which is not `Send` + = note: required for the cast to the object type `dyn Future + Send` +help: consider further restricting this bound + | +23 | async fn publish(&self, url: T) {} + | +++++++++++++++++++ diff -Nru rust-async-trait-0.1.24/tests/ui/delimiter-span.rs rust-async-trait-0.1.56/tests/ui/delimiter-span.rs --- rust-async-trait-0.1.24/tests/ui/delimiter-span.rs 2020-02-04 04:26:32.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/delimiter-span.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,7 +1,9 @@ +#![allow(unused_macro_rules)] + use async_trait::async_trait; macro_rules! picky { - (ident) => {}; + ($(t:tt)*) => {}; } #[async_trait] @@ -14,6 +16,7 @@ #[async_trait] impl Trait for Struct { async fn method() { + picky!({ 123, self }); picky!({ 123 }); } } diff -Nru rust-async-trait-0.1.24/tests/ui/delimiter-span.stderr rust-async-trait-0.1.56/tests/ui/delimiter-span.stderr --- rust-async-trait-0.1.24/tests/ui/delimiter-span.stderr 2020-02-04 04:26:32.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/delimiter-span.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -1,8 +1,17 @@ error: no rules expected the token `{` - --> $DIR/delimiter-span.rs:17:16 + --> tests/ui/delimiter-span.rs:19:16 | -3 | macro_rules! picky { +5 | macro_rules! picky { | ------------------ when calling this macro ... -17 | picky!({ 123 }); +19 | picky!({ 123, self }); + | ^ no rules expected this token in macro call + +error: no rules expected the token `{` + --> tests/ui/delimiter-span.rs:20:16 + | +5 | macro_rules! picky { + | ------------------ when calling this macro +... +20 | picky!({ 123 }); | ^ no rules expected this token in macro call diff -Nru rust-async-trait-0.1.24/tests/ui/lifetime-span.rs rust-async-trait-0.1.56/tests/ui/lifetime-span.rs --- rust-async-trait-0.1.24/tests/ui/lifetime-span.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/lifetime-span.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,36 @@ +use async_trait::async_trait; + +struct A; +struct B; + +#[async_trait] +pub trait Trait<'r> { + async fn method(&'r self); +} + +#[async_trait] +impl Trait for A { + async fn method(&self) {} +} + +#[async_trait] +impl<'r> Trait<'r> for B { + async fn method(&self) {} +} + +#[async_trait] +pub trait Trait2 { + async fn method<'r>(&'r self); +} + +#[async_trait] +impl Trait2 for A { + async fn method(&self) {} +} + +#[async_trait] +impl<'r> Trait2<'r> for B { + async fn method(&'r self) {} +} + +fn main() {} diff -Nru rust-async-trait-0.1.24/tests/ui/lifetime-span.stderr rust-async-trait-0.1.56/tests/ui/lifetime-span.stderr --- rust-async-trait-0.1.24/tests/ui/lifetime-span.stderr 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/lifetime-span.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,25 @@ +error[E0726]: implicit elided lifetime not allowed here + --> tests/ui/lifetime-span.rs:12:6 + | +12 | impl Trait for A { + | ^^^^^ expected lifetime parameter + | + = note: assuming a `'static` lifetime... +help: indicate the anonymous lifetime + | +12 | impl Trait<'_> for A { + | ++++ + +error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied + --> tests/ui/lifetime-span.rs:32:10 + | +32 | impl<'r> Trait2<'r> for B { + | ^^^^^^---- help: remove these generics + | | + | expected 0 lifetime arguments + | +note: trait defined here, with 0 lifetime parameters + --> tests/ui/lifetime-span.rs:22:11 + | +22 | pub trait Trait2 { + | ^^^^^^ diff -Nru rust-async-trait-0.1.24/tests/ui/missing-async-in-impl.rs rust-async-trait-0.1.56/tests/ui/missing-async-in-impl.rs --- rust-async-trait-0.1.24/tests/ui/missing-async-in-impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/missing-async-in-impl.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,15 @@ +use async_trait::async_trait; + +#[async_trait] +pub trait Trait { + async fn method(); +} + +pub struct Struct; + +#[async_trait] +impl Trait for Struct { + fn method() {} +} + +fn main() {} diff -Nru rust-async-trait-0.1.24/tests/ui/missing-async-in-impl.stderr rust-async-trait-0.1.56/tests/ui/missing-async-in-impl.stderr --- rust-async-trait-0.1.24/tests/ui/missing-async-in-impl.stderr 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/missing-async-in-impl.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,8 @@ +error[E0195]: lifetime parameters or bounds on method `method` do not match the trait declaration + --> tests/ui/missing-async-in-impl.rs:12:14 + | +5 | async fn method(); + | -------- lifetimes in impl do not match this method in trait +... +12 | fn method() {} + | ^ lifetimes do not match method in trait diff -Nru rust-async-trait-0.1.24/tests/ui/missing-async-in-trait.rs rust-async-trait-0.1.56/tests/ui/missing-async-in-trait.rs --- rust-async-trait-0.1.24/tests/ui/missing-async-in-trait.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/missing-async-in-trait.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,15 @@ +use async_trait::async_trait; + +#[async_trait] +pub trait Trait { + fn method(); +} + +pub struct Struct; + +#[async_trait] +impl Trait for Struct { + async fn method() {} +} + +fn main() {} diff -Nru rust-async-trait-0.1.24/tests/ui/missing-async-in-trait.stderr rust-async-trait-0.1.56/tests/ui/missing-async-in-trait.stderr --- rust-async-trait-0.1.24/tests/ui/missing-async-in-trait.stderr 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/missing-async-in-trait.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,8 @@ +error[E0195]: lifetime parameters or bounds on method `method` do not match the trait declaration + --> tests/ui/missing-async-in-trait.rs:12:14 + | +5 | fn method(); + | - lifetimes in impl do not match this method in trait +... +12 | async fn method() {} + | ^^^^^^^^ lifetimes do not match method in trait diff -Nru rust-async-trait-0.1.24/tests/ui/missing-body.rs rust-async-trait-0.1.56/tests/ui/missing-body.rs --- rust-async-trait-0.1.24/tests/ui/missing-body.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/missing-body.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,15 @@ +use async_trait::async_trait; + +#[async_trait] +trait Trait { + async fn f(&self); +} + +struct Thing; + +#[async_trait] +impl Trait for Thing { + async fn f(&self); +} + +fn main() {} diff -Nru rust-async-trait-0.1.24/tests/ui/missing-body.stderr rust-async-trait-0.1.56/tests/ui/missing-body.stderr --- rust-async-trait-0.1.24/tests/ui/missing-body.stderr 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/missing-body.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,7 @@ +error: associated function in `impl` without body + --> tests/ui/missing-body.rs:12:5 + | +12 | async fn f(&self); + | ^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the function: `{ }` diff -Nru rust-async-trait-0.1.24/tests/ui/must-use.rs rust-async-trait-0.1.56/tests/ui/must-use.rs --- rust-async-trait-0.1.24/tests/ui/must-use.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/must-use.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,21 @@ +#![deny(unused_must_use)] + +use async_trait::async_trait; + +#[async_trait] +trait Interface { + async fn f(&self); +} + +struct Thing; + +#[async_trait] +impl Interface for Thing { + async fn f(&self) {} +} + +pub async fn f() { + Thing.f(); +} + +fn main() {} diff -Nru rust-async-trait-0.1.24/tests/ui/must-use.stderr rust-async-trait-0.1.56/tests/ui/must-use.stderr --- rust-async-trait-0.1.24/tests/ui/must-use.stderr 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/must-use.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,11 @@ +error: unused return value of `Interface::f` that must be used + --> tests/ui/must-use.rs:18:5 + | +18 | Thing.f(); + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/must-use.rs:1:9 + | +1 | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ diff -Nru rust-async-trait-0.1.24/tests/ui/self-span.rs rust-async-trait-0.1.56/tests/ui/self-span.rs --- rust-async-trait-0.1.24/tests/ui/self-span.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/self-span.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,30 @@ +use async_trait::async_trait; + +pub struct S {} + +pub enum E { + V {}, +} + +#[async_trait] +pub trait Trait { + async fn method(self); +} + +#[async_trait] +impl Trait for S { + async fn method(self) { + let _: () = self; + let _: Self = Self; + } +} + +#[async_trait] +impl Trait for E { + async fn method(self) { + let _: () = self; + let _: Self = Self::V; + } +} + +fn main() {} diff -Nru rust-async-trait-0.1.24/tests/ui/self-span.stderr rust-async-trait-0.1.56/tests/ui/self-span.stderr --- rust-async-trait-0.1.24/tests/ui/self-span.stderr 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/self-span.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> tests/ui/self-span.rs:17:21 + | +17 | let _: () = self; + | -- ^^^^ expected `()`, found struct `S` + | | + | expected due to this + +error: the `Self` constructor can only be used with tuple or unit structs + --> tests/ui/self-span.rs:18:23 + | +18 | let _: Self = Self; + | ^^^^ help: use curly brackets: `Self { /* fields */ }` + +error[E0308]: mismatched types + --> tests/ui/self-span.rs:25:21 + | +25 | let _: () = self; + | -- ^^^^ expected `()`, found enum `E` + | | + | expected due to this + +error[E0533]: expected unit struct, unit variant or constant, found struct variant `Self::V` + --> tests/ui/self-span.rs:26:23 + | +26 | let _: Self = Self::V; + | ^^^^^^^ diff -Nru rust-async-trait-0.1.24/tests/ui/send-not-implemented.rs rust-async-trait-0.1.56/tests/ui/send-not-implemented.rs --- rust-async-trait-0.1.24/tests/ui/send-not-implemented.rs 2019-11-16 20:57:14.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/send-not-implemented.rs 1973-11-29 21:33:09.000000000 +0000 @@ -10,6 +10,13 @@ let _guard = mutex.lock().unwrap(); f().await; } + + async fn test_ret(&self) -> bool { + let mutex = Mutex::new(()); + let _guard = mutex.lock().unwrap(); + f().await; + true + } } fn main() {} diff -Nru rust-async-trait-0.1.24/tests/ui/send-not-implemented.stderr rust-async-trait-0.1.56/tests/ui/send-not-implemented.stderr --- rust-async-trait-0.1.24/tests/ui/send-not-implemented.stderr 2019-12-13 09:53:58.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/send-not-implemented.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -1,5 +1,5 @@ error: future cannot be sent between threads safely - --> $DIR/send-not-implemented.rs:8:26 + --> tests/ui/send-not-implemented.rs:8:26 | 8 | async fn test(&self) { | __________________________^ @@ -7,16 +7,41 @@ 10 | | let _guard = mutex.lock().unwrap(); 11 | | f().await; 12 | | } - | |_____^ future returned by `__test` is not `Send` + | |_____^ future created by async block is not `Send` | - = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, ()>` + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` note: future is not `Send` as this value is used across an await - --> $DIR/send-not-implemented.rs:11:9 + --> tests/ui/send-not-implemented.rs:11:12 | 10 | let _guard = mutex.lock().unwrap(); - | ------ has type `std::sync::MutexGuard<'_, ()>` + | ------ has type `MutexGuard<'_, ()>` which is not `Send` 11 | f().await; - | ^^^^^^^^^ await occurs here, with `_guard` maybe used later + | ^^^^^^ await occurs here, with `_guard` maybe used later 12 | } | - `_guard` is later dropped here - = note: required for the cast to the object type `dyn std::future::Future + std::marker::Send` + = note: required for the cast to the object type `dyn Future + Send` + +error: future cannot be sent between threads safely + --> tests/ui/send-not-implemented.rs:14:38 + | +14 | async fn test_ret(&self) -> bool { + | ______________________________________^ +15 | | let mutex = Mutex::new(()); +16 | | let _guard = mutex.lock().unwrap(); +17 | | f().await; +18 | | true +19 | | } + | |_____^ future created by async block is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` +note: future is not `Send` as this value is used across an await + --> tests/ui/send-not-implemented.rs:17:12 + | +16 | let _guard = mutex.lock().unwrap(); + | ------ has type `MutexGuard<'_, ()>` which is not `Send` +17 | f().await; + | ^^^^^^ await occurs here, with `_guard` maybe used later +18 | true +19 | } + | - `_guard` is later dropped here + = note: required for the cast to the object type `dyn Future + Send` diff -Nru rust-async-trait-0.1.24/tests/ui/unreachable.rs rust-async-trait-0.1.56/tests/ui/unreachable.rs --- rust-async-trait-0.1.24/tests/ui/unreachable.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/unreachable.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,20 @@ +#![deny(warnings)] + +use async_trait::async_trait; + +#[async_trait] +pub trait Trait { + async fn f() { + unimplemented!() + } +} + +#[async_trait] +pub trait TraitFoo { + async fn f() { + let _y = unimplemented!(); + let _z = _y; + } +} + +fn main() {} diff -Nru rust-async-trait-0.1.24/tests/ui/unreachable.stderr rust-async-trait-0.1.56/tests/ui/unreachable.stderr --- rust-async-trait-0.1.24/tests/ui/unreachable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/unreachable.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,14 @@ +error: unreachable statement + --> tests/ui/unreachable.rs:16:9 + | +15 | let _y = unimplemented!(); + | ---------------- any code following this expression is unreachable +16 | let _z = _y; + | ^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> tests/ui/unreachable.rs:1:9 + | +1 | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unreachable_code)]` implied by `#[deny(warnings)]` diff -Nru rust-async-trait-0.1.24/tests/ui/unsupported-self.stderr rust-async-trait-0.1.56/tests/ui/unsupported-self.stderr --- rust-async-trait-0.1.24/tests/ui/unsupported-self.stderr 2019-12-04 09:57:44.000000000 +0000 +++ rust-async-trait-0.1.56/tests/ui/unsupported-self.stderr 1973-11-29 21:33:09.000000000 +0000 @@ -1,5 +1,5 @@ -error: Self type of this impl is unsupported in expression position - --> $DIR/unsupported-self.rs:11:17 +error: the `Self` constructor can only be used with tuple or unit structs + --> tests/ui/unsupported-self.rs:11:17 | 11 | let _ = Self; | ^^^^ diff -Nru rust-async-trait-0.1.24/.travis.yml rust-async-trait-0.1.56/.travis.yml --- rust-async-trait-0.1.24/.travis.yml 2019-10-26 17:27:32.000000000 +0000 +++ rust-async-trait-0.1.56/.travis.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -language: rust - -matrix: - include: - - rust: nightly - script: cargo test - env: RUSTFLAGS='--cfg async_trait_nightly_testing' - - rust: beta - script: cargo test - - rust: stable - script: cargo check