├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── dynosaur ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── examples │ ├── default_trait.rs │ ├── next.rs │ └── trait_variant.rs ├── src │ └── lib.rs └── tests │ ├── Cargo.toml │ ├── lib.rs │ ├── pass │ ├── anynomous-args.rs │ ├── anynomous-args.stdout │ ├── associated-types.rs │ ├── associated-types.stdout │ ├── async-and-non-async.rs │ ├── async-and-non-async.stdout │ ├── basic-apit.rs │ ├── basic-apit.stdout │ ├── basic-mut.rs │ ├── basic-mut.stdout │ ├── basic-no-ret.rs │ ├── basic-no-ret.stdout │ ├── basic-rpitit.rs │ ├── basic-rpitit.stdout │ ├── basic-with-self.rs │ ├── basic-with-self.stdout │ ├── basic.rs │ ├── basic.stdout │ ├── default-method-trait.rs │ ├── default-method-trait.stdout │ ├── handle-lifetimes.rs │ ├── handle-lifetimes.stdout │ ├── impl-future-bounds.rs │ ├── impl-future-bounds.stdout │ ├── multiple-lifetimes-and-where-clauses.rs │ ├── multiple-lifetimes-and-where-clauses.stdout │ ├── multiple-lifetimes.rs │ ├── multiple-lifetimes.stdout │ ├── non-future-impl-traits.rs │ ├── non-future-impl-traits.stdout │ ├── trait-variant.rs │ ├── trait-variant.stdout │ ├── visibility.rs │ ├── visibility.stdout │ ├── where-self-sized-rpit.rs │ ├── where-self-sized-rpit.stdout │ ├── where-self-sized.rs │ └── where-self-sized.stdout │ └── ui.rs └── dynosaur_derive ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT └── src ├── expand.rs ├── lib.rs ├── lifetime.rs ├── receiver.rs ├── sig.rs ├── traits.rs └── where_clauses.rs /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | workflow_dispatch: 9 | 10 | jobs: 11 | test: 12 | strategy: 13 | fail-fast: false 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: actions-rs/toolchain@v1 18 | with: 19 | profile: default 20 | toolchain: nightly 21 | override: true 22 | - name: Check formatting of all crates in the workspace 23 | uses: actions-rs/cargo@v1 24 | with: 25 | command: fmt 26 | args: --all -- --check 27 | - name: Run cargo test --all 28 | uses: actions-rs/cargo@v1 29 | with: 30 | command: test 31 | args: --all --locked 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["dynosaur", "dynosaur_derive", "dynosaur/tests"] 3 | resolver = "2" 4 | 5 | [workspace.dependencies] 6 | tokio = { version = "1.40.0", features = ["macros", "rt"] } 7 | trait-variant = "0.1" 8 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2024 The Rust Project Developers 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 The Rust Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Latest Version]][crates.io] [![Documentation]][docs.rs] [![GHA Status]][GitHub Actions] ![License] 2 | 3 | Currently Rust does not support dynamic dispatch on traits that use `async fn` or methods returning `impl Trait`. Dynosaur is a proc macro that allows dynamic dispatch on these traits but uses static dispatch otherwise. It requires at least Rust 1.75. 4 | 5 | This removes the need for the use of the `async_trait` proc macro, giving users the performance benefits of static dispatch without giving up the flexibility of dynamic dispatch. 6 | 7 | ```rust,ignore 8 | #[dynosaur::dynosaur(DynNext)] 9 | trait Next { 10 | type Item; 11 | async fn next(&mut self) -> Option; 12 | } 13 | ``` 14 | 15 | The macro above generates a type called `DynNext` which can be used like this: 16 | 17 | ```rust,ignore 18 | async fn dyn_dispatch(iter: &mut DynNext<'_, i32>) { 19 | while let Some(item) = iter.next().await { 20 | println!("- {item}"); 21 | } 22 | } 23 | 24 | let v = [1, 2, 3]; 25 | dyn_dispatch(&mut DynNext::boxed(my_next_iter).await; 26 | dyn_dispatch(DynNext::from_mut(&mut my_next_iter)).await; 27 | ``` 28 | 29 | Where `my_next_iter` is a value of a type that you would create that implements `Next`. For example: 30 | 31 | ```rust,ignore 32 | struct MyNextIter { 33 | v: Vec, 34 | i: usize, 35 | } 36 | 37 | impl Next for MyNextIter { 38 | type Item = T; 39 | 40 | async fn next(&mut self) -> Option { 41 | if self.i >= self.v.len() { 42 | return None; 43 | } 44 | do_some_async_work().await; 45 | let item = self.v[self.i]; 46 | self.i += 1; 47 | Some(item) 48 | } 49 | } 50 | 51 | async fn do_some_async_work() { 52 | // do something :) 53 | } 54 | ``` 55 | 56 | The general rule is that anywhere you would write `dyn Trait` (which would 57 | result in a compiler error), you instead write `DynTrait`. 58 | 59 | Methods returning `impl Trait` box their return types when dispatched 60 | dynamically, but not when dispatched statically. 61 | 62 | For more examples, take a look at [`dynosaur/examples`](dynosaur/examples) and [`dynosaur/tests/pass`](dynosaur/tests/pass). In tests you would find `.rs` files with what the user would write and `.stdout` files with what dynosaur generates. 63 | 64 | ## APIT Support 65 | 66 | Dynosaur supports dyn traits in argument position. In order to use them, the user needs an `impl MyTrait for Box {}` to be able to use impl MyTrait in argument position. 67 | 68 | TODO: In a future version, `dynosaur` will provide this impl for any trait with the `#[dynosaur]` attribute on the trait definition. 69 | 70 | ## What will it take to implement this support in Rust? 71 | 72 | There are many design questions to be answered before building this support into the language. You can find more background here: . 73 | 74 | ## How does this crate solve this issue? 75 | 76 | Given a trait `MyTrait`, this crate generates a struct called `DynMyTrait` that implements `MyTrait` by delegating to the actual impls on the concrete type and wrapping the result in a box. For more details on what is exactly generated you may want to check `.stdout` files in [`dynosaur/tests/pass`](dynosaur/tests/pass). 77 | 78 | #### License 79 | 80 | Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or 81 | [MIT license](LICENSE-MIT) at your option. 82 | 83 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in 84 | this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without 85 | any additional terms or conditions. 86 | 87 | [GitHub Actions]: https://github.com/spastorino/dynosaur/actions 88 | [GHA Status]: https://github.com/spastorino/dynosaur/actions/workflows/ci.yaml/badge.svg 89 | [crates.io]: https://crates.io/crates/dynosaur 90 | [Latest Version]: https://img.shields.io/crates/v/dynosaur.svg 91 | [Documentation]: https://img.shields.io/docsrs/dynosaur 92 | [docs.rs]: https://docs.rs/dynosaur 93 | [License]: https://img.shields.io/crates/l/dynosaur.svg 94 | -------------------------------------------------------------------------------- /dynosaur/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.21.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "annotate-snippets" 22 | version = "0.11.4" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991" 25 | dependencies = [ 26 | "anstyle", 27 | "unicode-width", 28 | ] 29 | 30 | [[package]] 31 | name = "anstyle" 32 | version = "1.0.7" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" 35 | 36 | [[package]] 37 | name = "anyhow" 38 | version = "1.0.86" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" 41 | 42 | [[package]] 43 | name = "backtrace" 44 | version = "0.3.71" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" 47 | dependencies = [ 48 | "addr2line", 49 | "cc", 50 | "cfg-if", 51 | "libc", 52 | "miniz_oxide", 53 | "object", 54 | "rustc-demangle", 55 | ] 56 | 57 | [[package]] 58 | name = "bstr" 59 | version = "1.9.1" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" 62 | dependencies = [ 63 | "memchr", 64 | "regex-automata", 65 | "serde", 66 | ] 67 | 68 | [[package]] 69 | name = "camino" 70 | version = "1.1.7" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" 73 | dependencies = [ 74 | "serde", 75 | ] 76 | 77 | [[package]] 78 | name = "cargo-platform" 79 | version = "0.1.8" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" 82 | dependencies = [ 83 | "serde", 84 | ] 85 | 86 | [[package]] 87 | name = "cargo_metadata" 88 | version = "0.18.1" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" 91 | dependencies = [ 92 | "camino", 93 | "cargo-platform", 94 | "semver", 95 | "serde", 96 | "serde_json", 97 | "thiserror", 98 | ] 99 | 100 | [[package]] 101 | name = "cc" 102 | version = "1.1.5" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" 105 | 106 | [[package]] 107 | name = "cfg-if" 108 | version = "1.0.0" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 111 | 112 | [[package]] 113 | name = "color-eyre" 114 | version = "0.6.3" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" 117 | dependencies = [ 118 | "backtrace", 119 | "color-spantrace", 120 | "eyre", 121 | "indenter", 122 | "once_cell", 123 | "owo-colors", 124 | "tracing-error", 125 | ] 126 | 127 | [[package]] 128 | name = "color-spantrace" 129 | version = "0.2.1" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" 132 | dependencies = [ 133 | "once_cell", 134 | "owo-colors", 135 | "tracing-core", 136 | "tracing-error", 137 | ] 138 | 139 | [[package]] 140 | name = "colored" 141 | version = "2.1.0" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" 144 | dependencies = [ 145 | "lazy_static", 146 | "windows-sys 0.48.0", 147 | ] 148 | 149 | [[package]] 150 | name = "comma" 151 | version = "1.0.0" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" 154 | 155 | [[package]] 156 | name = "console" 157 | version = "0.15.8" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" 160 | dependencies = [ 161 | "encode_unicode", 162 | "lazy_static", 163 | "libc", 164 | "unicode-width", 165 | "windows-sys 0.52.0", 166 | ] 167 | 168 | [[package]] 169 | name = "crossbeam-channel" 170 | version = "0.5.13" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" 173 | dependencies = [ 174 | "crossbeam-utils", 175 | ] 176 | 177 | [[package]] 178 | name = "crossbeam-utils" 179 | version = "0.8.20" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" 182 | 183 | [[package]] 184 | name = "dynosaur" 185 | version = "0.1.0" 186 | dependencies = [ 187 | "proc-macro2", 188 | "quote", 189 | "syn", 190 | "ui_test", 191 | ] 192 | 193 | [[package]] 194 | name = "encode_unicode" 195 | version = "0.3.6" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" 198 | 199 | [[package]] 200 | name = "eyre" 201 | version = "0.6.12" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" 204 | dependencies = [ 205 | "indenter", 206 | "once_cell", 207 | ] 208 | 209 | [[package]] 210 | name = "gimli" 211 | version = "0.28.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 214 | 215 | [[package]] 216 | name = "indenter" 217 | version = "0.3.3" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" 220 | 221 | [[package]] 222 | name = "indicatif" 223 | version = "0.17.8" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" 226 | dependencies = [ 227 | "console", 228 | "instant", 229 | "number_prefix", 230 | "portable-atomic", 231 | "unicode-width", 232 | ] 233 | 234 | [[package]] 235 | name = "instant" 236 | version = "0.1.13" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" 239 | dependencies = [ 240 | "cfg-if", 241 | ] 242 | 243 | [[package]] 244 | name = "itoa" 245 | version = "1.0.11" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 248 | 249 | [[package]] 250 | name = "lazy_static" 251 | version = "1.5.0" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 254 | 255 | [[package]] 256 | name = "levenshtein" 257 | version = "1.0.5" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" 260 | 261 | [[package]] 262 | name = "libc" 263 | version = "0.2.155" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" 266 | 267 | [[package]] 268 | name = "memchr" 269 | version = "2.7.4" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 272 | 273 | [[package]] 274 | name = "miniz_oxide" 275 | version = "0.7.4" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" 278 | dependencies = [ 279 | "adler", 280 | ] 281 | 282 | [[package]] 283 | name = "number_prefix" 284 | version = "0.4.0" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" 287 | 288 | [[package]] 289 | name = "object" 290 | version = "0.32.2" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 293 | dependencies = [ 294 | "memchr", 295 | ] 296 | 297 | [[package]] 298 | name = "once_cell" 299 | version = "1.19.0" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 302 | 303 | [[package]] 304 | name = "owo-colors" 305 | version = "3.5.0" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" 308 | 309 | [[package]] 310 | name = "pad" 311 | version = "0.1.6" 312 | source = "registry+https://github.com/rust-lang/crates.io-index" 313 | checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" 314 | dependencies = [ 315 | "unicode-width", 316 | ] 317 | 318 | [[package]] 319 | name = "pin-project-lite" 320 | version = "0.2.14" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 323 | 324 | [[package]] 325 | name = "portable-atomic" 326 | version = "1.6.0" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" 329 | 330 | [[package]] 331 | name = "prettydiff" 332 | version = "0.7.0" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "abec3fb083c10660b3854367697da94c674e9e82aa7511014dc958beeb7215e9" 335 | dependencies = [ 336 | "owo-colors", 337 | "pad", 338 | ] 339 | 340 | [[package]] 341 | name = "proc-macro2" 342 | version = "1.0.86" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 345 | dependencies = [ 346 | "unicode-ident", 347 | ] 348 | 349 | [[package]] 350 | name = "quote" 351 | version = "1.0.36" 352 | source = "registry+https://github.com/rust-lang/crates.io-index" 353 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 354 | dependencies = [ 355 | "proc-macro2", 356 | ] 357 | 358 | [[package]] 359 | name = "regex" 360 | version = "1.10.5" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" 363 | dependencies = [ 364 | "regex-automata", 365 | "regex-syntax", 366 | ] 367 | 368 | [[package]] 369 | name = "regex-automata" 370 | version = "0.4.7" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" 373 | dependencies = [ 374 | "regex-syntax", 375 | ] 376 | 377 | [[package]] 378 | name = "regex-syntax" 379 | version = "0.8.4" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" 382 | 383 | [[package]] 384 | name = "rustc-demangle" 385 | version = "0.1.24" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 388 | 389 | [[package]] 390 | name = "rustc_version" 391 | version = "0.4.0" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 394 | dependencies = [ 395 | "semver", 396 | ] 397 | 398 | [[package]] 399 | name = "rustfix" 400 | version = "0.8.4" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "4cef0c817217c330b3ef879e06455d726c1cffc800eaf7734d3b4ac63213636b" 403 | dependencies = [ 404 | "serde", 405 | "serde_json", 406 | "thiserror", 407 | "tracing", 408 | ] 409 | 410 | [[package]] 411 | name = "ryu" 412 | version = "1.0.18" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 415 | 416 | [[package]] 417 | name = "semver" 418 | version = "1.0.23" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" 421 | dependencies = [ 422 | "serde", 423 | ] 424 | 425 | [[package]] 426 | name = "serde" 427 | version = "1.0.204" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" 430 | dependencies = [ 431 | "serde_derive", 432 | ] 433 | 434 | [[package]] 435 | name = "serde_derive" 436 | version = "1.0.204" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" 439 | dependencies = [ 440 | "proc-macro2", 441 | "quote", 442 | "syn", 443 | ] 444 | 445 | [[package]] 446 | name = "serde_json" 447 | version = "1.0.120" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" 450 | dependencies = [ 451 | "itoa", 452 | "ryu", 453 | "serde", 454 | ] 455 | 456 | [[package]] 457 | name = "sharded-slab" 458 | version = "0.1.7" 459 | source = "registry+https://github.com/rust-lang/crates.io-index" 460 | checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 461 | dependencies = [ 462 | "lazy_static", 463 | ] 464 | 465 | [[package]] 466 | name = "spanned" 467 | version = "0.2.1" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "ed14ba8b4b82241bd5daba2c49185d4a0581a0058355fe96537338f002b8605d" 470 | dependencies = [ 471 | "bstr", 472 | "color-eyre", 473 | ] 474 | 475 | [[package]] 476 | name = "syn" 477 | version = "2.0.71" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" 480 | dependencies = [ 481 | "proc-macro2", 482 | "quote", 483 | "unicode-ident", 484 | ] 485 | 486 | [[package]] 487 | name = "thiserror" 488 | version = "1.0.62" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" 491 | dependencies = [ 492 | "thiserror-impl", 493 | ] 494 | 495 | [[package]] 496 | name = "thiserror-impl" 497 | version = "1.0.62" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" 500 | dependencies = [ 501 | "proc-macro2", 502 | "quote", 503 | "syn", 504 | ] 505 | 506 | [[package]] 507 | name = "thread_local" 508 | version = "1.1.8" 509 | source = "registry+https://github.com/rust-lang/crates.io-index" 510 | checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" 511 | dependencies = [ 512 | "cfg-if", 513 | "once_cell", 514 | ] 515 | 516 | [[package]] 517 | name = "tracing" 518 | version = "0.1.40" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 521 | dependencies = [ 522 | "pin-project-lite", 523 | "tracing-attributes", 524 | "tracing-core", 525 | ] 526 | 527 | [[package]] 528 | name = "tracing-attributes" 529 | version = "0.1.27" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 532 | dependencies = [ 533 | "proc-macro2", 534 | "quote", 535 | "syn", 536 | ] 537 | 538 | [[package]] 539 | name = "tracing-core" 540 | version = "0.1.32" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 543 | dependencies = [ 544 | "once_cell", 545 | "valuable", 546 | ] 547 | 548 | [[package]] 549 | name = "tracing-error" 550 | version = "0.2.0" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" 553 | dependencies = [ 554 | "tracing", 555 | "tracing-subscriber", 556 | ] 557 | 558 | [[package]] 559 | name = "tracing-subscriber" 560 | version = "0.3.18" 561 | source = "registry+https://github.com/rust-lang/crates.io-index" 562 | checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" 563 | dependencies = [ 564 | "sharded-slab", 565 | "thread_local", 566 | "tracing-core", 567 | ] 568 | 569 | [[package]] 570 | name = "ui_test" 571 | version = "0.24.0" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "bc1c6c78d55482388711c8d417b8e547263046a607512278fed274c54633bbe4" 574 | dependencies = [ 575 | "annotate-snippets", 576 | "anyhow", 577 | "bstr", 578 | "cargo-platform", 579 | "cargo_metadata", 580 | "color-eyre", 581 | "colored", 582 | "comma", 583 | "crossbeam-channel", 584 | "indicatif", 585 | "lazy_static", 586 | "levenshtein", 587 | "prettydiff", 588 | "regex", 589 | "rustc_version", 590 | "rustfix", 591 | "serde", 592 | "serde_json", 593 | "spanned", 594 | ] 595 | 596 | [[package]] 597 | name = "unicode-ident" 598 | version = "1.0.12" 599 | source = "registry+https://github.com/rust-lang/crates.io-index" 600 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 601 | 602 | [[package]] 603 | name = "unicode-width" 604 | version = "0.1.13" 605 | source = "registry+https://github.com/rust-lang/crates.io-index" 606 | checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" 607 | 608 | [[package]] 609 | name = "valuable" 610 | version = "0.1.0" 611 | source = "registry+https://github.com/rust-lang/crates.io-index" 612 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 613 | 614 | [[package]] 615 | name = "windows-sys" 616 | version = "0.48.0" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 619 | dependencies = [ 620 | "windows-targets 0.48.5", 621 | ] 622 | 623 | [[package]] 624 | name = "windows-sys" 625 | version = "0.52.0" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 628 | dependencies = [ 629 | "windows-targets 0.52.6", 630 | ] 631 | 632 | [[package]] 633 | name = "windows-targets" 634 | version = "0.48.5" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 637 | dependencies = [ 638 | "windows_aarch64_gnullvm 0.48.5", 639 | "windows_aarch64_msvc 0.48.5", 640 | "windows_i686_gnu 0.48.5", 641 | "windows_i686_msvc 0.48.5", 642 | "windows_x86_64_gnu 0.48.5", 643 | "windows_x86_64_gnullvm 0.48.5", 644 | "windows_x86_64_msvc 0.48.5", 645 | ] 646 | 647 | [[package]] 648 | name = "windows-targets" 649 | version = "0.52.6" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 652 | dependencies = [ 653 | "windows_aarch64_gnullvm 0.52.6", 654 | "windows_aarch64_msvc 0.52.6", 655 | "windows_i686_gnu 0.52.6", 656 | "windows_i686_gnullvm", 657 | "windows_i686_msvc 0.52.6", 658 | "windows_x86_64_gnu 0.52.6", 659 | "windows_x86_64_gnullvm 0.52.6", 660 | "windows_x86_64_msvc 0.52.6", 661 | ] 662 | 663 | [[package]] 664 | name = "windows_aarch64_gnullvm" 665 | version = "0.48.5" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 668 | 669 | [[package]] 670 | name = "windows_aarch64_gnullvm" 671 | version = "0.52.6" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 674 | 675 | [[package]] 676 | name = "windows_aarch64_msvc" 677 | version = "0.48.5" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 680 | 681 | [[package]] 682 | name = "windows_aarch64_msvc" 683 | version = "0.52.6" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 686 | 687 | [[package]] 688 | name = "windows_i686_gnu" 689 | version = "0.48.5" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 692 | 693 | [[package]] 694 | name = "windows_i686_gnu" 695 | version = "0.52.6" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 698 | 699 | [[package]] 700 | name = "windows_i686_gnullvm" 701 | version = "0.52.6" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 704 | 705 | [[package]] 706 | name = "windows_i686_msvc" 707 | version = "0.48.5" 708 | source = "registry+https://github.com/rust-lang/crates.io-index" 709 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 710 | 711 | [[package]] 712 | name = "windows_i686_msvc" 713 | version = "0.52.6" 714 | source = "registry+https://github.com/rust-lang/crates.io-index" 715 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 716 | 717 | [[package]] 718 | name = "windows_x86_64_gnu" 719 | version = "0.48.5" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 722 | 723 | [[package]] 724 | name = "windows_x86_64_gnu" 725 | version = "0.52.6" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 728 | 729 | [[package]] 730 | name = "windows_x86_64_gnullvm" 731 | version = "0.48.5" 732 | source = "registry+https://github.com/rust-lang/crates.io-index" 733 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 734 | 735 | [[package]] 736 | name = "windows_x86_64_gnullvm" 737 | version = "0.52.6" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 740 | 741 | [[package]] 742 | name = "windows_x86_64_msvc" 743 | version = "0.48.5" 744 | source = "registry+https://github.com/rust-lang/crates.io-index" 745 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 746 | 747 | [[package]] 748 | name = "windows_x86_64_msvc" 749 | version = "0.52.6" 750 | source = "registry+https://github.com/rust-lang/crates.io-index" 751 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 752 | -------------------------------------------------------------------------------- /dynosaur/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dynosaur" 3 | version = "0.2.0" 4 | authors = [ 5 | "Santiago Pastorino ", 6 | "Tyler Mandry ", 7 | "Niko Matsakis ", 8 | ] 9 | categories = ["asynchronous", "no-std"] 10 | keywords = ["async", "trait", "impl"] 11 | description = "Dynamic dispatch for return position impl traits and async in Rust" 12 | documentation = "https://docs.rs/dynosaur" 13 | license = "MIT OR Apache-2.0" 14 | repository = "https://github.com/spastorino/dynosaur" 15 | edition = "2021" 16 | rust-version = "1.75" 17 | 18 | [dependencies] 19 | dynosaur_derive = { version = "0.2", path = "../dynosaur_derive" } 20 | 21 | [dev-dependencies] 22 | tokio = { workspace = true } 23 | trait-variant = { workspace = true } 24 | ui_test = "0.28" 25 | 26 | [[example]] 27 | name = "next" 28 | 29 | [[example]] 30 | name = "trait_variant" 31 | 32 | [[test]] 33 | name = "ui" 34 | harness = false 35 | -------------------------------------------------------------------------------- /dynosaur/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2024 The Rust Project Developers 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /dynosaur/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 The Rust Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /dynosaur/README.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /dynosaur/examples/default_trait.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | 3 | #[dynosaur::dynosaur(DynFoo)] 4 | trait Foo { 5 | fn foo(&self) -> impl Display { 6 | 1 7 | } 8 | } 9 | 10 | impl Foo for i32 {} 11 | 12 | impl Foo for Box {} 13 | 14 | impl Foo for &mut S {} 15 | 16 | fn dyn_dispatch(f: &mut DynFoo<'_>) { 17 | print!("dyn_dispatch: "); 18 | let foo = f.foo(); 19 | println!("{foo} "); 20 | } 21 | 22 | fn static_dispatch(f: impl Foo) { 23 | print!("static_dispatch: "); 24 | let foo = f.foo(); 25 | println!("{foo} "); 26 | } 27 | 28 | fn main() { 29 | dyn_dispatch(&mut DynFoo::new_box(1)); 30 | dyn_dispatch(DynFoo::from_mut(&mut 1)); 31 | static_dispatch(1); 32 | static_dispatch(DynFoo::new_box(1)); 33 | static_dispatch(DynFoo::from_mut(&mut 1)); 34 | } 35 | -------------------------------------------------------------------------------- /dynosaur/examples/next.rs: -------------------------------------------------------------------------------- 1 | #[dynosaur::dynosaur(DynNext)] 2 | trait Next { 3 | type Item; 4 | async fn next(&mut self) -> Option; 5 | } 6 | 7 | async fn dyn_dispatch(iter: &mut DynNext<'_, i32>) { 8 | print!("dyn_dispatch: "); 9 | while let Some(item) = iter.next().await { 10 | print!("{item} "); 11 | } 12 | println!(); 13 | } 14 | 15 | async fn static_dispatch(mut iter: impl Next) { 16 | print!("static_dispatch: "); 17 | while let Some(item) = iter.next().await { 18 | print!("{item} "); 19 | } 20 | println!(); 21 | } 22 | 23 | #[tokio::main(flavor = "current_thread")] 24 | async fn main() { 25 | let v = [1, 2, 3]; 26 | dyn_dispatch(&mut DynNext::new_box(from_iter(v))).await; 27 | dyn_dispatch(DynNext::from_mut(&mut from_iter(v))).await; 28 | static_dispatch(from_iter(v)).await; 29 | static_dispatch(DynNext::new_box(from_iter(v))).await; 30 | static_dispatch(DynNext::from_mut(&mut from_iter(v))).await; 31 | } 32 | 33 | impl Next for Box { 34 | type Item = S::Item; 35 | fn next(&mut self) -> impl core::future::Future> { 36 | S::next(&mut *self) 37 | } 38 | } 39 | 40 | impl Next for &mut S { 41 | type Item = S::Item; 42 | fn next(&mut self) -> impl core::future::Future> { 43 | S::next(&mut *self) 44 | } 45 | } 46 | 47 | struct ForArray { 48 | v: [T; N], 49 | i: usize, 50 | } 51 | 52 | fn from_iter(v: [T; N]) -> ForArray { 53 | ForArray { v, i: 0 } 54 | } 55 | 56 | impl Next for ForArray { 57 | type Item = T; 58 | 59 | async fn next(&mut self) -> Option { 60 | if self.i >= self.v.len() { 61 | return None; 62 | } 63 | stuff().await; 64 | let item = self.v[self.i]; 65 | self.i += 1; 66 | Some(item) 67 | } 68 | } 69 | 70 | async fn stuff() {} 71 | -------------------------------------------------------------------------------- /dynosaur/examples/trait_variant.rs: -------------------------------------------------------------------------------- 1 | #[trait_variant::make(SendNext: Send)] 2 | #[dynosaur::dynosaur(DynNext = dyn Next)] 3 | #[dynosaur::dynosaur(DynSendNext = dyn SendNext)] 4 | trait Next { 5 | type Item; 6 | async fn next(&mut self) -> Option; 7 | } 8 | 9 | async fn dyn_dispatch(iter: &mut DynSendNext<'_, i32>) { 10 | print!("dyn_dispatch: "); 11 | while let Some(item) = iter.next().await { 12 | print!("{item} "); 13 | } 14 | println!(); 15 | } 16 | 17 | async fn dyn_dispatch_local(iter: &mut DynNext<'_, i32>) { 18 | print!("dyn_dispatch: "); 19 | while let Some(item) = iter.next().await { 20 | print!("{item} "); 21 | } 22 | println!(); 23 | } 24 | 25 | async fn static_dispatch(mut iter: impl SendNext) { 26 | print!("static_dispatch: "); 27 | while let Some(item) = iter.next().await { 28 | print!("{item} "); 29 | } 30 | println!(); 31 | } 32 | 33 | async fn static_dispatch_local(mut iter: impl Next) { 34 | print!("static_dispatch: "); 35 | while let Some(item) = iter.next().await { 36 | print!("{item} "); 37 | } 38 | println!(); 39 | } 40 | 41 | #[tokio::main(flavor = "current_thread")] 42 | async fn main() { 43 | let v = [1, 2, 3]; 44 | dyn_dispatch(&mut DynSendNext::new_box(from_iter(v))).await; 45 | dyn_dispatch(&mut DynSendNext::new_box(from_iter(v))).await; 46 | dyn_dispatch_local(DynNext::from_mut(&mut from_iter(v))).await; 47 | dyn_dispatch_local(DynNext::from_mut(&mut from_iter(v))).await; 48 | static_dispatch(from_iter(v)).await; 49 | static_dispatch_local(from_iter(v)).await; 50 | static_dispatch(DynSendNext::new_box(from_iter(v))).await; 51 | static_dispatch(DynSendNext::from_mut(&mut from_iter(v))).await; 52 | static_dispatch_local(DynNext::new_box(from_iter(v))).await; 53 | static_dispatch_local(DynNext::from_mut(&mut from_iter(v))).await; 54 | } 55 | 56 | impl SendNext for Box { 57 | type Item = S::Item; 58 | fn next(&mut self) -> impl core::future::Future> { 59 | S::next(&mut *self) 60 | } 61 | } 62 | 63 | impl SendNext for &mut S { 64 | type Item = S::Item; 65 | fn next(&mut self) -> impl core::future::Future> { 66 | S::next(&mut *self) 67 | } 68 | } 69 | 70 | impl Next for Box> { 71 | type Item = Item; 72 | fn next(&mut self) -> impl core::future::Future> { 73 | DynNext::next(&mut *self) 74 | } 75 | } 76 | 77 | impl Next for &mut DynNext<'_, Item> { 78 | type Item = Item; 79 | fn next(&mut self) -> impl core::future::Future> { 80 | DynNext::next(&mut *self) 81 | } 82 | } 83 | 84 | struct ForArray { 85 | v: [T; N], 86 | i: usize, 87 | } 88 | 89 | fn from_iter(v: [T; N]) -> ForArray { 90 | ForArray { v, i: 0 } 91 | } 92 | 93 | impl SendNext for ForArray { 94 | type Item = T; 95 | 96 | async fn next(&mut self) -> Option { 97 | if self.i >= self.v.len() { 98 | return None; 99 | } 100 | stuff().await; 101 | let item = self.v[self.i]; 102 | self.i += 1; 103 | Some(item) 104 | } 105 | } 106 | 107 | async fn stuff() {} 108 | -------------------------------------------------------------------------------- /dynosaur/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | 3 | pub use dynosaur_derive::*; 4 | -------------------------------------------------------------------------------- /dynosaur/tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Stub manifest file to specify dependencies. 2 | # This is required because ui tests don't have access to dev dependencies: 3 | # https://github.com/oli-obk/ui_test/issues/282 4 | 5 | [package] 6 | name = "dynosaur_ui_tests" 7 | version = "0.2.0" 8 | edition = "2021" 9 | 10 | [lib] 11 | path = "lib.rs" 12 | 13 | [dependencies] 14 | dynosaur = { version = "0.2", path = "../" } 15 | trait-variant = { workspace = true } 16 | -------------------------------------------------------------------------------- /dynosaur/tests/lib.rs: -------------------------------------------------------------------------------- 1 | // Empty stub for Cargo.toml. 2 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/anynomous-args.rs: -------------------------------------------------------------------------------- 1 | #[dynosaur::dynosaur(DynSomeTrait)] 2 | trait SomeTrait { 3 | async fn multiple_elided_lifetimes(&self, _: &u8, _: &u8); 4 | } 5 | impl SomeTrait for () { 6 | async fn multiple_elided_lifetimes(&self, _: &u8, _: &u8) {} 7 | } 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/anynomous-args.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | trait SomeTrait { 7 | async fn multiple_elided_lifetimes(&self, _: &u8, _: &u8); 8 | } 9 | mod __dynosaur_macro_dynsometrait { 10 | use super::*; 11 | trait ErasedSomeTrait { 12 | fn multiple_elided_lifetimes<'life0, 'life1, 'life2, 13 | 'dynosaur>(&'life0 self, __dynosaur_arg1: &'life1 u8, 14 | __dynosaur_arg2: &'life2 u8) 15 | -> 16 | ::core::pin::Pin + 17 | 'dynosaur>> 18 | where 19 | 'life0: 'dynosaur, 20 | 'life1: 'dynosaur, 21 | 'life2: 'dynosaur, 22 | Self: 'dynosaur; 23 | } 24 | impl ErasedSomeTrait for DYNOSAUR { 25 | fn multiple_elided_lifetimes<'life0, 'life1, 'life2, 26 | 'dynosaur>(&'life0 self, __dynosaur_arg1: &'life1 u8, 27 | __dynosaur_arg2: &'life2 u8) 28 | -> 29 | ::core::pin::Pin + 30 | 'dynosaur>> where 'life0: 'dynosaur, 'life1: 'dynosaur, 31 | 'life2: 'dynosaur, Self: 'dynosaur { 32 | Box::pin(::multiple_elided_lifetimes(self, __dynosaur_arg1, 34 | __dynosaur_arg2)) 35 | } 36 | } 37 | #[repr(transparent)] 38 | pub struct DynSomeTrait<'dynosaur_struct> { 39 | ptr: dyn ErasedSomeTrait + 'dynosaur_struct, 40 | } 41 | impl<'dynosaur_struct> SomeTrait for DynSomeTrait<'dynosaur_struct> { 42 | fn multiple_elided_lifetimes(&self, __dynosaur_arg1: &u8, 43 | __dynosaur_arg2: &u8) 44 | -> impl ::core::future::Future { 45 | let ret: 46 | ::core::pin::Pin + '_>> = 48 | self.ptr.multiple_elided_lifetimes(__dynosaur_arg1, 49 | __dynosaur_arg2); 50 | let ret: 51 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 53 | ret 54 | } 55 | } 56 | impl<'dynosaur_struct> DynSomeTrait<'dynosaur_struct> { 57 | pub fn new_box(value: impl SomeTrait + 'dynosaur_struct) 58 | -> Box> { 59 | let value = Box::new(value); 60 | let value: Box = value; 61 | unsafe { ::core::mem::transmute(value) } 62 | } 63 | pub fn new_arc(value: impl SomeTrait + 'dynosaur_struct) 64 | -> std::sync::Arc> { 65 | let value = std::sync::Arc::new(value); 66 | let value: 67 | std::sync::Arc = 68 | value; 69 | unsafe { ::core::mem::transmute(value) } 70 | } 71 | pub fn new_rc(value: impl SomeTrait + 'dynosaur_struct) 72 | -> std::rc::Rc> { 73 | let value = std::rc::Rc::new(value); 74 | let value: std::rc::Rc = 75 | value; 76 | unsafe { ::core::mem::transmute(value) } 77 | } 78 | pub fn from_ref(value: &(impl SomeTrait + 'dynosaur_struct)) 79 | -> &DynSomeTrait<'dynosaur_struct> { 80 | let value: &(dyn ErasedSomeTrait + 'dynosaur_struct) = &*value; 81 | unsafe { ::core::mem::transmute(value) } 82 | } 83 | pub fn from_mut(value: &mut (impl SomeTrait + 'dynosaur_struct)) 84 | -> &mut DynSomeTrait<'dynosaur_struct> { 85 | let value: &mut (dyn ErasedSomeTrait + 'dynosaur_struct) = 86 | &mut *value; 87 | unsafe { ::core::mem::transmute(value) } 88 | } 89 | } 90 | } 91 | use __dynosaur_macro_dynsometrait::DynSomeTrait; 92 | impl SomeTrait for () { 93 | async fn multiple_elided_lifetimes(&self, _: &u8, _: &u8) {} 94 | } 95 | 96 | fn main() {} 97 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/associated-types.rs: -------------------------------------------------------------------------------- 1 | trait Baz {} 2 | 3 | #[dynosaur::dynosaur(DynFoo)] 4 | trait Foo { 5 | type Bar: Baz; 6 | 7 | async fn foo(&self) -> Self::Bar; 8 | } 9 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/associated-types.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | trait Baz {} 7 | 8 | trait Foo { 9 | type Bar: Baz; 10 | 11 | async fn foo(&self) 12 | -> Self::Bar; 13 | } 14 | mod __dynosaur_macro_dynfoo { 15 | use super::*; 16 | trait ErasedFoo { 17 | type Bar: Baz; 18 | fn foo<'life0, 'dynosaur>(&'life0 self) 19 | -> 20 | ::core::pin::Pin + 'dynosaur>> 22 | where 23 | 'life0: 'dynosaur, 24 | Self: 'dynosaur; 25 | } 26 | impl ErasedFoo for DYNOSAUR { 27 | type Bar = ::Bar; 28 | fn foo<'life0, 'dynosaur>(&'life0 self) 29 | -> 30 | ::core::pin::Pin + 'dynosaur>> where 'life0: 'dynosaur, 32 | Self: 'dynosaur { 33 | Box::pin(::foo(self)) 34 | } 35 | } 36 | #[repr(transparent)] 37 | pub struct DynFoo<'dynosaur_struct, Bar: Baz> { 38 | ptr: dyn ErasedFoo + 'dynosaur_struct, 39 | } 40 | impl<'dynosaur_struct, Bar: Baz> Foo for DynFoo<'dynosaur_struct, Bar> { 41 | type Bar = Bar; 42 | fn foo(&self) -> impl ::core::future::Future { 43 | let ret: 44 | ::core::pin::Pin + '_>> = self.ptr.foo(); 46 | let ret: 47 | ::core::pin::Pin + 'static>> = 49 | unsafe { ::core::mem::transmute(ret) }; 50 | ret 51 | } 52 | } 53 | impl<'dynosaur_struct, Bar: Baz> DynFoo<'dynosaur_struct, Bar> { 54 | pub fn new_box(value: impl Foo + 'dynosaur_struct) 55 | -> Box> { 56 | let value = Box::new(value); 57 | let value: Box + 'dynosaur_struct> = 58 | value; 59 | unsafe { ::core::mem::transmute(value) } 60 | } 61 | pub fn new_arc(value: impl Foo + 'dynosaur_struct) 62 | -> std::sync::Arc> { 63 | let value = std::sync::Arc::new(value); 64 | let value: 65 | std::sync::Arc + 66 | 'dynosaur_struct> = value; 67 | unsafe { ::core::mem::transmute(value) } 68 | } 69 | pub fn new_rc(value: impl Foo + 'dynosaur_struct) 70 | -> std::rc::Rc> { 71 | let value = std::rc::Rc::new(value); 72 | let value: 73 | std::rc::Rc + 'dynosaur_struct> = 74 | value; 75 | unsafe { ::core::mem::transmute(value) } 76 | } 77 | pub fn from_ref(value: &(impl Foo + 'dynosaur_struct)) 78 | -> &DynFoo<'dynosaur_struct, Bar> { 79 | let value: &(dyn ErasedFoo + 'dynosaur_struct) = 80 | &*value; 81 | unsafe { ::core::mem::transmute(value) } 82 | } 83 | pub fn from_mut(value: &mut (impl Foo + 'dynosaur_struct)) 84 | -> &mut DynFoo<'dynosaur_struct, Bar> { 85 | let value: &mut (dyn ErasedFoo + 'dynosaur_struct) = 86 | &mut *value; 87 | unsafe { ::core::mem::transmute(value) } 88 | } 89 | } 90 | } 91 | use __dynosaur_macro_dynfoo::DynFoo; 92 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/async-and-non-async.rs: -------------------------------------------------------------------------------- 1 | use dynosaur::dynosaur; 2 | 3 | #[dynosaur(DynJobQueue)] 4 | pub trait JobQueue { 5 | fn len(&self) -> usize; 6 | async fn dispatch(&self); 7 | } 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/async-and-non-async.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use dynosaur::dynosaur; 7 | 8 | pub trait JobQueue { 9 | fn len(&self) 10 | -> usize; 11 | async fn dispatch(&self); 12 | } 13 | mod __dynosaur_macro_dynjobqueue { 14 | use super::*; 15 | pub trait ErasedJobQueue { 16 | fn len(&self) 17 | -> usize; 18 | fn dispatch<'life0, 'dynosaur>(&'life0 self) 19 | -> 20 | ::core::pin::Pin + 21 | 'dynosaur>> 22 | where 23 | 'life0: 'dynosaur, 24 | Self: 'dynosaur; 25 | } 26 | impl ErasedJobQueue for DYNOSAUR { 27 | fn len(&self) -> usize { ::len(self) } 28 | fn dispatch<'life0, 'dynosaur>(&'life0 self) 29 | -> 30 | ::core::pin::Pin + 31 | 'dynosaur>> where 'life0: 'dynosaur, Self: 'dynosaur { 32 | Box::pin(::dispatch(self)) 33 | } 34 | } 35 | #[repr(transparent)] 36 | pub struct DynJobQueue<'dynosaur_struct> { 37 | ptr: dyn ErasedJobQueue + 'dynosaur_struct, 38 | } 39 | impl<'dynosaur_struct> JobQueue for DynJobQueue<'dynosaur_struct> { 40 | fn len(&self) -> usize { self.ptr.len() } 41 | fn dispatch(&self) -> impl ::core::future::Future { 42 | let ret: 43 | ::core::pin::Pin + '_>> = self.ptr.dispatch(); 45 | let ret: 46 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 48 | ret 49 | } 50 | } 51 | impl<'dynosaur_struct> DynJobQueue<'dynosaur_struct> { 52 | pub fn new_box(value: impl JobQueue + 'dynosaur_struct) 53 | -> Box> { 54 | let value = Box::new(value); 55 | let value: Box = value; 56 | unsafe { ::core::mem::transmute(value) } 57 | } 58 | pub fn new_arc(value: impl JobQueue + 'dynosaur_struct) 59 | -> std::sync::Arc> { 60 | let value = std::sync::Arc::new(value); 61 | let value: std::sync::Arc = 62 | value; 63 | unsafe { ::core::mem::transmute(value) } 64 | } 65 | pub fn new_rc(value: impl JobQueue + 'dynosaur_struct) 66 | -> std::rc::Rc> { 67 | let value = std::rc::Rc::new(value); 68 | let value: std::rc::Rc = 69 | value; 70 | unsafe { ::core::mem::transmute(value) } 71 | } 72 | pub fn from_ref(value: &(impl JobQueue + 'dynosaur_struct)) 73 | -> &DynJobQueue<'dynosaur_struct> { 74 | let value: &(dyn ErasedJobQueue + 'dynosaur_struct) = &*value; 75 | unsafe { ::core::mem::transmute(value) } 76 | } 77 | pub fn from_mut(value: &mut (impl JobQueue + 'dynosaur_struct)) 78 | -> &mut DynJobQueue<'dynosaur_struct> { 79 | let value: &mut (dyn ErasedJobQueue + 'dynosaur_struct) = 80 | &mut *value; 81 | unsafe { ::core::mem::transmute(value) } 82 | } 83 | } 84 | } 85 | use __dynosaur_macro_dynjobqueue::DynJobQueue; 86 | 87 | fn main() {} 88 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic-apit.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use dynosaur::dynosaur; 3 | 4 | trait Foo {} 5 | 6 | impl Foo for Box {} 7 | 8 | #[dynosaur(DynMyTrait)] 9 | trait MyTrait { 10 | fn foo(&self, _: impl Foo) -> i32; 11 | async fn bar(&self, _: impl Foo) -> i32; 12 | fn baz(&self, _: impl Future) -> i32; 13 | } 14 | 15 | fn main() {} 16 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic-apit.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use core::future::Future; 7 | use dynosaur::dynosaur; 8 | 9 | trait Foo {} 10 | 11 | impl Foo for Box {} 12 | 13 | trait MyTrait { 14 | fn foo(&self, _: impl Foo) 15 | -> i32; 16 | async fn bar(&self, _: impl Foo) 17 | -> i32; 18 | fn baz(&self, _: impl Future) 19 | -> i32; 20 | } 21 | mod __dynosaur_macro_dynmytrait { 22 | use super::*; 23 | trait ErasedMyTrait { 24 | fn foo(&self, __dynosaur_arg1: Box) 25 | -> i32; 26 | fn bar<'life0, 27 | 'dynosaur>(&'life0 self, __dynosaur_arg1: Box) 28 | -> 29 | ::core::pin::Pin + 30 | 'dynosaur>> 31 | where 32 | 'life0: 'dynosaur, 33 | Self: 'dynosaur; 34 | fn baz(&self, 35 | __dynosaur_arg1: ::core::pin::Pin + '_>>) 36 | -> i32; 37 | } 38 | impl ErasedMyTrait for DYNOSAUR { 39 | fn foo(&self, __dynosaur_arg1: Box) -> i32 { 40 | ::foo(self, __dynosaur_arg1) 41 | } 42 | fn bar<'life0, 43 | 'dynosaur>(&'life0 self, 44 | __dynosaur_arg1: Box) 45 | -> 46 | ::core::pin::Pin + 'dynosaur>> where 'life0: 'dynosaur, Self: 'dynosaur { 48 | Box::pin(::bar(self, __dynosaur_arg1)) 49 | } 50 | fn baz(&self, 51 | __dynosaur_arg1: 52 | ::core::pin::Pin + '_>>) -> i32 { 53 | ::baz(self, __dynosaur_arg1) 54 | } 55 | } 56 | #[repr(transparent)] 57 | pub struct DynMyTrait<'dynosaur_struct> { 58 | ptr: dyn ErasedMyTrait + 'dynosaur_struct, 59 | } 60 | impl<'dynosaur_struct> MyTrait for DynMyTrait<'dynosaur_struct> { 61 | fn foo(&self, __dynosaur_arg1: impl Foo) -> i32 { 62 | self.ptr.foo(Box::new(__dynosaur_arg1)) 63 | } 64 | fn bar(&self, __dynosaur_arg1: impl Foo) 65 | -> impl ::core::future::Future { 66 | let ret: 67 | ::core::pin::Pin + '_>> = self.ptr.bar(Box::new(__dynosaur_arg1)); 69 | let ret: 70 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 72 | ret 73 | } 74 | fn baz(&self, __dynosaur_arg1: impl Future) -> i32 { 75 | self.ptr.baz(Box::pin(__dynosaur_arg1)) 76 | } 77 | } 78 | impl<'dynosaur_struct> DynMyTrait<'dynosaur_struct> { 79 | pub fn new_box(value: impl MyTrait + 'dynosaur_struct) 80 | -> Box> { 81 | let value = Box::new(value); 82 | let value: Box = value; 83 | unsafe { ::core::mem::transmute(value) } 84 | } 85 | pub fn new_arc(value: impl MyTrait + 'dynosaur_struct) 86 | -> std::sync::Arc> { 87 | let value = std::sync::Arc::new(value); 88 | let value: std::sync::Arc = 89 | value; 90 | unsafe { ::core::mem::transmute(value) } 91 | } 92 | pub fn new_rc(value: impl MyTrait + 'dynosaur_struct) 93 | -> std::rc::Rc> { 94 | let value = std::rc::Rc::new(value); 95 | let value: std::rc::Rc = 96 | value; 97 | unsafe { ::core::mem::transmute(value) } 98 | } 99 | pub fn from_ref(value: &(impl MyTrait + 'dynosaur_struct)) 100 | -> &DynMyTrait<'dynosaur_struct> { 101 | let value: &(dyn ErasedMyTrait + 'dynosaur_struct) = &*value; 102 | unsafe { ::core::mem::transmute(value) } 103 | } 104 | pub fn from_mut(value: &mut (impl MyTrait + 'dynosaur_struct)) 105 | -> &mut DynMyTrait<'dynosaur_struct> { 106 | let value: &mut (dyn ErasedMyTrait + 'dynosaur_struct) = 107 | &mut *value; 108 | unsafe { ::core::mem::transmute(value) } 109 | } 110 | } 111 | } 112 | use __dynosaur_macro_dynmytrait::DynMyTrait; 113 | 114 | fn main() {} 115 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic-mut.rs: -------------------------------------------------------------------------------- 1 | use dynosaur::dynosaur; 2 | 3 | #[dynosaur(DynMyTrait)] 4 | trait MyTrait { 5 | async fn foo(&mut self); 6 | } 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic-mut.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use dynosaur::dynosaur; 7 | 8 | trait MyTrait { 9 | async fn foo(&mut self); 10 | } 11 | mod __dynosaur_macro_dynmytrait { 12 | use super::*; 13 | trait ErasedMyTrait { 14 | fn foo<'life0, 'dynosaur>(&'life0 mut self) 15 | -> 16 | ::core::pin::Pin + 17 | 'dynosaur>> 18 | where 19 | 'life0: 'dynosaur, 20 | Self: 'dynosaur; 21 | } 22 | impl ErasedMyTrait for DYNOSAUR { 23 | fn foo<'life0, 'dynosaur>(&'life0 mut self) 24 | -> 25 | ::core::pin::Pin + 26 | 'dynosaur>> where 'life0: 'dynosaur, Self: 'dynosaur { 27 | Box::pin(::foo(self)) 28 | } 29 | } 30 | #[repr(transparent)] 31 | pub struct DynMyTrait<'dynosaur_struct> { 32 | ptr: dyn ErasedMyTrait + 'dynosaur_struct, 33 | } 34 | impl<'dynosaur_struct> MyTrait for DynMyTrait<'dynosaur_struct> { 35 | fn foo(&mut self) -> impl ::core::future::Future { 36 | let ret: 37 | ::core::pin::Pin + '_>> = self.ptr.foo(); 39 | let ret: 40 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 42 | ret 43 | } 44 | } 45 | impl<'dynosaur_struct> DynMyTrait<'dynosaur_struct> { 46 | pub fn new_box(value: impl MyTrait + 'dynosaur_struct) 47 | -> Box> { 48 | let value = Box::new(value); 49 | let value: Box = value; 50 | unsafe { ::core::mem::transmute(value) } 51 | } 52 | pub fn new_arc(value: impl MyTrait + 'dynosaur_struct) 53 | -> std::sync::Arc> { 54 | let value = std::sync::Arc::new(value); 55 | let value: std::sync::Arc = 56 | value; 57 | unsafe { ::core::mem::transmute(value) } 58 | } 59 | pub fn new_rc(value: impl MyTrait + 'dynosaur_struct) 60 | -> std::rc::Rc> { 61 | let value = std::rc::Rc::new(value); 62 | let value: std::rc::Rc = 63 | value; 64 | unsafe { ::core::mem::transmute(value) } 65 | } 66 | pub fn from_ref(value: &(impl MyTrait + 'dynosaur_struct)) 67 | -> &DynMyTrait<'dynosaur_struct> { 68 | let value: &(dyn ErasedMyTrait + 'dynosaur_struct) = &*value; 69 | unsafe { ::core::mem::transmute(value) } 70 | } 71 | pub fn from_mut(value: &mut (impl MyTrait + 'dynosaur_struct)) 72 | -> &mut DynMyTrait<'dynosaur_struct> { 73 | let value: &mut (dyn ErasedMyTrait + 'dynosaur_struct) = 74 | &mut *value; 75 | unsafe { ::core::mem::transmute(value) } 76 | } 77 | } 78 | } 79 | use __dynosaur_macro_dynmytrait::DynMyTrait; 80 | 81 | fn main() {} 82 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic-no-ret.rs: -------------------------------------------------------------------------------- 1 | use dynosaur::dynosaur; 2 | 3 | #[dynosaur(DynMyTrait)] 4 | trait MyTrait { 5 | async fn foo(&self); 6 | } 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic-no-ret.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use dynosaur::dynosaur; 7 | 8 | trait MyTrait { 9 | async fn foo(&self); 10 | } 11 | mod __dynosaur_macro_dynmytrait { 12 | use super::*; 13 | trait ErasedMyTrait { 14 | fn foo<'life0, 'dynosaur>(&'life0 self) 15 | -> 16 | ::core::pin::Pin + 17 | 'dynosaur>> 18 | where 19 | 'life0: 'dynosaur, 20 | Self: 'dynosaur; 21 | } 22 | impl ErasedMyTrait for DYNOSAUR { 23 | fn foo<'life0, 'dynosaur>(&'life0 self) 24 | -> 25 | ::core::pin::Pin + 26 | 'dynosaur>> where 'life0: 'dynosaur, Self: 'dynosaur { 27 | Box::pin(::foo(self)) 28 | } 29 | } 30 | #[repr(transparent)] 31 | pub struct DynMyTrait<'dynosaur_struct> { 32 | ptr: dyn ErasedMyTrait + 'dynosaur_struct, 33 | } 34 | impl<'dynosaur_struct> MyTrait for DynMyTrait<'dynosaur_struct> { 35 | fn foo(&self) -> impl ::core::future::Future { 36 | let ret: 37 | ::core::pin::Pin + '_>> = self.ptr.foo(); 39 | let ret: 40 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 42 | ret 43 | } 44 | } 45 | impl<'dynosaur_struct> DynMyTrait<'dynosaur_struct> { 46 | pub fn new_box(value: impl MyTrait + 'dynosaur_struct) 47 | -> Box> { 48 | let value = Box::new(value); 49 | let value: Box = value; 50 | unsafe { ::core::mem::transmute(value) } 51 | } 52 | pub fn new_arc(value: impl MyTrait + 'dynosaur_struct) 53 | -> std::sync::Arc> { 54 | let value = std::sync::Arc::new(value); 55 | let value: std::sync::Arc = 56 | value; 57 | unsafe { ::core::mem::transmute(value) } 58 | } 59 | pub fn new_rc(value: impl MyTrait + 'dynosaur_struct) 60 | -> std::rc::Rc> { 61 | let value = std::rc::Rc::new(value); 62 | let value: std::rc::Rc = 63 | value; 64 | unsafe { ::core::mem::transmute(value) } 65 | } 66 | pub fn from_ref(value: &(impl MyTrait + 'dynosaur_struct)) 67 | -> &DynMyTrait<'dynosaur_struct> { 68 | let value: &(dyn ErasedMyTrait + 'dynosaur_struct) = &*value; 69 | unsafe { ::core::mem::transmute(value) } 70 | } 71 | pub fn from_mut(value: &mut (impl MyTrait + 'dynosaur_struct)) 72 | -> &mut DynMyTrait<'dynosaur_struct> { 73 | let value: &mut (dyn ErasedMyTrait + 'dynosaur_struct) = 74 | &mut *value; 75 | unsafe { ::core::mem::transmute(value) } 76 | } 77 | } 78 | } 79 | use __dynosaur_macro_dynmytrait::DynMyTrait; 80 | 81 | fn main() {} 82 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic-rpitit.rs: -------------------------------------------------------------------------------- 1 | use dynosaur::dynosaur; 2 | 3 | #[dynosaur(DynMyTrait)] 4 | trait MyTrait { 5 | fn foo(&self) -> impl Send; 6 | } 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic-rpitit.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use dynosaur::dynosaur; 7 | 8 | trait MyTrait { 9 | fn foo(&self) 10 | -> impl Send; 11 | } 12 | mod __dynosaur_macro_dynmytrait { 13 | use super::*; 14 | trait ErasedMyTrait { 15 | fn foo<'life0, 'dynosaur>(&'life0 self) 16 | -> Box 17 | where 18 | 'life0: 'dynosaur, 19 | Self: 'dynosaur; 20 | } 21 | impl ErasedMyTrait for DYNOSAUR { 22 | fn foo<'life0, 'dynosaur>(&'life0 self) -> Box 23 | where 'life0: 'dynosaur, Self: 'dynosaur { 24 | Box::new(::foo(self)) 25 | } 26 | } 27 | #[repr(transparent)] 28 | pub struct DynMyTrait<'dynosaur_struct> { 29 | ptr: dyn ErasedMyTrait + 'dynosaur_struct, 30 | } 31 | impl<'dynosaur_struct> MyTrait for DynMyTrait<'dynosaur_struct> { 32 | fn foo(&self) -> impl Send { 33 | let ret: Box = self.ptr.foo(); 34 | let ret: Box = 35 | unsafe { ::core::mem::transmute(ret) }; 36 | ret 37 | } 38 | } 39 | impl<'dynosaur_struct> DynMyTrait<'dynosaur_struct> { 40 | pub fn new_box(value: impl MyTrait + 'dynosaur_struct) 41 | -> Box> { 42 | let value = Box::new(value); 43 | let value: Box = value; 44 | unsafe { ::core::mem::transmute(value) } 45 | } 46 | pub fn new_arc(value: impl MyTrait + 'dynosaur_struct) 47 | -> std::sync::Arc> { 48 | let value = std::sync::Arc::new(value); 49 | let value: std::sync::Arc = 50 | value; 51 | unsafe { ::core::mem::transmute(value) } 52 | } 53 | pub fn new_rc(value: impl MyTrait + 'dynosaur_struct) 54 | -> std::rc::Rc> { 55 | let value = std::rc::Rc::new(value); 56 | let value: std::rc::Rc = 57 | value; 58 | unsafe { ::core::mem::transmute(value) } 59 | } 60 | pub fn from_ref(value: &(impl MyTrait + 'dynosaur_struct)) 61 | -> &DynMyTrait<'dynosaur_struct> { 62 | let value: &(dyn ErasedMyTrait + 'dynosaur_struct) = &*value; 63 | unsafe { ::core::mem::transmute(value) } 64 | } 65 | pub fn from_mut(value: &mut (impl MyTrait + 'dynosaur_struct)) 66 | -> &mut DynMyTrait<'dynosaur_struct> { 67 | let value: &mut (dyn ErasedMyTrait + 'dynosaur_struct) = 68 | &mut *value; 69 | unsafe { ::core::mem::transmute(value) } 70 | } 71 | } 72 | } 73 | use __dynosaur_macro_dynmytrait::DynMyTrait; 74 | 75 | fn main() {} 76 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic-with-self.rs: -------------------------------------------------------------------------------- 1 | use dynosaur::dynosaur; 2 | 3 | #[dynosaur(DynMyTrait)] 4 | trait MyTrait { 5 | type Item; 6 | async fn foo(&self) -> Self::Item; 7 | } 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic-with-self.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use dynosaur::dynosaur; 7 | 8 | trait MyTrait { 9 | type Item; 10 | async fn foo(&self) 11 | -> Self::Item; 12 | } 13 | mod __dynosaur_macro_dynmytrait { 14 | use super::*; 15 | trait ErasedMyTrait { 16 | type Item; 17 | fn foo<'life0, 'dynosaur>(&'life0 self) 18 | -> 19 | ::core::pin::Pin + 'dynosaur>> 21 | where 22 | 'life0: 'dynosaur, 23 | Self: 'dynosaur; 24 | } 25 | impl ErasedMyTrait for DYNOSAUR { 26 | type Item = ::Item; 27 | fn foo<'life0, 'dynosaur>(&'life0 self) 28 | -> 29 | ::core::pin::Pin + 'dynosaur>> where 'life0: 'dynosaur, 31 | Self: 'dynosaur { 32 | Box::pin(::foo(self)) 33 | } 34 | } 35 | #[repr(transparent)] 36 | pub struct DynMyTrait<'dynosaur_struct, Item> { 37 | ptr: dyn ErasedMyTrait + 'dynosaur_struct, 38 | } 39 | impl<'dynosaur_struct, Item> MyTrait for 40 | DynMyTrait<'dynosaur_struct, Item> { 41 | type Item = Item; 42 | fn foo(&self) -> impl ::core::future::Future { 43 | let ret: 44 | ::core::pin::Pin + '_>> = self.ptr.foo(); 46 | let ret: 47 | ::core::pin::Pin + 'static>> = 49 | unsafe { ::core::mem::transmute(ret) }; 50 | ret 51 | } 52 | } 53 | impl<'dynosaur_struct, Item> DynMyTrait<'dynosaur_struct, Item> { 54 | pub fn new_box(value: impl MyTrait + 'dynosaur_struct) 55 | -> Box> { 56 | let value = Box::new(value); 57 | let value: 58 | Box + 'dynosaur_struct> = 59 | value; 60 | unsafe { ::core::mem::transmute(value) } 61 | } 62 | pub fn new_arc(value: impl MyTrait + 'dynosaur_struct) 63 | -> std::sync::Arc> { 64 | let value = std::sync::Arc::new(value); 65 | let value: 66 | std::sync::Arc + 67 | 'dynosaur_struct> = value; 68 | unsafe { ::core::mem::transmute(value) } 69 | } 70 | pub fn new_rc(value: impl MyTrait + 'dynosaur_struct) 71 | -> std::rc::Rc> { 72 | let value = std::rc::Rc::new(value); 73 | let value: 74 | std::rc::Rc + 75 | 'dynosaur_struct> = value; 76 | unsafe { ::core::mem::transmute(value) } 77 | } 78 | pub fn from_ref(value: 79 | &(impl MyTrait + 'dynosaur_struct)) 80 | -> &DynMyTrait<'dynosaur_struct, Item> { 81 | let value: &(dyn ErasedMyTrait + 'dynosaur_struct) = 82 | &*value; 83 | unsafe { ::core::mem::transmute(value) } 84 | } 85 | pub fn from_mut(value: 86 | &mut (impl MyTrait + 'dynosaur_struct)) 87 | -> &mut DynMyTrait<'dynosaur_struct, Item> { 88 | let value: 89 | &mut (dyn ErasedMyTrait + 'dynosaur_struct) = 90 | &mut *value; 91 | unsafe { ::core::mem::transmute(value) } 92 | } 93 | } 94 | } 95 | use __dynosaur_macro_dynmytrait::DynMyTrait; 96 | 97 | fn main() {} 98 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic.rs: -------------------------------------------------------------------------------- 1 | use dynosaur::dynosaur; 2 | 3 | #[dynosaur(DynMyTrait)] 4 | trait MyTrait { 5 | async fn foo(&self) -> i32; 6 | } 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/basic.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use dynosaur::dynosaur; 7 | 8 | trait MyTrait { 9 | async fn foo(&self) 10 | -> i32; 11 | } 12 | mod __dynosaur_macro_dynmytrait { 13 | use super::*; 14 | trait ErasedMyTrait { 15 | fn foo<'life0, 'dynosaur>(&'life0 self) 16 | -> 17 | ::core::pin::Pin + 18 | 'dynosaur>> 19 | where 20 | 'life0: 'dynosaur, 21 | Self: 'dynosaur; 22 | } 23 | impl ErasedMyTrait for DYNOSAUR { 24 | fn foo<'life0, 'dynosaur>(&'life0 self) 25 | -> 26 | ::core::pin::Pin + 'dynosaur>> where 'life0: 'dynosaur, Self: 'dynosaur { 28 | Box::pin(::foo(self)) 29 | } 30 | } 31 | #[repr(transparent)] 32 | pub struct DynMyTrait<'dynosaur_struct> { 33 | ptr: dyn ErasedMyTrait + 'dynosaur_struct, 34 | } 35 | impl<'dynosaur_struct> MyTrait for DynMyTrait<'dynosaur_struct> { 36 | fn foo(&self) -> impl ::core::future::Future { 37 | let ret: 38 | ::core::pin::Pin + '_>> = self.ptr.foo(); 40 | let ret: 41 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 43 | ret 44 | } 45 | } 46 | impl<'dynosaur_struct> DynMyTrait<'dynosaur_struct> { 47 | pub fn new_box(value: impl MyTrait + 'dynosaur_struct) 48 | -> Box> { 49 | let value = Box::new(value); 50 | let value: Box = value; 51 | unsafe { ::core::mem::transmute(value) } 52 | } 53 | pub fn new_arc(value: impl MyTrait + 'dynosaur_struct) 54 | -> std::sync::Arc> { 55 | let value = std::sync::Arc::new(value); 56 | let value: std::sync::Arc = 57 | value; 58 | unsafe { ::core::mem::transmute(value) } 59 | } 60 | pub fn new_rc(value: impl MyTrait + 'dynosaur_struct) 61 | -> std::rc::Rc> { 62 | let value = std::rc::Rc::new(value); 63 | let value: std::rc::Rc = 64 | value; 65 | unsafe { ::core::mem::transmute(value) } 66 | } 67 | pub fn from_ref(value: &(impl MyTrait + 'dynosaur_struct)) 68 | -> &DynMyTrait<'dynosaur_struct> { 69 | let value: &(dyn ErasedMyTrait + 'dynosaur_struct) = &*value; 70 | unsafe { ::core::mem::transmute(value) } 71 | } 72 | pub fn from_mut(value: &mut (impl MyTrait + 'dynosaur_struct)) 73 | -> &mut DynMyTrait<'dynosaur_struct> { 74 | let value: &mut (dyn ErasedMyTrait + 'dynosaur_struct) = 75 | &mut *value; 76 | unsafe { ::core::mem::transmute(value) } 77 | } 78 | } 79 | } 80 | use __dynosaur_macro_dynmytrait::DynMyTrait; 81 | 82 | fn main() {} 83 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/default-method-trait.rs: -------------------------------------------------------------------------------- 1 | use dynosaur::dynosaur; 2 | 3 | #[dynosaur(DynMyTrait)] 4 | trait MyTrait { 5 | fn foo(&mut self) -> impl Send { 6 | 10 7 | } 8 | } 9 | 10 | fn main() {} 11 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/default-method-trait.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use dynosaur::dynosaur; 7 | 8 | trait MyTrait { 9 | fn foo(&mut self) -> impl Send { 10 } 10 | } 11 | mod __dynosaur_macro_dynmytrait { 12 | use super::*; 13 | trait ErasedMyTrait { 14 | fn foo<'life0, 'dynosaur>(&'life0 mut self) 15 | -> Box 16 | where 17 | 'life0: 'dynosaur, 18 | Self: 'dynosaur; 19 | } 20 | impl ErasedMyTrait for DYNOSAUR { 21 | fn foo<'life0, 'dynosaur>(&'life0 mut self) 22 | -> Box where 'life0: 'dynosaur, 23 | Self: 'dynosaur { 24 | Box::new(::foo(self)) 25 | } 26 | } 27 | #[repr(transparent)] 28 | pub struct DynMyTrait<'dynosaur_struct> { 29 | ptr: dyn ErasedMyTrait + 'dynosaur_struct, 30 | } 31 | impl<'dynosaur_struct> MyTrait for DynMyTrait<'dynosaur_struct> { 32 | fn foo(&mut self) -> impl Send { 33 | let ret: Box = self.ptr.foo(); 34 | let ret: Box = 35 | unsafe { ::core::mem::transmute(ret) }; 36 | ret 37 | } 38 | } 39 | impl<'dynosaur_struct> DynMyTrait<'dynosaur_struct> { 40 | pub fn new_box(value: impl MyTrait + 'dynosaur_struct) 41 | -> Box> { 42 | let value = Box::new(value); 43 | let value: Box = value; 44 | unsafe { ::core::mem::transmute(value) } 45 | } 46 | pub fn new_arc(value: impl MyTrait + 'dynosaur_struct) 47 | -> std::sync::Arc> { 48 | let value = std::sync::Arc::new(value); 49 | let value: std::sync::Arc = 50 | value; 51 | unsafe { ::core::mem::transmute(value) } 52 | } 53 | pub fn new_rc(value: impl MyTrait + 'dynosaur_struct) 54 | -> std::rc::Rc> { 55 | let value = std::rc::Rc::new(value); 56 | let value: std::rc::Rc = 57 | value; 58 | unsafe { ::core::mem::transmute(value) } 59 | } 60 | pub fn from_ref(value: &(impl MyTrait + 'dynosaur_struct)) 61 | -> &DynMyTrait<'dynosaur_struct> { 62 | let value: &(dyn ErasedMyTrait + 'dynosaur_struct) = &*value; 63 | unsafe { ::core::mem::transmute(value) } 64 | } 65 | pub fn from_mut(value: &mut (impl MyTrait + 'dynosaur_struct)) 66 | -> &mut DynMyTrait<'dynosaur_struct> { 67 | let value: &mut (dyn ErasedMyTrait + 'dynosaur_struct) = 68 | &mut *value; 69 | unsafe { ::core::mem::transmute(value) } 70 | } 71 | } 72 | } 73 | use __dynosaur_macro_dynmytrait::DynMyTrait; 74 | 75 | fn main() {} 76 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/handle-lifetimes.rs: -------------------------------------------------------------------------------- 1 | use dynosaur::dynosaur; 2 | 3 | #[dynosaur(DynMyTrait)] 4 | trait MyTrait { 5 | type Item; 6 | async fn foo(&self, x: &i32) -> i32; 7 | } 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/handle-lifetimes.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use dynosaur::dynosaur; 7 | 8 | trait MyTrait { 9 | type Item; 10 | async fn foo(&self, x: &i32) 11 | -> i32; 12 | } 13 | mod __dynosaur_macro_dynmytrait { 14 | use super::*; 15 | trait ErasedMyTrait { 16 | type Item; 17 | fn foo<'life0, 'life1, 'dynosaur>(&'life0 self, x: &'life1 i32) 18 | -> 19 | ::core::pin::Pin + 20 | 'dynosaur>> 21 | where 22 | 'life0: 'dynosaur, 23 | 'life1: 'dynosaur, 24 | Self: 'dynosaur; 25 | } 26 | impl ErasedMyTrait for DYNOSAUR { 27 | type Item = ::Item; 28 | fn foo<'life0, 'life1, 'dynosaur>(&'life0 self, x: &'life1 i32) 29 | -> 30 | ::core::pin::Pin + 'dynosaur>> where 'life0: 'dynosaur, 'life1: 'dynosaur, 32 | Self: 'dynosaur { 33 | Box::pin(::foo(self, x)) 34 | } 35 | } 36 | #[repr(transparent)] 37 | pub struct DynMyTrait<'dynosaur_struct, Item> { 38 | ptr: dyn ErasedMyTrait + 'dynosaur_struct, 39 | } 40 | impl<'dynosaur_struct, Item> MyTrait for 41 | DynMyTrait<'dynosaur_struct, Item> { 42 | type Item = Item; 43 | fn foo(&self, x: &i32) -> impl ::core::future::Future { 44 | let ret: 45 | ::core::pin::Pin + '_>> = self.ptr.foo(x); 47 | let ret: 48 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 50 | ret 51 | } 52 | } 53 | impl<'dynosaur_struct, Item> DynMyTrait<'dynosaur_struct, Item> { 54 | pub fn new_box(value: impl MyTrait + 'dynosaur_struct) 55 | -> Box> { 56 | let value = Box::new(value); 57 | let value: 58 | Box + 'dynosaur_struct> = 59 | value; 60 | unsafe { ::core::mem::transmute(value) } 61 | } 62 | pub fn new_arc(value: impl MyTrait + 'dynosaur_struct) 63 | -> std::sync::Arc> { 64 | let value = std::sync::Arc::new(value); 65 | let value: 66 | std::sync::Arc + 67 | 'dynosaur_struct> = value; 68 | unsafe { ::core::mem::transmute(value) } 69 | } 70 | pub fn new_rc(value: impl MyTrait + 'dynosaur_struct) 71 | -> std::rc::Rc> { 72 | let value = std::rc::Rc::new(value); 73 | let value: 74 | std::rc::Rc + 75 | 'dynosaur_struct> = value; 76 | unsafe { ::core::mem::transmute(value) } 77 | } 78 | pub fn from_ref(value: 79 | &(impl MyTrait + 'dynosaur_struct)) 80 | -> &DynMyTrait<'dynosaur_struct, Item> { 81 | let value: &(dyn ErasedMyTrait + 'dynosaur_struct) = 82 | &*value; 83 | unsafe { ::core::mem::transmute(value) } 84 | } 85 | pub fn from_mut(value: 86 | &mut (impl MyTrait + 'dynosaur_struct)) 87 | -> &mut DynMyTrait<'dynosaur_struct, Item> { 88 | let value: 89 | &mut (dyn ErasedMyTrait + 'dynosaur_struct) = 90 | &mut *value; 91 | unsafe { ::core::mem::transmute(value) } 92 | } 93 | } 94 | } 95 | use __dynosaur_macro_dynmytrait::DynMyTrait; 96 | 97 | fn main() {} 98 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/impl-future-bounds.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | 3 | #[dynosaur::dynosaur(DynFoo)] 4 | trait Foo: Send { 5 | fn foo(&self) -> impl Future + Send; 6 | } 7 | 8 | struct FooImpl; 9 | 10 | impl Foo for FooImpl { 11 | async fn foo(&self) -> i32 { 12 | 1 13 | } 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/impl-future-bounds.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use std::future::Future; 7 | 8 | trait Foo: Send { 9 | fn foo(&self) 10 | -> impl Future + Send; 11 | } 12 | mod __dynosaur_macro_dynfoo { 13 | use super::*; 14 | trait ErasedFoo: Send { 15 | fn foo<'life0, 'dynosaur>(&'life0 self) 16 | -> ::core::pin::Pin + Send + 'dynosaur>> 17 | where 18 | 'life0: 'dynosaur, 19 | Self: 'dynosaur; 20 | } 21 | impl ErasedFoo for DYNOSAUR { 22 | fn foo<'life0, 'dynosaur>(&'life0 self) 23 | -> 24 | ::core::pin::Pin + Send + 25 | 'dynosaur>> where 'life0: 'dynosaur, Self: 'dynosaur { 26 | Box::pin(::foo(self)) 27 | } 28 | } 29 | #[repr(transparent)] 30 | pub struct DynFoo<'dynosaur_struct> { 31 | ptr: dyn ErasedFoo + 'dynosaur_struct, 32 | } 33 | impl<'dynosaur_struct> Foo for DynFoo<'dynosaur_struct> { 34 | fn foo(&self) -> impl Future + Send { 35 | let ret: 36 | ::core::pin::Pin + Send + 37 | '_>> = self.ptr.foo(); 38 | let ret: 39 | ::core::pin::Pin + Send + 40 | 'static>> = unsafe { ::core::mem::transmute(ret) }; 41 | ret 42 | } 43 | } 44 | impl<'dynosaur_struct> DynFoo<'dynosaur_struct> { 45 | pub fn new_box(value: impl Foo + 'dynosaur_struct) 46 | -> Box> { 47 | let value = Box::new(value); 48 | let value: Box = value; 49 | unsafe { ::core::mem::transmute(value) } 50 | } 51 | pub fn new_arc(value: impl Foo + 'dynosaur_struct) 52 | -> std::sync::Arc> { 53 | let value = std::sync::Arc::new(value); 54 | let value: std::sync::Arc = 55 | value; 56 | unsafe { ::core::mem::transmute(value) } 57 | } 58 | pub fn new_rc(value: impl Foo + 'dynosaur_struct) 59 | -> std::rc::Rc> { 60 | let value = std::rc::Rc::new(value); 61 | let value: std::rc::Rc = value; 62 | unsafe { ::core::mem::transmute(value) } 63 | } 64 | pub fn from_ref(value: &(impl Foo + 'dynosaur_struct)) 65 | -> &DynFoo<'dynosaur_struct> { 66 | let value: &(dyn ErasedFoo + 'dynosaur_struct) = &*value; 67 | unsafe { ::core::mem::transmute(value) } 68 | } 69 | pub fn from_mut(value: &mut (impl Foo + 'dynosaur_struct)) 70 | -> &mut DynFoo<'dynosaur_struct> { 71 | let value: &mut (dyn ErasedFoo + 'dynosaur_struct) = &mut *value; 72 | unsafe { ::core::mem::transmute(value) } 73 | } 74 | } 75 | } 76 | use __dynosaur_macro_dynfoo::DynFoo; 77 | 78 | struct FooImpl; 79 | 80 | impl Foo for FooImpl { 81 | async fn foo(&self) -> i32 { 1 } 82 | } 83 | 84 | fn main() {} 85 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/multiple-lifetimes-and-where-clauses.rs: -------------------------------------------------------------------------------- 1 | #[dynosaur::dynosaur(DynSomeTrait)] 2 | trait SomeTrait<'a, 'b> { 3 | async fn lotsa_lifetimes<'d, 'e, 'f>(&self, a: &'d u32, b: &'e u32, c: &'f u32) -> &'a u32 4 | where 5 | 'b: 'a; 6 | } 7 | 8 | struct MyData<'a, 'b, 'c>(&'a u32, &'b u32, &'c u32) 9 | where 10 | 'b: 'a; 11 | 12 | impl<'a, 'b, 'c> SomeTrait<'a, 'b> for MyData<'a, 'b, 'c> { 13 | async fn lotsa_lifetimes<'d, 'e, 'f>(&self, a: &'d u32, b: &'e u32, c: &'f u32) -> &'a u32 14 | where 15 | 'b: 'a, 16 | { 17 | self.0 18 | } 19 | } 20 | 21 | fn main() {} 22 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/multiple-lifetimes-and-where-clauses.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | trait SomeTrait<'a, 'b> { 7 | async fn lotsa_lifetimes<'d, 'e, 8 | 'f>(&self, a: &'d u32, b: &'e u32, c: &'f u32) 9 | -> &'a u32 10 | where 11 | 'b: 'a; 12 | } 13 | mod __dynosaur_macro_dynsometrait { 14 | use super::*; 15 | trait ErasedSomeTrait<'a, 'b> { 16 | fn lotsa_lifetimes<'d, 'e, 'f, 'life0, 17 | 'dynosaur>(&'life0 self, a: &'d u32, b: &'e u32, c: &'f u32) 18 | -> 19 | ::core::pin::Pin + 'dynosaur>> 21 | where 22 | 'b: 'a, 23 | 'd: 'dynosaur, 24 | 'e: 'dynosaur, 25 | 'f: 'dynosaur, 26 | 'a: 'dynosaur, 27 | 'b: 'dynosaur, 28 | 'life0: 'dynosaur, 29 | Self: 'dynosaur; 30 | } 31 | impl<'a, 'b, DYNOSAUR: SomeTrait<'a, 'b>> ErasedSomeTrait<'a, 'b> for 32 | DYNOSAUR { 33 | fn lotsa_lifetimes<'d, 'e, 'f, 'life0, 34 | 'dynosaur>(&'life0 self, a: &'d u32, b: &'e u32, c: &'f u32) 35 | -> 36 | ::core::pin::Pin + 'dynosaur>> where 'b: 'a, 'd: 'dynosaur, 38 | 'e: 'dynosaur, 'f: 'dynosaur, 'a: 'dynosaur, 'b: 'dynosaur, 39 | 'life0: 'dynosaur, Self: 'dynosaur { 40 | Box::pin(>::lotsa_lifetimes(self, a, b, c)) 42 | } 43 | } 44 | #[repr(transparent)] 45 | pub struct DynSomeTrait<'dynosaur_struct, 'a, 'b> { 46 | ptr: dyn ErasedSomeTrait<'a, 'b> + 'dynosaur_struct, 47 | } 48 | impl<'dynosaur_struct, 'a, 'b> SomeTrait<'a, 'b> for 49 | DynSomeTrait<'dynosaur_struct, 'a, 'b> { 50 | fn lotsa_lifetimes<'d, 'e, 51 | 'f>(&self, a: &'d u32, b: &'e u32, c: &'f u32) 52 | -> impl ::core::future::Future where 'b: 'a { 53 | let ret: 54 | ::core::pin::Pin + '_>> = self.ptr.lotsa_lifetimes(a, b, c); 56 | let ret: 57 | ::core::pin::Pin + 'static>> = 59 | unsafe { ::core::mem::transmute(ret) }; 60 | ret 61 | } 62 | } 63 | impl<'dynosaur_struct, 'a, 'b> DynSomeTrait<'dynosaur_struct, 'a, 'b> { 64 | pub fn new_box(value: impl SomeTrait<'a, 'b> + 'dynosaur_struct) 65 | -> Box> { 66 | let value = Box::new(value); 67 | let value: Box + 'dynosaur_struct> = 68 | value; 69 | unsafe { ::core::mem::transmute(value) } 70 | } 71 | pub fn new_arc(value: impl SomeTrait<'a, 'b> + 'dynosaur_struct) 72 | -> std::sync::Arc> { 73 | let value = std::sync::Arc::new(value); 74 | let value: 75 | std::sync::Arc + 76 | 'dynosaur_struct> = value; 77 | unsafe { ::core::mem::transmute(value) } 78 | } 79 | pub fn new_rc(value: impl SomeTrait<'a, 'b> + 'dynosaur_struct) 80 | -> std::rc::Rc> { 81 | let value = std::rc::Rc::new(value); 82 | let value: 83 | std::rc::Rc + 84 | 'dynosaur_struct> = value; 85 | unsafe { ::core::mem::transmute(value) } 86 | } 87 | pub fn from_ref(value: &(impl SomeTrait<'a, 'b> + 'dynosaur_struct)) 88 | -> &DynSomeTrait<'dynosaur_struct, 'a, 'b> { 89 | let value: &(dyn ErasedSomeTrait<'a, 'b> + 'dynosaur_struct) = 90 | &*value; 91 | unsafe { ::core::mem::transmute(value) } 92 | } 93 | pub fn from_mut(value: 94 | &mut (impl SomeTrait<'a, 'b> + 'dynosaur_struct)) 95 | -> &mut DynSomeTrait<'dynosaur_struct, 'a, 'b> { 96 | let value: &mut (dyn ErasedSomeTrait<'a, 'b> + 'dynosaur_struct) = 97 | &mut *value; 98 | unsafe { ::core::mem::transmute(value) } 99 | } 100 | } 101 | } 102 | use __dynosaur_macro_dynsometrait::DynSomeTrait; 103 | 104 | struct MyData<'a, 'b, 'c>(&'a u32, &'b u32, &'c u32) where 'b: 'a; 105 | 106 | impl<'a, 'b, 'c> SomeTrait<'a, 'b> for MyData<'a, 'b, 'c> { 107 | async fn lotsa_lifetimes<'d, 'e, 108 | 'f>(&self, a: &'d u32, b: &'e u32, c: &'f u32) -> &'a u32 where 109 | 'b: 'a { 110 | self.0 111 | } 112 | } 113 | 114 | fn main() {} 115 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/multiple-lifetimes.rs: -------------------------------------------------------------------------------- 1 | #[dynosaur::dynosaur(DynSomeTrait)] 2 | trait SomeTrait { 3 | async fn multiple_elided_lifetimes(&self, a: &u8, b: &u8); 4 | async fn multiple_named_lifetimes<'a, 'b>(&self, a: &'a u8, b: &'b u8, c: &u8); 5 | async fn same_lifetimes_multiple_params<'a>(&self, a1: &'a u8, a2: &'a u8, c: &u8) -> &'a u8; 6 | async fn multiple_static_and_anonymous(&self, a: &'static u8, b: &'_ u8, c: &'_ u8); 7 | } 8 | 9 | impl SomeTrait for () { 10 | async fn multiple_elided_lifetimes(&self, a: &u8, b: &u8) {} 11 | async fn multiple_named_lifetimes<'a, 'b>(&self, a: &'a u8, b: &'b u8, c: &u8) {} 12 | async fn same_lifetimes_multiple_params<'a>(&self, a1: &'a u8, a2: &'a u8, c: &u8) -> &'a u8 { 13 | a2 14 | } 15 | async fn multiple_static_and_anonymous(&self, a: &'static u8, b: &'_ u8, c: &'_ u8) {} 16 | } 17 | 18 | fn main() {} 19 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/multiple-lifetimes.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | trait SomeTrait { 7 | async fn multiple_elided_lifetimes(&self, a: &u8, b: &u8); 8 | async fn multiple_named_lifetimes<'a, 9 | 'b>(&self, a: &'a u8, b: &'b u8, c: &u8); 10 | async fn same_lifetimes_multiple_params<'a>(&self, a1: &'a u8, a2: &'a u8, 11 | c: &u8) 12 | -> &'a u8; 13 | async fn multiple_static_and_anonymous(&self, a: &'static u8, b: &'_ u8, 14 | c: &'_ u8); 15 | } 16 | mod __dynosaur_macro_dynsometrait { 17 | use super::*; 18 | trait ErasedSomeTrait { 19 | fn multiple_elided_lifetimes<'life0, 'life1, 'life2, 20 | 'dynosaur>(&'life0 self, a: &'life1 u8, b: &'life2 u8) 21 | -> 22 | ::core::pin::Pin + 23 | 'dynosaur>> 24 | where 25 | 'life0: 'dynosaur, 26 | 'life1: 'dynosaur, 27 | 'life2: 'dynosaur, 28 | Self: 'dynosaur; 29 | fn multiple_named_lifetimes<'a, 'b, 'life0, 'life1, 30 | 'dynosaur>(&'life0 self, a: &'a u8, b: &'b u8, c: &'life1 u8) 31 | -> 32 | ::core::pin::Pin + 33 | 'dynosaur>> 34 | where 35 | 'a: 'dynosaur, 36 | 'b: 'dynosaur, 37 | 'life0: 'dynosaur, 38 | 'life1: 'dynosaur, 39 | Self: 'dynosaur; 40 | fn same_lifetimes_multiple_params<'a, 'life0, 'life1, 41 | 'dynosaur>(&'life0 self, a1: &'a u8, a2: &'a u8, c: &'life1 u8) 42 | -> 43 | ::core::pin::Pin + 44 | 'dynosaur>> 45 | where 46 | 'a: 'dynosaur, 47 | 'life0: 'dynosaur, 48 | 'life1: 'dynosaur, 49 | Self: 'dynosaur; 50 | fn multiple_static_and_anonymous<'life0, 'life1, 'life2, 51 | 'dynosaur>(&'life0 self, a: &'static u8, b: &'life1 u8, c: &'life2 u8) 52 | -> 53 | ::core::pin::Pin + 54 | 'dynosaur>> 55 | where 56 | 'life0: 'dynosaur, 57 | 'life1: 'dynosaur, 58 | 'life2: 'dynosaur, 59 | Self: 'dynosaur; 60 | } 61 | impl ErasedSomeTrait for DYNOSAUR { 62 | fn multiple_elided_lifetimes<'life0, 'life1, 'life2, 63 | 'dynosaur>(&'life0 self, a: &'life1 u8, b: &'life2 u8) 64 | -> 65 | ::core::pin::Pin + 66 | 'dynosaur>> where 'life0: 'dynosaur, 'life1: 'dynosaur, 67 | 'life2: 'dynosaur, Self: 'dynosaur { 68 | Box::pin(::multiple_elided_lifetimes(self, a, b)) 70 | } 71 | fn multiple_named_lifetimes<'a, 'b, 'life0, 'life1, 72 | 'dynosaur>(&'life0 self, a: &'a u8, b: &'b u8, c: &'life1 u8) 73 | -> 74 | ::core::pin::Pin + 75 | 'dynosaur>> where 'a: 'dynosaur, 'b: 'dynosaur, 76 | 'life0: 'dynosaur, 'life1: 'dynosaur, Self: 'dynosaur { 77 | Box::pin(::multiple_named_lifetimes(self, a, b, c)) 79 | } 80 | fn same_lifetimes_multiple_params<'a, 'life0, 'life1, 81 | 'dynosaur>(&'life0 self, a1: &'a u8, a2: &'a u8, c: &'life1 u8) 82 | -> 83 | ::core::pin::Pin + 'dynosaur>> where 'a: 'dynosaur, 'life0: 'dynosaur, 85 | 'life1: 'dynosaur, Self: 'dynosaur { 86 | Box::pin(::same_lifetimes_multiple_params(self, a1, a2, c)) 88 | } 89 | fn multiple_static_and_anonymous<'life0, 'life1, 'life2, 90 | 'dynosaur>(&'life0 self, a: &'static u8, b: &'life1 u8, 91 | c: &'life2 u8) 92 | -> 93 | ::core::pin::Pin + 94 | 'dynosaur>> where 'life0: 'dynosaur, 'life1: 'dynosaur, 95 | 'life2: 'dynosaur, Self: 'dynosaur { 96 | Box::pin(::multiple_static_and_anonymous(self, a, b, c)) 98 | } 99 | } 100 | #[repr(transparent)] 101 | pub struct DynSomeTrait<'dynosaur_struct> { 102 | ptr: dyn ErasedSomeTrait + 'dynosaur_struct, 103 | } 104 | impl<'dynosaur_struct> SomeTrait for DynSomeTrait<'dynosaur_struct> { 105 | fn multiple_elided_lifetimes(&self, a: &u8, b: &u8) 106 | -> impl ::core::future::Future { 107 | let ret: 108 | ::core::pin::Pin + '_>> = self.ptr.multiple_elided_lifetimes(a, b); 110 | let ret: 111 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 113 | ret 114 | } 115 | fn multiple_named_lifetimes<'a, 116 | 'b>(&self, a: &'a u8, b: &'b u8, c: &u8) 117 | -> impl ::core::future::Future { 118 | let ret: 119 | ::core::pin::Pin + '_>> = self.ptr.multiple_named_lifetimes(a, b, c); 121 | let ret: 122 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 124 | ret 125 | } 126 | fn same_lifetimes_multiple_params<'a>(&self, a1: &'a u8, a2: &'a u8, 127 | c: &u8) -> impl ::core::future::Future { 128 | let ret: 129 | ::core::pin::Pin + '_>> = 131 | self.ptr.same_lifetimes_multiple_params(a1, a2, c); 132 | let ret: 133 | ::core::pin::Pin + 'static>> = 135 | unsafe { ::core::mem::transmute(ret) }; 136 | ret 137 | } 138 | fn multiple_static_and_anonymous(&self, a: &'static u8, b: &'_ u8, 139 | c: &'_ u8) -> impl ::core::future::Future { 140 | let ret: 141 | ::core::pin::Pin + '_>> = 143 | self.ptr.multiple_static_and_anonymous(a, b, c); 144 | let ret: 145 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 147 | ret 148 | } 149 | } 150 | impl<'dynosaur_struct> DynSomeTrait<'dynosaur_struct> { 151 | pub fn new_box(value: impl SomeTrait + 'dynosaur_struct) 152 | -> Box> { 153 | let value = Box::new(value); 154 | let value: Box = value; 155 | unsafe { ::core::mem::transmute(value) } 156 | } 157 | pub fn new_arc(value: impl SomeTrait + 'dynosaur_struct) 158 | -> std::sync::Arc> { 159 | let value = std::sync::Arc::new(value); 160 | let value: 161 | std::sync::Arc = 162 | value; 163 | unsafe { ::core::mem::transmute(value) } 164 | } 165 | pub fn new_rc(value: impl SomeTrait + 'dynosaur_struct) 166 | -> std::rc::Rc> { 167 | let value = std::rc::Rc::new(value); 168 | let value: std::rc::Rc = 169 | value; 170 | unsafe { ::core::mem::transmute(value) } 171 | } 172 | pub fn from_ref(value: &(impl SomeTrait + 'dynosaur_struct)) 173 | -> &DynSomeTrait<'dynosaur_struct> { 174 | let value: &(dyn ErasedSomeTrait + 'dynosaur_struct) = &*value; 175 | unsafe { ::core::mem::transmute(value) } 176 | } 177 | pub fn from_mut(value: &mut (impl SomeTrait + 'dynosaur_struct)) 178 | -> &mut DynSomeTrait<'dynosaur_struct> { 179 | let value: &mut (dyn ErasedSomeTrait + 'dynosaur_struct) = 180 | &mut *value; 181 | unsafe { ::core::mem::transmute(value) } 182 | } 183 | } 184 | } 185 | use __dynosaur_macro_dynsometrait::DynSomeTrait; 186 | 187 | impl SomeTrait for () { 188 | async fn multiple_elided_lifetimes(&self, a: &u8, b: &u8) {} 189 | async fn multiple_named_lifetimes<'a, 190 | 'b>(&self, a: &'a u8, b: &'b u8, c: &u8) {} 191 | async fn same_lifetimes_multiple_params<'a>(&self, a1: &'a u8, a2: &'a u8, 192 | c: &u8) -> &'a u8 { 193 | a2 194 | } 195 | async fn multiple_static_and_anonymous(&self, a: &'static u8, b: &'_ u8, 196 | c: &'_ u8) {} 197 | } 198 | 199 | fn main() {} 200 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/non-future-impl-traits.rs: -------------------------------------------------------------------------------- 1 | #[dynosaur::dynosaur(DynSomeTrait)] 2 | trait SomeTrait { 3 | fn get_iter(&mut self) -> impl Iterator + '_; 4 | } 5 | 6 | struct MyImpl([u8; 4]); 7 | 8 | impl SomeTrait for MyImpl { 9 | fn get_iter(&mut self) -> impl Iterator + '_ { 10 | return self.0.into_iter(); 11 | } 12 | } 13 | 14 | fn main() { 15 | let mut st = DynSomeTrait::new_box(MyImpl([3, 2, 4, 1])); 16 | for x in st.get_iter() { 17 | println!("{}", x); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/non-future-impl-traits.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | trait SomeTrait { 7 | fn get_iter(&mut self) 8 | -> impl Iterator + '_; 9 | } 10 | mod __dynosaur_macro_dynsometrait { 11 | use super::*; 12 | trait ErasedSomeTrait { 13 | fn get_iter<'life0, 'dynosaur>(&'life0 mut self) 14 | -> Box + 'dynosaur> 15 | where 16 | 'life0: 'dynosaur, 17 | Self: 'dynosaur; 18 | } 19 | impl ErasedSomeTrait for DYNOSAUR { 20 | fn get_iter<'life0, 'dynosaur>(&'life0 mut self) 21 | -> Box + 'dynosaur> where 22 | 'life0: 'dynosaur, Self: 'dynosaur { 23 | Box::new(::get_iter(self)) 24 | } 25 | } 26 | #[repr(transparent)] 27 | pub struct DynSomeTrait<'dynosaur_struct> { 28 | ptr: dyn ErasedSomeTrait + 'dynosaur_struct, 29 | } 30 | impl<'dynosaur_struct> SomeTrait for DynSomeTrait<'dynosaur_struct> { 31 | fn get_iter(&mut self) -> impl Iterator + '_ { 32 | let ret: Box + '_> = self.ptr.get_iter(); 33 | let ret: Box + '_> = 34 | unsafe { ::core::mem::transmute(ret) }; 35 | ret 36 | } 37 | } 38 | impl<'dynosaur_struct> DynSomeTrait<'dynosaur_struct> { 39 | pub fn new_box(value: impl SomeTrait + 'dynosaur_struct) 40 | -> Box> { 41 | let value = Box::new(value); 42 | let value: Box = value; 43 | unsafe { ::core::mem::transmute(value) } 44 | } 45 | pub fn new_arc(value: impl SomeTrait + 'dynosaur_struct) 46 | -> std::sync::Arc> { 47 | let value = std::sync::Arc::new(value); 48 | let value: 49 | std::sync::Arc = 50 | value; 51 | unsafe { ::core::mem::transmute(value) } 52 | } 53 | pub fn new_rc(value: impl SomeTrait + 'dynosaur_struct) 54 | -> std::rc::Rc> { 55 | let value = std::rc::Rc::new(value); 56 | let value: std::rc::Rc = 57 | value; 58 | unsafe { ::core::mem::transmute(value) } 59 | } 60 | pub fn from_ref(value: &(impl SomeTrait + 'dynosaur_struct)) 61 | -> &DynSomeTrait<'dynosaur_struct> { 62 | let value: &(dyn ErasedSomeTrait + 'dynosaur_struct) = &*value; 63 | unsafe { ::core::mem::transmute(value) } 64 | } 65 | pub fn from_mut(value: &mut (impl SomeTrait + 'dynosaur_struct)) 66 | -> &mut DynSomeTrait<'dynosaur_struct> { 67 | let value: &mut (dyn ErasedSomeTrait + 'dynosaur_struct) = 68 | &mut *value; 69 | unsafe { ::core::mem::transmute(value) } 70 | } 71 | } 72 | } 73 | use __dynosaur_macro_dynsometrait::DynSomeTrait; 74 | 75 | struct MyImpl([u8; 4]); 76 | 77 | impl SomeTrait for MyImpl { 78 | fn get_iter(&mut self) -> impl Iterator + '_ { 79 | return self.0.into_iter(); 80 | } 81 | } 82 | 83 | fn main() { 84 | let mut st = DynSomeTrait::new_box(MyImpl([3, 2, 4, 1])); 85 | for x in st.get_iter() { 86 | { ::std::io::_print(format_args!("{0}\n", x)); }; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/trait-variant.rs: -------------------------------------------------------------------------------- 1 | #[trait_variant::make(SendNext: Send)] 2 | #[dynosaur::dynosaur(DynNext = dyn Next)] 3 | #[dynosaur::dynosaur(DynSendNext = dyn SendNext)] 4 | trait Next { 5 | type Item; 6 | async fn next(&mut self) -> Option; 7 | } 8 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/trait-variant.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | #[allow(async_fn_in_trait)] 7 | trait Next { 8 | type Item; 9 | async fn next(&mut self) 10 | -> Option; 11 | } 12 | mod __dynosaur_macro_dynnext { 13 | use super::*; 14 | #[allow(async_fn_in_trait)] 15 | trait ErasedNext { 16 | type Item; 17 | fn next<'life0, 'dynosaur>(&'life0 mut self) 18 | -> 19 | ::core::pin::Pin> + 'dynosaur>> 21 | where 22 | 'life0: 'dynosaur, 23 | Self: 'dynosaur; 24 | } 25 | impl ErasedNext for DYNOSAUR { 26 | type Item = ::Item; 27 | fn next<'life0, 'dynosaur>(&'life0 mut self) 28 | -> 29 | ::core::pin::Pin> + 'dynosaur>> where 'life0: 'dynosaur, 31 | Self: 'dynosaur { 32 | Box::pin(::next(self)) 33 | } 34 | } 35 | #[repr(transparent)] 36 | pub struct DynNext<'dynosaur_struct, Item> { 37 | ptr: dyn ErasedNext + 'dynosaur_struct, 38 | } 39 | impl<'dynosaur_struct, Item> Next for DynNext<'dynosaur_struct, Item> { 40 | type Item = Item; 41 | fn next(&mut self) 42 | -> impl ::core::future::Future> { 43 | let ret: 44 | ::core::pin::Pin> + '_>> = self.ptr.next(); 46 | let ret: 47 | ::core::pin::Pin> + 'static>> = 49 | unsafe { ::core::mem::transmute(ret) }; 50 | ret 51 | } 52 | } 53 | impl<'dynosaur_struct, Item> DynNext<'dynosaur_struct, Item> { 54 | pub fn new_box(value: impl Next + 'dynosaur_struct) 55 | -> Box> { 56 | let value = Box::new(value); 57 | let value: Box + 'dynosaur_struct> = 58 | value; 59 | unsafe { ::core::mem::transmute(value) } 60 | } 61 | pub fn new_arc(value: impl Next + 'dynosaur_struct) 62 | -> std::sync::Arc> { 63 | let value = std::sync::Arc::new(value); 64 | let value: 65 | std::sync::Arc + 66 | 'dynosaur_struct> = value; 67 | unsafe { ::core::mem::transmute(value) } 68 | } 69 | pub fn new_rc(value: impl Next + 'dynosaur_struct) 70 | -> std::rc::Rc> { 71 | let value = std::rc::Rc::new(value); 72 | let value: 73 | std::rc::Rc + 74 | 'dynosaur_struct> = value; 75 | unsafe { ::core::mem::transmute(value) } 76 | } 77 | pub fn from_ref(value: &(impl Next + 'dynosaur_struct)) 78 | -> &DynNext<'dynosaur_struct, Item> { 79 | let value: &(dyn ErasedNext + 'dynosaur_struct) = 80 | &*value; 81 | unsafe { ::core::mem::transmute(value) } 82 | } 83 | pub fn from_mut(value: 84 | &mut (impl Next + 'dynosaur_struct)) 85 | -> &mut DynNext<'dynosaur_struct, Item> { 86 | let value: &mut (dyn ErasedNext + 'dynosaur_struct) = 87 | &mut *value; 88 | unsafe { ::core::mem::transmute(value) } 89 | } 90 | } 91 | } 92 | use __dynosaur_macro_dynnext::DynNext; 93 | trait SendNext: Send { 94 | type Item; 95 | fn next(&mut self) 96 | -> impl ::core::future::Future> + Send; 97 | } 98 | mod __dynosaur_macro_dynsendnext { 99 | use super::*; 100 | trait ErasedSendNext: Send { 101 | type Item; 102 | fn next<'life0, 'dynosaur>(&'life0 mut self) 103 | -> 104 | ::core::pin::Pin> + Send + 'dynosaur>> 106 | where 107 | 'life0: 'dynosaur, 108 | Self: 'dynosaur; 109 | } 110 | impl ErasedSendNext for DYNOSAUR { 111 | type Item = ::Item; 112 | fn next<'life0, 'dynosaur>(&'life0 mut self) 113 | -> 114 | ::core::pin::Pin> + Send + 'dynosaur>> where 116 | 'life0: 'dynosaur, Self: 'dynosaur { 117 | Box::pin(::next(self)) 118 | } 119 | } 120 | #[repr(transparent)] 121 | pub struct DynSendNext<'dynosaur_struct, Item> { 122 | ptr: dyn ErasedSendNext + 'dynosaur_struct, 123 | } 124 | impl<'dynosaur_struct, Item> SendNext for 125 | DynSendNext<'dynosaur_struct, Item> { 126 | type Item = Item; 127 | fn next(&mut self) 128 | -> 129 | impl ::core::future::Future> + 130 | Send { 131 | let ret: 132 | ::core::pin::Pin> + Send + '_>> = self.ptr.next(); 134 | let ret: 135 | ::core::pin::Pin> + Send + 'static>> = 137 | unsafe { ::core::mem::transmute(ret) }; 138 | ret 139 | } 140 | } 141 | impl<'dynosaur_struct, Item> DynSendNext<'dynosaur_struct, Item> { 142 | pub fn new_box(value: impl SendNext + 'dynosaur_struct) 143 | -> Box> { 144 | let value = Box::new(value); 145 | let value: 146 | Box + 'dynosaur_struct> = 147 | value; 148 | unsafe { ::core::mem::transmute(value) } 149 | } 150 | pub fn new_arc(value: impl SendNext + 'dynosaur_struct) 151 | -> std::sync::Arc> { 152 | let value = std::sync::Arc::new(value); 153 | let value: 154 | std::sync::Arc + 155 | 'dynosaur_struct> = value; 156 | unsafe { ::core::mem::transmute(value) } 157 | } 158 | pub fn new_rc(value: impl SendNext + 'dynosaur_struct) 159 | -> std::rc::Rc> { 160 | let value = std::rc::Rc::new(value); 161 | let value: 162 | std::rc::Rc + 163 | 'dynosaur_struct> = value; 164 | unsafe { ::core::mem::transmute(value) } 165 | } 166 | pub fn from_ref(value: 167 | &(impl SendNext + 'dynosaur_struct)) 168 | -> &DynSendNext<'dynosaur_struct, Item> { 169 | let value: &(dyn ErasedSendNext + 'dynosaur_struct) = 170 | &*value; 171 | unsafe { ::core::mem::transmute(value) } 172 | } 173 | pub fn from_mut(value: 174 | &mut (impl SendNext + 'dynosaur_struct)) 175 | -> &mut DynSendNext<'dynosaur_struct, Item> { 176 | let value: 177 | &mut (dyn ErasedSendNext + 'dynosaur_struct) = 178 | &mut *value; 179 | unsafe { ::core::mem::transmute(value) } 180 | } 181 | } 182 | } 183 | use __dynosaur_macro_dynsendnext::DynSendNext; 184 | impl Next for TraitVariantBlanketType { 185 | type Item = ::Item; 186 | async fn next(&mut self) -> Option { 187 | ::next(self).await 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/visibility.rs: -------------------------------------------------------------------------------- 1 | use dynosaur::dynosaur; 2 | 3 | #[dynosaur(pub(crate) DynMyTrait)] 4 | trait MyTrait { 5 | async fn foo(&self) -> i32; 6 | } 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/visibility.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use dynosaur::dynosaur; 7 | 8 | trait MyTrait { 9 | async fn foo(&self) 10 | -> i32; 11 | } 12 | mod __dynosaur_macro_dynmytrait { 13 | use super::*; 14 | trait ErasedMyTrait { 15 | fn foo<'life0, 'dynosaur>(&'life0 self) 16 | -> 17 | ::core::pin::Pin + 18 | 'dynosaur>> 19 | where 20 | 'life0: 'dynosaur, 21 | Self: 'dynosaur; 22 | } 23 | impl ErasedMyTrait for DYNOSAUR { 24 | fn foo<'life0, 'dynosaur>(&'life0 self) 25 | -> 26 | ::core::pin::Pin + 'dynosaur>> where 'life0: 'dynosaur, Self: 'dynosaur { 28 | Box::pin(::foo(self)) 29 | } 30 | } 31 | #[repr(transparent)] 32 | pub struct DynMyTrait<'dynosaur_struct> { 33 | ptr: dyn ErasedMyTrait + 'dynosaur_struct, 34 | } 35 | impl<'dynosaur_struct> MyTrait for DynMyTrait<'dynosaur_struct> { 36 | fn foo(&self) -> impl ::core::future::Future { 37 | let ret: 38 | ::core::pin::Pin + '_>> = self.ptr.foo(); 40 | let ret: 41 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 43 | ret 44 | } 45 | } 46 | impl<'dynosaur_struct> DynMyTrait<'dynosaur_struct> { 47 | pub fn new_box(value: impl MyTrait + 'dynosaur_struct) 48 | -> Box> { 49 | let value = Box::new(value); 50 | let value: Box = value; 51 | unsafe { ::core::mem::transmute(value) } 52 | } 53 | pub fn new_arc(value: impl MyTrait + 'dynosaur_struct) 54 | -> std::sync::Arc> { 55 | let value = std::sync::Arc::new(value); 56 | let value: std::sync::Arc = 57 | value; 58 | unsafe { ::core::mem::transmute(value) } 59 | } 60 | pub fn new_rc(value: impl MyTrait + 'dynosaur_struct) 61 | -> std::rc::Rc> { 62 | let value = std::rc::Rc::new(value); 63 | let value: std::rc::Rc = 64 | value; 65 | unsafe { ::core::mem::transmute(value) } 66 | } 67 | pub fn from_ref(value: &(impl MyTrait + 'dynosaur_struct)) 68 | -> &DynMyTrait<'dynosaur_struct> { 69 | let value: &(dyn ErasedMyTrait + 'dynosaur_struct) = &*value; 70 | unsafe { ::core::mem::transmute(value) } 71 | } 72 | pub fn from_mut(value: &mut (impl MyTrait + 'dynosaur_struct)) 73 | -> &mut DynMyTrait<'dynosaur_struct> { 74 | let value: &mut (dyn ErasedMyTrait + 'dynosaur_struct) = 75 | &mut *value; 76 | unsafe { ::core::mem::transmute(value) } 77 | } 78 | } 79 | } 80 | pub(crate) use __dynosaur_macro_dynmytrait::DynMyTrait; 81 | 82 | fn main() {} 83 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/where-self-sized-rpit.rs: -------------------------------------------------------------------------------- 1 | use dynosaur::dynosaur; 2 | 3 | #[dynosaur(DynMyTrait)] 4 | trait MyTrait { 5 | fn foo(&mut self) -> impl ::core::future::Future 6 | where 7 | Self: Sized; 8 | async fn bar(&mut self); 9 | } 10 | 11 | fn main() {} 12 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/where-self-sized-rpit.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use dynosaur::dynosaur; 7 | 8 | trait MyTrait { 9 | fn foo(&mut self) 10 | -> impl ::core::future::Future 11 | where 12 | Self: Sized; 13 | async fn bar(&mut self); 14 | } 15 | mod __dynosaur_macro_dynmytrait { 16 | use super::*; 17 | trait ErasedMyTrait { 18 | fn bar<'life0, 'dynosaur>(&'life0 mut self) 19 | -> 20 | ::core::pin::Pin + 21 | 'dynosaur>> 22 | where 23 | 'life0: 'dynosaur, 24 | Self: 'dynosaur; 25 | } 26 | impl ErasedMyTrait for DYNOSAUR { 27 | fn bar<'life0, 'dynosaur>(&'life0 mut self) 28 | -> 29 | ::core::pin::Pin + 30 | 'dynosaur>> where 'life0: 'dynosaur, Self: 'dynosaur { 31 | Box::pin(::bar(self)) 32 | } 33 | } 34 | #[repr(transparent)] 35 | pub struct DynMyTrait<'dynosaur_struct> { 36 | ptr: dyn ErasedMyTrait + 'dynosaur_struct, 37 | } 38 | impl<'dynosaur_struct> MyTrait for DynMyTrait<'dynosaur_struct> { 39 | #[allow(unreachable_code)] 40 | fn foo(&mut self) -> impl ::core::future::Future where 41 | Self: Sized { 42 | 43 | 44 | ::core::panicking::panic("internal error: entered unreachable code") 45 | as 46 | ::core::pin::Pin + 47 | 'static>> 48 | } 49 | fn bar(&mut self) -> impl ::core::future::Future { 50 | let ret: 51 | ::core::pin::Pin + '_>> = self.ptr.bar(); 53 | let ret: 54 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 56 | ret 57 | } 58 | } 59 | impl<'dynosaur_struct> DynMyTrait<'dynosaur_struct> { 60 | pub fn new_box(value: impl MyTrait + 'dynosaur_struct) 61 | -> Box> { 62 | let value = Box::new(value); 63 | let value: Box = value; 64 | unsafe { ::core::mem::transmute(value) } 65 | } 66 | pub fn new_arc(value: impl MyTrait + 'dynosaur_struct) 67 | -> std::sync::Arc> { 68 | let value = std::sync::Arc::new(value); 69 | let value: std::sync::Arc = 70 | value; 71 | unsafe { ::core::mem::transmute(value) } 72 | } 73 | pub fn new_rc(value: impl MyTrait + 'dynosaur_struct) 74 | -> std::rc::Rc> { 75 | let value = std::rc::Rc::new(value); 76 | let value: std::rc::Rc = 77 | value; 78 | unsafe { ::core::mem::transmute(value) } 79 | } 80 | pub fn from_ref(value: &(impl MyTrait + 'dynosaur_struct)) 81 | -> &DynMyTrait<'dynosaur_struct> { 82 | let value: &(dyn ErasedMyTrait + 'dynosaur_struct) = &*value; 83 | unsafe { ::core::mem::transmute(value) } 84 | } 85 | pub fn from_mut(value: &mut (impl MyTrait + 'dynosaur_struct)) 86 | -> &mut DynMyTrait<'dynosaur_struct> { 87 | let value: &mut (dyn ErasedMyTrait + 'dynosaur_struct) = 88 | &mut *value; 89 | unsafe { ::core::mem::transmute(value) } 90 | } 91 | } 92 | } 93 | use __dynosaur_macro_dynmytrait::DynMyTrait; 94 | fn main() {} 95 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/where-self-sized.rs: -------------------------------------------------------------------------------- 1 | use dynosaur::dynosaur; 2 | 3 | #[dynosaur(DynMyTrait)] 4 | trait MyTrait { 5 | async fn foo(&mut self) 6 | where 7 | Self: Sized; 8 | async fn bar(&mut self); 9 | } 10 | 11 | fn main() {} 12 | -------------------------------------------------------------------------------- /dynosaur/tests/pass/where-self-sized.stdout: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | use dynosaur::dynosaur; 7 | 8 | trait MyTrait { 9 | async fn foo(&mut self) 10 | where 11 | Self: Sized; 12 | async fn bar(&mut self); 13 | } 14 | mod __dynosaur_macro_dynmytrait { 15 | use super::*; 16 | trait ErasedMyTrait { 17 | fn bar<'life0, 'dynosaur>(&'life0 mut self) 18 | -> 19 | ::core::pin::Pin + 20 | 'dynosaur>> 21 | where 22 | 'life0: 'dynosaur, 23 | Self: 'dynosaur; 24 | } 25 | impl ErasedMyTrait for DYNOSAUR { 26 | fn bar<'life0, 'dynosaur>(&'life0 mut self) 27 | -> 28 | ::core::pin::Pin + 29 | 'dynosaur>> where 'life0: 'dynosaur, Self: 'dynosaur { 30 | Box::pin(::bar(self)) 31 | } 32 | } 33 | #[repr(transparent)] 34 | pub struct DynMyTrait<'dynosaur_struct> { 35 | ptr: dyn ErasedMyTrait + 'dynosaur_struct, 36 | } 37 | impl<'dynosaur_struct> MyTrait for DynMyTrait<'dynosaur_struct> { 38 | async fn foo(&mut self) where Self: Sized { 39 | 40 | ::core::panicking::panic("internal error: entered unreachable code") 41 | } 42 | fn bar(&mut self) -> impl ::core::future::Future { 43 | let ret: 44 | ::core::pin::Pin + '_>> = self.ptr.bar(); 46 | let ret: 47 | ::core::pin::Pin + 'static>> = unsafe { ::core::mem::transmute(ret) }; 49 | ret 50 | } 51 | } 52 | impl<'dynosaur_struct> DynMyTrait<'dynosaur_struct> { 53 | pub fn new_box(value: impl MyTrait + 'dynosaur_struct) 54 | -> Box> { 55 | let value = Box::new(value); 56 | let value: Box = value; 57 | unsafe { ::core::mem::transmute(value) } 58 | } 59 | pub fn new_arc(value: impl MyTrait + 'dynosaur_struct) 60 | -> std::sync::Arc> { 61 | let value = std::sync::Arc::new(value); 62 | let value: std::sync::Arc = 63 | value; 64 | unsafe { ::core::mem::transmute(value) } 65 | } 66 | pub fn new_rc(value: impl MyTrait + 'dynosaur_struct) 67 | -> std::rc::Rc> { 68 | let value = std::rc::Rc::new(value); 69 | let value: std::rc::Rc = 70 | value; 71 | unsafe { ::core::mem::transmute(value) } 72 | } 73 | pub fn from_ref(value: &(impl MyTrait + 'dynosaur_struct)) 74 | -> &DynMyTrait<'dynosaur_struct> { 75 | let value: &(dyn ErasedMyTrait + 'dynosaur_struct) = &*value; 76 | unsafe { ::core::mem::transmute(value) } 77 | } 78 | pub fn from_mut(value: &mut (impl MyTrait + 'dynosaur_struct)) 79 | -> &mut DynMyTrait<'dynosaur_struct> { 80 | let value: &mut (dyn ErasedMyTrait + 'dynosaur_struct) = 81 | &mut *value; 82 | unsafe { ::core::mem::transmute(value) } 83 | } 84 | } 85 | } 86 | use __dynosaur_macro_dynmytrait::DynMyTrait; 87 | fn main() {} 88 | -------------------------------------------------------------------------------- /dynosaur/tests/ui.rs: -------------------------------------------------------------------------------- 1 | use std::path::{Path, PathBuf}; 2 | 3 | use ui_test::color_eyre::eyre::Result; 4 | use ui_test::dependencies::DependencyBuilder; 5 | use ui_test::spanned::Spanned; 6 | use ui_test::{ignore_output_conflict, run_tests, CommandBuilder, Config}; 7 | 8 | enum Mode { 9 | Expand, 10 | Compile, 11 | Panic, 12 | } 13 | 14 | fn cfg(path: &Path, mode: Mode) -> Config { 15 | let mut config = Config { 16 | program: CommandBuilder::rustc(), 17 | output_conflict_handling: if std::env::var_os("BLESS").is_some() { 18 | ui_test::bless_output_files 19 | } else { 20 | ui_test::error_on_output_conflict 21 | }, 22 | ..Config::rustc(path) 23 | }; 24 | 25 | let exit_status = match mode { 26 | Mode::Expand => { 27 | config.program.args.push("-Zunpretty=expanded".into()); 28 | 0 29 | } 30 | 31 | Mode::Compile => { 32 | config.output_conflict_handling = ignore_output_conflict; 33 | 0 34 | } 35 | 36 | Mode::Panic => 101, 37 | }; 38 | 39 | let require_annotations = false; // we're not showing errors in a specific line anyway 40 | config.comment_defaults.base().exit_status = Spanned::dummy(exit_status).into(); 41 | config.comment_defaults.base().require_annotations = Spanned::dummy(require_annotations).into(); 42 | config.comment_defaults.base().set_custom( 43 | "dependencies", 44 | DependencyBuilder { 45 | crate_manifest_path: PathBuf::from("tests/Cargo.toml"), 46 | ..DependencyBuilder::default() 47 | }, 48 | ); 49 | config 50 | } 51 | 52 | fn main() -> Result<()> { 53 | run_tests(cfg(&Path::new("tests/pass"), Mode::Expand))?; 54 | run_tests(cfg(&Path::new("tests/pass"), Mode::Compile))?; 55 | run_tests(cfg(&Path::new("tests/fail"), Mode::Panic)) 56 | } 57 | -------------------------------------------------------------------------------- /dynosaur_derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dynosaur_derive" 3 | version = "0.2.0" 4 | authors = [ 5 | "Santiago Pastorino ", 6 | "Tyler Mandry ", 7 | "Niko Matsakis ", 8 | ] 9 | categories = ["asynchronous", "no-std"] 10 | keywords = ["async", "trait", "impl"] 11 | description = "Dynamic dispatch for return position impl traits and async in Rust" 12 | documentation = "https://docs.rs/dynosaur" 13 | license = "MIT OR Apache-2.0" 14 | repository = "https://github.com/spastorino/dynosaur" 15 | edition = "2021" 16 | rust-version = "1.75" 17 | 18 | [lib] 19 | proc-macro = true 20 | 21 | [dependencies] 22 | proc-macro2 = "1.0" 23 | quote = "1.0" 24 | syn = { version = "2.0", features = ["full", "visit", "visit-mut"] } 25 | 26 | [dev-dependencies] 27 | tokio = { workspace = true } 28 | trait-variant = { workspace = true } 29 | -------------------------------------------------------------------------------- /dynosaur_derive/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2024 The Rust Project Developers 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /dynosaur_derive/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 The Rust Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /dynosaur_derive/src/expand.rs: -------------------------------------------------------------------------------- 1 | use crate::lifetime::{AddLifetimeToImplTrait, CollectLifetimes}; 2 | use crate::receiver::has_self_in_sig; 3 | use crate::sig::{is_async, is_future, is_rpit}; 4 | use crate::where_clauses::{has_where_self_sized, where_clause_or_default}; 5 | use proc_macro2::{Span, TokenStream}; 6 | use quote::quote; 7 | use std::mem; 8 | use syn::punctuated::Punctuated; 9 | use syn::visit_mut::VisitMut; 10 | use syn::{ 11 | parse_quote, parse_quote_spanned, Error, FnArg, GenericParam, Generics, Ident, ItemTrait, 12 | Lifetime, Pat, PatIdent, ReturnType, Signature, Token, Type, TypeImplTrait, TypeParamBound, 13 | }; 14 | 15 | /// Expands the signature of each function on the trait, converting async fn into fn with return 16 | /// type Future and makes lifetimes explicit. 17 | /// 18 | /// Converts: 19 | /// 20 | /// ```rust 21 | /// trait MyTrait { 22 | /// async fn foo(&self) -> i32; 23 | /// } 24 | /// ``` 25 | /// 26 | /// into: 27 | /// 28 | /// ```rust 29 | /// trait ErasedMyTrait { 30 | /// fn foo<'life0, 'dynosaur>(&'life0 self) 31 | /// -> 32 | /// ::core::pin::Pin + 33 | /// 'dynosaur>> 34 | /// where 35 | /// 'life0: 'dynosaur, 36 | /// Self: 'dynosaur; 37 | /// } 38 | /// ``` 39 | pub(crate) fn expand_fn_sig(item_trait_generics: &Generics, sig: &mut Signature) { 40 | expand_arg_names(sig); 41 | expand_apits(sig); 42 | 43 | if is_async(sig) || is_rpit(sig) { 44 | expand_fn_input(item_trait_generics, sig); 45 | let ret_ty = expand_sig_ret_ty(sig, "'dynosaur"); 46 | if let Some(asyncness) = sig.asyncness.take() { 47 | sig.fn_token.span = asyncness.span; 48 | } 49 | sig.output = parse_quote! { -> #ret_ty }; 50 | } 51 | } 52 | 53 | fn expand_apits(sig: &mut Signature) { 54 | let lifetime_ident = if is_async(sig) { "'dynosaur" } else { "'_" }; 55 | 56 | for arg in &mut sig.inputs { 57 | if let FnArg::Typed(arg) = arg { 58 | if let Type::ImplTrait(type_impl_trait) = &*arg.ty { 59 | let bounds = expand_bounds(&type_impl_trait.bounds, Some(lifetime_ident)); 60 | 61 | arg.ty = if is_future(type_impl_trait) { 62 | parse_quote! { ::core::pin::Pin> } 63 | } else { 64 | parse_quote! { Box } 65 | }; 66 | } 67 | } 68 | } 69 | } 70 | 71 | fn expand_fn_input(item_trait_generics: &Generics, sig: &mut Signature) { 72 | let mut lifetimes = CollectLifetimes::new(); 73 | for arg in &mut sig.inputs { 74 | match arg { 75 | FnArg::Receiver(arg) => lifetimes.visit_receiver_mut(arg), 76 | FnArg::Typed(arg) => lifetimes.visit_type_mut(&mut arg.ty), 77 | } 78 | } 79 | 80 | for param in &mut sig.generics.params { 81 | match param { 82 | GenericParam::Type(param) => { 83 | let param_name = ¶m.ident; 84 | let span = match param.colon_token.take() { 85 | Some(colon_token) => colon_token.span, 86 | None => param_name.span(), 87 | }; 88 | let bounds = mem::replace(&mut param.bounds, Punctuated::new()); 89 | where_clause_or_default(&mut sig.generics.where_clause) 90 | .predicates 91 | .push(parse_quote_spanned!(span=> #param_name: 'dynosaur + #bounds)); 92 | } 93 | GenericParam::Lifetime(param) => { 94 | let param_name = ¶m.lifetime; 95 | let span = match param.colon_token.take() { 96 | Some(colon_token) => colon_token.span, 97 | None => param_name.span(), 98 | }; 99 | let bounds = mem::replace(&mut param.bounds, Punctuated::new()); 100 | where_clause_or_default(&mut sig.generics.where_clause) 101 | .predicates 102 | .push(parse_quote_spanned!(span=> #param: 'dynosaur + #bounds)); 103 | } 104 | GenericParam::Const(_) => {} 105 | } 106 | } 107 | 108 | for lifetime in item_trait_generics 109 | .params 110 | .iter() 111 | .filter_map(move |param| match param { 112 | GenericParam::Lifetime(param) => Some(¶m.lifetime), 113 | _ => None, 114 | }) 115 | { 116 | let span = lifetime.span(); 117 | where_clause_or_default(&mut sig.generics.where_clause) 118 | .predicates 119 | .push(parse_quote_spanned!(span=> #lifetime: 'dynosaur)); 120 | } 121 | 122 | if sig.generics.lt_token.is_none() { 123 | sig.generics.lt_token = Some(Token![<](sig.ident.span())); 124 | } 125 | if sig.generics.gt_token.is_none() { 126 | sig.generics.gt_token = Some(Token![>](sig.paren_token.span.join())); 127 | } 128 | 129 | for elided in lifetimes.elided { 130 | sig.generics.params.push(parse_quote!(#elided)); 131 | where_clause_or_default(&mut sig.generics.where_clause) 132 | .predicates 133 | .push(parse_quote_spanned!(elided.span()=> #elided: 'dynosaur)); 134 | } 135 | 136 | sig.generics.params.push(parse_quote!('dynosaur)); 137 | 138 | if has_self_in_sig(sig) { 139 | where_clause_or_default(&mut sig.generics.where_clause) 140 | .predicates 141 | .push(parse_quote! { 142 | Self: 'dynosaur 143 | }); 144 | } 145 | 146 | for arg in &mut sig.inputs { 147 | if let FnArg::Typed(arg) = arg { 148 | AddLifetimeToImplTrait.visit_type_mut(&mut arg.ty); 149 | } 150 | } 151 | } 152 | 153 | pub(crate) fn expand_arg_names(sig: &mut Signature) { 154 | let mut wild_id = 1; 155 | 156 | for arg in &mut sig.inputs { 157 | if let FnArg::Typed(arg) = arg { 158 | if matches!(*arg.pat, Pat::Wild(_)) { 159 | arg.pat = Box::new(Pat::Ident(PatIdent { 160 | attrs: Vec::new(), 161 | by_ref: None, 162 | mutability: None, 163 | ident: Ident::new(&format!("__dynosaur_arg{}", wild_id), Span::call_site()), 164 | subpat: None, 165 | })); 166 | 167 | wild_id += 1; 168 | } 169 | } 170 | } 171 | } 172 | 173 | pub(crate) fn expand_sig_ret_ty(sig: &Signature, lifetime_ident: &str) -> Type { 174 | let is_async = is_async(sig); 175 | let is_rpit = is_rpit(sig); 176 | 177 | if is_async || is_rpit { 178 | let bounds = expand_ret_bounds(sig, Some(lifetime_ident)); 179 | 180 | if is_async { 181 | parse_quote! { ::core::pin::Pin> } 182 | } else { 183 | parse_quote! { Box } 184 | } 185 | } else { 186 | match &sig.output { 187 | ReturnType::Default => parse_quote! { () }, 188 | ReturnType::Type(_, ty) => parse_quote! { #ty }, 189 | } 190 | } 191 | } 192 | 193 | pub(crate) fn expand_sig_ret_ty_to_rpit(sig: &Signature) -> Type { 194 | let bounds = expand_ret_bounds(sig, None); 195 | parse_quote! { impl #bounds } 196 | } 197 | 198 | pub(crate) fn expand_ret_bounds( 199 | sig: &Signature, 200 | lifetime: Option<&str>, 201 | ) -> Punctuated { 202 | let mut ret_bounds = Punctuated::new(); 203 | 204 | let ret_bounds = match (sig.asyncness.is_some(), &sig.output) { 205 | (true, ReturnType::Default) => { 206 | ret_bounds.push(TypeParamBound::Verbatim( 207 | quote! { ::core::future::Future }, 208 | )); 209 | &ret_bounds 210 | } 211 | (true, ReturnType::Type(_, ret)) => { 212 | ret_bounds.push(TypeParamBound::Verbatim( 213 | quote! { ::core::future::Future }, 214 | )); 215 | &ret_bounds 216 | } 217 | (false, ReturnType::Type(_, ret)) => { 218 | if let Type::ImplTrait(TypeImplTrait { bounds, .. }) = &**ret { 219 | bounds 220 | } else { 221 | ret_bounds.push(TypeParamBound::Verbatim( 222 | Error::new_spanned(&sig.output, "unsupported return type").to_compile_error(), 223 | )); 224 | &ret_bounds 225 | } 226 | } 227 | _ => { 228 | ret_bounds.push(TypeParamBound::Verbatim( 229 | Error::new_spanned(&sig.output, "unsupported return type").to_compile_error(), 230 | )); 231 | &ret_bounds 232 | } 233 | }; 234 | 235 | expand_bounds(&ret_bounds, lifetime) 236 | } 237 | 238 | fn expand_bounds( 239 | bounds: &Punctuated, 240 | lifetime: Option<&str>, 241 | ) -> Punctuated { 242 | let mut ret_bounds = Punctuated::new(); 243 | 244 | for bound in bounds { 245 | if !matches!(bound, TypeParamBound::Lifetime(_)) { 246 | ret_bounds.push(bound.clone()); 247 | } 248 | } 249 | 250 | if let Some(lifetime) = lifetime { 251 | ret_bounds.push(TypeParamBound::Lifetime(Lifetime::new( 252 | lifetime, 253 | Span::call_site(), 254 | ))); 255 | } 256 | 257 | ret_bounds 258 | } 259 | 260 | pub(crate) fn expand_invoke_args(sig: &Signature, ufc: bool) -> Vec { 261 | let mut args = Vec::new(); 262 | 263 | for arg in &sig.inputs { 264 | match arg { 265 | FnArg::Receiver(_) => { 266 | if !ufc { 267 | // Do not need & or &mut as this is at calling site 268 | args.push(quote! { self }); 269 | } 270 | } 271 | FnArg::Typed(pat_type) => match &*pat_type.pat { 272 | Pat::Ident(arg) => { 273 | if let Type::ImplTrait(type_impl_trait) = &*pat_type.ty { 274 | if is_future(type_impl_trait) { 275 | args.push(quote! { Box::pin(#arg) }); 276 | } else { 277 | args.push(quote! { Box::new(#arg) }); 278 | } 279 | } else { 280 | args.push(quote! { #arg }); 281 | } 282 | } 283 | _ => { 284 | args.push( 285 | Error::new_spanned( 286 | &pat_type.pat, 287 | "patterns are not supported in arguments", 288 | ) 289 | .to_compile_error(), 290 | ); 291 | } 292 | }, 293 | } 294 | } 295 | 296 | args 297 | } 298 | 299 | pub(crate) fn expand_blanket_impl_fn(item_trait: &ItemTrait, sig: &mut Signature) -> TokenStream { 300 | let is_async = is_async(sig); 301 | let is_rpit = is_rpit(sig); 302 | 303 | expand_fn_sig(&item_trait.generics, sig); 304 | 305 | let trait_ident = &item_trait.ident; 306 | let (_, trait_generics, _) = &item_trait.generics.split_for_impl(); 307 | let ident = &sig.ident; 308 | let args = expand_invoke_args(sig, false); 309 | let value = quote! { ::#ident(#(#args),*) }; 310 | 311 | let value = if is_async { 312 | quote! { 313 | Box::pin(#value) 314 | } 315 | } else if is_rpit { 316 | quote! { 317 | Box::new(#value) 318 | } 319 | } else { 320 | value 321 | }; 322 | 323 | quote! { 324 | #sig { 325 | #value 326 | } 327 | } 328 | } 329 | 330 | pub(crate) fn expand_dyn_struct_fn(sig: &Signature) -> TokenStream { 331 | if has_where_self_sized(sig) { 332 | if is_rpit(sig) { 333 | let ty = expand_sig_ret_ty(&sig, "'static"); 334 | quote! { 335 | #[allow(unreachable_code)] 336 | #sig { 337 | unreachable!() as #ty 338 | } 339 | } 340 | } else { 341 | quote! { 342 | #sig { 343 | unreachable!() 344 | } 345 | } 346 | } 347 | } else { 348 | let ident = &sig.ident; 349 | let is_async = is_async(sig); 350 | let is_rpit = is_rpit(sig); 351 | 352 | let mut sig = sig.clone(); 353 | expand_arg_names(&mut sig); 354 | let args = expand_invoke_args(&sig, true); 355 | 356 | if !is_async && !is_rpit { 357 | quote! { 358 | #sig { 359 | self.ptr.#ident(#(#args),*) 360 | } 361 | } 362 | } else { 363 | let (ty1, ty2) = if is_async { 364 | let ty1 = expand_sig_ret_ty(&sig, "'_"); 365 | let ty2 = expand_sig_ret_ty(&sig, "'static"); 366 | let sig_ret_ty = expand_sig_ret_ty_to_rpit(&mut sig); 367 | sig.output = parse_quote! { -> #sig_ret_ty }; 368 | (ty1, ty2) 369 | } else { 370 | // is_rpit 371 | let ty = expand_sig_ret_ty(&sig, "'_"); 372 | (ty.clone(), ty) 373 | }; 374 | 375 | if let Some(asyncness) = sig.asyncness.take() { 376 | sig.fn_token.span = asyncness.span; 377 | } 378 | 379 | quote! { 380 | #sig { 381 | let ret: #ty1 = self.ptr.#ident(#(#args),*); 382 | let ret: #ty2 = unsafe { ::core::mem::transmute(ret) }; 383 | ret 384 | } 385 | } 386 | } 387 | } 388 | } 389 | -------------------------------------------------------------------------------- /dynosaur_derive/src/lib.rs: -------------------------------------------------------------------------------- 1 | use expand::{expand_blanket_impl_fn, expand_dyn_struct_fn, expand_fn_sig}; 2 | use proc_macro2::{Span, TokenStream}; 3 | use quote::quote; 4 | use syn::{ 5 | parse::{Parse, ParseStream}, 6 | parse_macro_input, parse_quote, 7 | punctuated::Punctuated, 8 | Error, GenericParam, Ident, ItemTrait, Result, Token, TraitItem, TraitItemConst, TraitItemFn, 9 | TraitItemType, TypeParam, Visibility, 10 | }; 11 | use traits::{ 12 | dyn_compatible_items, struct_trait_params, trait_item_erased_name, StructTraitParams, 13 | }; 14 | 15 | mod expand; 16 | mod lifetime; 17 | mod receiver; 18 | mod sig; 19 | mod traits; 20 | mod where_clauses; 21 | 22 | struct Attrs { 23 | vis: Visibility, 24 | ident: Ident, 25 | target: Option, 26 | } 27 | 28 | struct Target { 29 | trait_name: Ident, 30 | } 31 | 32 | impl Parse for Attrs { 33 | fn parse(input: ParseStream) -> Result { 34 | Ok(Attrs { 35 | vis: input.parse()?, 36 | ident: input.parse()?, 37 | target: if input.peek(Token![=]) { 38 | input.parse::()?; 39 | input.parse::()?; 40 | Some(Target { 41 | trait_name: input.parse()?, 42 | }) 43 | } else { 44 | None 45 | }, 46 | }) 47 | } 48 | } 49 | 50 | /// Create a struct that takes the place of `dyn Trait` for a trait, supporting 51 | /// both `async` and `-> impl Trait` methods. 52 | /// 53 | /// ``` 54 | /// # mod dynosaur { pub use dynosaur_derive::dynosaur; } 55 | /// #[dynosaur::dynosaur(pub DynNext)] 56 | /// pub trait Next { 57 | /// type Item; 58 | /// async fn next(&self) -> Option; 59 | /// } 60 | /// # // This is necessary to prevent weird scoping errors in the doctets: 61 | /// # fn main() {} 62 | /// ``` 63 | /// 64 | /// Here, the struct is named `DynNext`. It can be used like this: 65 | /// 66 | /// ``` 67 | /// # mod dynosaur { pub use dynosaur_derive::dynosaur; } 68 | /// # #[dynosaur::dynosaur(DynNext)] 69 | /// # trait Next { 70 | /// # type Item; 71 | /// # async fn next(&self) -> Option; 72 | /// # } 73 | /// # 74 | /// # fn from_iter(v: T) -> impl Next { 75 | /// # Never 76 | /// # } 77 | /// # struct Never; 78 | /// # impl Next for Never { 79 | /// # type Item = i32; 80 | /// # async fn next(&self) -> Option { None } 81 | /// # } 82 | /// # 83 | /// # #[tokio::main(flavor = "current_thread")] 84 | /// # async fn main() { 85 | /// # 86 | /// async fn dyn_dispatch(iter: &mut DynNext<'_, i32>) { 87 | /// while let Some(item) = iter.next().await { 88 | /// println!("- {item}"); 89 | /// } 90 | /// } 91 | /// 92 | /// let a = [1, 2, 3]; 93 | /// dyn_dispatch(DynNext::from_mut(&mut from_iter(a))).await; 94 | /// # } 95 | /// ``` 96 | /// 97 | /// ## Interface 98 | /// 99 | /// The `Dyn` struct produced by this macro has the following constructors: 100 | /// 101 | /// ```ignore 102 | /// impl<'a> DynTrait<'a> { 103 | /// fn new_box(from: impl Trait) -> Box { ... } 104 | /// fn new_arc(from: impl Trait) -> std::sync::Arc { ... } 105 | /// fn new_rc(from: impl Trait) -> std::rc::Rc { ... } 106 | /// fn from_ref(from: &'a impl Trait) -> &'a Self { ... } 107 | /// fn from_mut(from: &'a mut impl Trait) -> &'a mut Self { ... } 108 | /// } 109 | /// ``` 110 | /// 111 | /// Normally a concrete type behind a pointer coerces to `dyn Trait` implicitly. 112 | /// When using the `Dyn` struct created by this macro, such conversions must be 113 | /// done explicitly with the provided constructors. 114 | /// 115 | /// ## Use with `trait_variant` 116 | /// 117 | /// You can use dynosaur with the trait_variant macro like this. The 118 | /// trait_variant attribute must go first. 119 | /// 120 | /// ```rust 121 | /// # pub mod dynosaur { pub use dynosaur_derive::dynosaur; } 122 | /// #[trait_variant::make(SendNext: Send)] 123 | /// #[dynosaur::dynosaur(DynNext = dyn Next)] 124 | /// #[dynosaur::dynosaur(DynSendNext = dyn SendNext)] 125 | /// trait Next { 126 | /// type Item; 127 | /// async fn next(&mut self) -> Option; 128 | /// } 129 | /// # // This is necessary to prevent weird scoping errors in the doctets: 130 | /// # fn main() {} 131 | /// ``` 132 | /// 133 | /// The `DynNext = dyn Next` is a more explicit form of the macro invocation 134 | /// that allows you to select a particular trait. 135 | /// 136 | /// ## Performance 137 | /// 138 | /// In addition to the normal overhead of dynamic dispatch, calling `async` and 139 | /// `-> impl Trait` methods on a `Dyn` struct will box the returned value so it 140 | /// has a known size. 141 | /// 142 | /// There is no performance cost to using this macro when the trait is used with 143 | /// static dispatch. 144 | #[proc_macro_attribute] 145 | pub fn dynosaur( 146 | attr: proc_macro::TokenStream, 147 | item: proc_macro::TokenStream, 148 | ) -> proc_macro::TokenStream { 149 | let attrs = parse_macro_input!(attr as Attrs); 150 | let item_trait = parse_macro_input!(item as ItemTrait); 151 | if let Some(target) = attrs.target { 152 | // This attribute is being applied to a different trait than the one 153 | // named (possibly one created by trait_variant). 154 | // TODO: Add checking in case a trait is missing or misspelled. 155 | if target.trait_name != item_trait.ident { 156 | return quote! { #item_trait }.into(); 157 | } 158 | } 159 | 160 | let vis = &attrs.vis; 161 | let struct_ident = &attrs.ident; 162 | 163 | let erased_trait = mk_erased_trait(&item_trait); 164 | let erased_trait_blanket_impl = mk_erased_trait_blanket_impl(&item_trait); 165 | let dyn_struct = mk_dyn_struct(&struct_ident, &item_trait); 166 | let dyn_struct_impl_item = mk_dyn_struct_impl_item(struct_ident, &item_trait); 167 | let struct_inherent_impl = mk_struct_inherent_impl(struct_ident, &item_trait); 168 | 169 | let dynosaur_mod = Ident::new( 170 | &format!( 171 | "__dynosaur_macro_{}", 172 | struct_ident.to_string().to_lowercase(), 173 | ), 174 | Span::call_site(), 175 | ); 176 | 177 | quote! { 178 | #item_trait 179 | 180 | mod #dynosaur_mod { 181 | use super::*; 182 | #erased_trait 183 | #erased_trait_blanket_impl 184 | #dyn_struct 185 | #dyn_struct_impl_item 186 | #struct_inherent_impl 187 | } 188 | 189 | #vis use #dynosaur_mod::#struct_ident; 190 | } 191 | .into() 192 | } 193 | 194 | fn mk_erased_trait(item_trait: &ItemTrait) -> ItemTrait { 195 | let items: Vec<_> = dyn_compatible_items(&item_trait.items) 196 | .cloned() 197 | .map(|mut trait_item| { 198 | if let TraitItem::Fn(ref mut trait_item_fn) = trait_item { 199 | // Remove default method if any for the erased trait 200 | trait_item_fn.default = None; 201 | 202 | expand_fn_sig(&item_trait.generics, &mut trait_item_fn.sig); 203 | } 204 | 205 | trait_item 206 | }) 207 | .collect(); 208 | 209 | ItemTrait { 210 | ident: trait_item_erased_name(&item_trait.ident), 211 | items, 212 | ..item_trait.clone() 213 | } 214 | } 215 | 216 | fn mk_erased_trait_blanket_impl(item_trait: &ItemTrait) -> TokenStream { 217 | let trait_ident = &item_trait.ident; 218 | let erased_trait_ident = trait_item_erased_name(&trait_ident); 219 | let (_, trait_generics, _) = &item_trait.generics.split_for_impl(); 220 | 221 | let items = dyn_compatible_items(&item_trait.items) 222 | .cloned() 223 | .map(|trait_item| { 224 | match trait_item { 225 | TraitItem::Const(TraitItemConst { 226 | ident, 227 | generics, 228 | ty, 229 | .. 230 | }) => { 231 | // const makes the trait not dyn compatible, so whatever we do here is going to fail. 232 | // We should probably do a better error handling at some point. 233 | quote! { 234 | const #ident #generics: #ty = ::#ident; 235 | } 236 | } 237 | TraitItem::Fn(mut trait_item_fn) => { 238 | expand_blanket_impl_fn(item_trait, &mut trait_item_fn.sig) 239 | } 240 | TraitItem::Type(TraitItemType { ident, generics, .. }) => { 241 | let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 242 | quote! { 243 | type #ident #impl_generics = :: #ident #ty_generics #where_clause; 244 | } 245 | } 246 | _ => Error::new_spanned(trait_item, "unsupported item type").into_compile_error(), 247 | } 248 | }); 249 | 250 | let blanket_bound: TypeParam = parse_quote!(DYNOSAUR: #trait_ident #trait_generics); 251 | let blanket = blanket_bound.ident.clone(); 252 | let mut blanket_generics = item_trait.generics.clone(); 253 | blanket_generics 254 | .params 255 | .push(GenericParam::Type(blanket_bound)); 256 | let (blanket_impl_generics, _, blanket_where_clause) = &blanket_generics.split_for_impl(); 257 | 258 | quote! { 259 | impl #blanket_impl_generics #erased_trait_ident #trait_generics for #blanket #blanket_where_clause 260 | { 261 | #(#items)* 262 | } 263 | } 264 | } 265 | 266 | fn mk_dyn_struct(struct_ident: &Ident, item_trait: &ItemTrait) -> TokenStream { 267 | let erased_trait = mk_erased_trait(&item_trait); 268 | let erased_trait_ident = &erased_trait.ident; 269 | let StructTraitParams { 270 | struct_with_bounds_params, 271 | trait_params, 272 | .. 273 | } = struct_trait_params(&erased_trait); 274 | 275 | quote! { 276 | #[repr(transparent)] 277 | pub struct #struct_ident #struct_with_bounds_params { 278 | ptr: dyn #erased_trait_ident #trait_params + 'dynosaur_struct 279 | } 280 | } 281 | } 282 | 283 | fn mk_dyn_struct_impl_item(struct_ident: &Ident, item_trait: &ItemTrait) -> TokenStream { 284 | let item_trait_ident = &item_trait.ident; 285 | let (_, trait_generics, where_clause) = &item_trait.generics.split_for_impl(); 286 | 287 | let items = item_trait.items.iter().map(|item| match item { 288 | TraitItem::Const(TraitItemConst { 289 | ident, 290 | generics, 291 | ty, 292 | .. 293 | }) => { 294 | // const makes the trait not dyn compatible, so whatever we do here is going to fail. 295 | // We should probably do a better error handling at some point. 296 | quote! { 297 | const #ident #generics: #ty = ::#ident; 298 | } 299 | } 300 | TraitItem::Fn(TraitItemFn { sig, .. }) => expand_dyn_struct_fn(sig), 301 | TraitItem::Type(TraitItemType { 302 | ident, generics, .. 303 | }) => { 304 | let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 305 | quote! { 306 | type #ident #impl_generics = #ident #ty_generics #where_clause; 307 | } 308 | } 309 | _ => Error::new_spanned(item, "unsupported item type").into_compile_error(), 310 | }); 311 | 312 | let StructTraitParams { 313 | struct_params, 314 | struct_with_bounds_params, 315 | .. 316 | } = struct_trait_params(item_trait); 317 | 318 | quote! { 319 | impl #struct_with_bounds_params #item_trait_ident #trait_generics for #struct_ident #struct_params #where_clause 320 | { 321 | #(#items)* 322 | } 323 | } 324 | } 325 | 326 | fn mk_struct_inherent_impl(struct_ident: &Ident, item_trait: &ItemTrait) -> TokenStream { 327 | let trait_ident = &item_trait.ident; 328 | let erased_trait = mk_erased_trait(item_trait); 329 | let StructTraitParams { 330 | struct_params, 331 | struct_with_bounds_params, 332 | trait_params, 333 | } = struct_trait_params(&erased_trait); 334 | let erased_trait_ident = &erased_trait.ident; 335 | 336 | let mut where_bounds: Punctuated<_, Token![,]> = Punctuated::new(); 337 | erased_trait 338 | .generics 339 | .type_params() 340 | .map(|param| ¶m.ident) 341 | .for_each(|param| { 342 | where_bounds.push(quote! { 343 | #param: 'dynosaur_struct 344 | }); 345 | }); 346 | erased_trait.items.iter().for_each(|item| match item { 347 | TraitItem::Type(TraitItemType { ident, .. }) => { 348 | where_bounds.push(quote! { 349 | #ident: 'dynosaur_struct, 350 | }); 351 | } 352 | _ => {} 353 | }); 354 | 355 | quote! { 356 | impl #struct_with_bounds_params #struct_ident #struct_params 357 | { 358 | pub fn new_box(value: impl #trait_ident #trait_params + 'dynosaur_struct) -> Box<#struct_ident #struct_params> { 359 | let value = Box::new(value); 360 | let value: Box = value; 361 | unsafe { ::core::mem::transmute(value) } 362 | } 363 | 364 | pub fn new_arc(value: impl #trait_ident #trait_params + 'dynosaur_struct) -> std::sync::Arc<#struct_ident #struct_params> { 365 | let value = std::sync::Arc::new(value); 366 | let value: std::sync::Arc = value; 367 | unsafe { ::core::mem::transmute(value) } 368 | } 369 | 370 | pub fn new_rc(value: impl #trait_ident #trait_params + 'dynosaur_struct) -> std::rc::Rc<#struct_ident #struct_params> { 371 | let value = std::rc::Rc::new(value); 372 | let value: std::rc::Rc = value; 373 | unsafe { ::core::mem::transmute(value) } 374 | } 375 | 376 | pub fn from_ref(value: &(impl #trait_ident #trait_params + 'dynosaur_struct)) -> & #struct_ident #struct_params { 377 | let value: &(dyn #erased_trait_ident #trait_params + 'dynosaur_struct) = &*value; 378 | unsafe { ::core::mem::transmute(value) } 379 | } 380 | 381 | pub fn from_mut(value: &mut (impl #trait_ident #trait_params + 'dynosaur_struct)) -> &mut #struct_ident #struct_params { 382 | let value: &mut (dyn #erased_trait_ident #trait_params + 'dynosaur_struct) = &mut *value; 383 | unsafe { ::core::mem::transmute(value) } 384 | } 385 | } 386 | } 387 | } 388 | -------------------------------------------------------------------------------- /dynosaur_derive/src/lifetime.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::{Span, TokenStream}; 2 | use std::mem; 3 | use syn::visit_mut::{self, VisitMut}; 4 | use syn::{ 5 | parse_quote_spanned, token, Expr, GenericArgument, Lifetime, Receiver, ReturnType, Token, Type, 6 | TypeBareFn, TypeImplTrait, TypeParen, TypePtr, TypeReference, 7 | }; 8 | 9 | pub struct CollectLifetimes { 10 | pub elided: Vec, 11 | pub explicit: Vec, 12 | } 13 | 14 | impl CollectLifetimes { 15 | pub fn new() -> Self { 16 | CollectLifetimes { 17 | elided: Vec::new(), 18 | explicit: Vec::new(), 19 | } 20 | } 21 | 22 | fn visit_opt_lifetime(&mut self, reference: Token![&], lifetime: &mut Option) { 23 | match lifetime { 24 | None => *lifetime = Some(self.next_lifetime(reference.span)), 25 | Some(lifetime) => self.visit_lifetime(lifetime), 26 | } 27 | } 28 | 29 | fn visit_lifetime(&mut self, lifetime: &mut Lifetime) { 30 | if lifetime.ident == "_" { 31 | *lifetime = self.next_lifetime(lifetime.span()); 32 | } else { 33 | self.explicit.push(lifetime.clone()); 34 | } 35 | } 36 | 37 | fn next_lifetime(&mut self, span: Span) -> Lifetime { 38 | let name = format!("'life{}", self.elided.len()); 39 | let life = Lifetime::new(&name, span); 40 | self.elided.push(life.clone()); 41 | life 42 | } 43 | } 44 | 45 | impl VisitMut for CollectLifetimes { 46 | fn visit_receiver_mut(&mut self, arg: &mut Receiver) { 47 | if let Some((reference, lifetime)) = &mut arg.reference { 48 | self.visit_opt_lifetime(*reference, lifetime); 49 | } else { 50 | visit_mut::visit_type_mut(self, &mut arg.ty); 51 | } 52 | } 53 | 54 | fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) { 55 | self.visit_opt_lifetime(ty.and_token, &mut ty.lifetime); 56 | visit_mut::visit_type_reference_mut(self, ty); 57 | } 58 | 59 | fn visit_generic_argument_mut(&mut self, gen: &mut GenericArgument) { 60 | if let GenericArgument::Lifetime(lifetime) = gen { 61 | self.visit_lifetime(lifetime); 62 | } 63 | visit_mut::visit_generic_argument_mut(self, gen); 64 | } 65 | } 66 | 67 | pub struct AddLifetimeToImplTrait; 68 | 69 | impl VisitMut for AddLifetimeToImplTrait { 70 | fn visit_type_impl_trait_mut(&mut self, ty: &mut TypeImplTrait) { 71 | let span = ty.impl_token.span; 72 | let lifetime = parse_quote_spanned!(span=> 'dynosaur); 73 | ty.bounds.insert(0, lifetime); 74 | if let Some(punct) = ty.bounds.pairs_mut().next().unwrap().punct_mut() { 75 | punct.span = span; 76 | } 77 | visit_mut::visit_type_impl_trait_mut(self, ty); 78 | } 79 | 80 | fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) { 81 | parenthesize_impl_trait(&mut ty.elem, ty.and_token.span); 82 | visit_mut::visit_type_reference_mut(self, ty); 83 | } 84 | 85 | fn visit_type_ptr_mut(&mut self, ty: &mut TypePtr) { 86 | parenthesize_impl_trait(&mut ty.elem, ty.star_token.span); 87 | visit_mut::visit_type_ptr_mut(self, ty); 88 | } 89 | 90 | fn visit_type_bare_fn_mut(&mut self, ty: &mut TypeBareFn) { 91 | if let ReturnType::Type(arrow, return_type) = &mut ty.output { 92 | parenthesize_impl_trait(return_type, arrow.spans[0]); 93 | } 94 | visit_mut::visit_type_bare_fn_mut(self, ty); 95 | } 96 | 97 | fn visit_expr_mut(&mut self, _e: &mut Expr) { 98 | // Do not recurse into impl Traits inside of an array length expression. 99 | // 100 | // fn outer(arg: [u8; { fn inner(_: impl Trait) {}; 0 }]); 101 | } 102 | } 103 | 104 | fn parenthesize_impl_trait(elem: &mut Type, paren_span: Span) { 105 | if let Type::ImplTrait(_) = *elem { 106 | let placeholder = Type::Verbatim(TokenStream::new()); 107 | *elem = Type::Paren(TypeParen { 108 | paren_token: token::Paren(paren_span), 109 | elem: Box::new(mem::replace(elem, placeholder)), 110 | }); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /dynosaur_derive/src/receiver.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::{TokenStream, TokenTree}; 2 | use syn::visit::{self, Visit}; 3 | use syn::{ExprPath, Item, Macro, Receiver, Signature, TypePath}; 4 | 5 | pub fn has_self_in_sig(sig: &Signature) -> bool { 6 | let mut visitor = HasSelf(false); 7 | visitor.visit_signature(sig); 8 | visitor.0 9 | } 10 | 11 | struct HasSelf(bool); 12 | 13 | impl Visit<'_> for HasSelf { 14 | fn visit_expr_path(&mut self, expr: &ExprPath) { 15 | self.0 |= expr.path.segments[0].ident == "Self"; 16 | visit::visit_expr_path(self, expr); 17 | } 18 | 19 | fn visit_type_path(&mut self, ty: &TypePath) { 20 | self.0 |= ty.path.segments[0].ident == "Self"; 21 | visit::visit_type_path(self, ty); 22 | } 23 | 24 | fn visit_receiver(&mut self, _arg: &Receiver) { 25 | self.0 = true; 26 | } 27 | 28 | fn visit_item(&mut self, _: &Item) { 29 | // Do not recurse into nested items. 30 | } 31 | 32 | fn visit_macro(&mut self, mac: &Macro) { 33 | if !contains_fn(mac.tokens.clone()) { 34 | self.0 |= has_self_in_token_stream(mac.tokens.clone()); 35 | } 36 | } 37 | } 38 | 39 | fn contains_fn(tokens: TokenStream) -> bool { 40 | tokens.into_iter().any(|tt| match tt { 41 | TokenTree::Ident(ident) => ident == "fn", 42 | TokenTree::Group(group) => contains_fn(group.stream()), 43 | _ => false, 44 | }) 45 | } 46 | 47 | fn has_self_in_token_stream(tokens: TokenStream) -> bool { 48 | tokens.into_iter().any(|tt| match tt { 49 | TokenTree::Ident(ident) => ident == "Self", 50 | TokenTree::Group(group) => has_self_in_token_stream(group.stream()), 51 | _ => false, 52 | }) 53 | } 54 | -------------------------------------------------------------------------------- /dynosaur_derive/src/sig.rs: -------------------------------------------------------------------------------- 1 | use syn::{ReturnType, Signature, Type, TypeImplTrait, TypeParamBound}; 2 | 3 | pub(crate) fn is_async(sig: &Signature) -> bool { 4 | match sig { 5 | Signature { 6 | asyncness: Some(_), .. 7 | } => true, 8 | Signature { 9 | asyncness: None, 10 | output: ReturnType::Type(_, ret), 11 | .. 12 | } => { 13 | if let Type::ImplTrait(type_impl_trait) = &**ret { 14 | is_future(type_impl_trait) 15 | } else { 16 | false 17 | } 18 | } 19 | _ => false, 20 | } 21 | } 22 | 23 | pub(crate) fn is_rpit(sig: &Signature) -> bool { 24 | match sig { 25 | Signature { 26 | asyncness: Some(_), .. 27 | } => false, 28 | Signature { 29 | asyncness: None, 30 | output: ReturnType::Type(_, ret), 31 | .. 32 | } => { 33 | matches!(**ret, Type::ImplTrait(_)) 34 | } 35 | _ => false, 36 | } 37 | } 38 | 39 | pub(crate) fn is_future(type_impl_trait: &TypeImplTrait) -> bool { 40 | type_impl_trait 41 | .bounds 42 | .iter() 43 | .find(|bound| match bound { 44 | TypeParamBound::Trait(trait_bound) => { 45 | let segments = &trait_bound.path.segments; 46 | 47 | segments.len() == 3 48 | && (segments[0].ident == "core" || segments[0].ident == "std") 49 | && segments[1].ident == "future" 50 | && segments[2].ident == "Future" 51 | || segments.len() == 2 52 | && segments[0].ident == "future" 53 | && segments[1].ident == "Future" 54 | || segments.len() == 1 && segments[0].ident == "Future" 55 | } 56 | _ => false, 57 | }) 58 | .is_some() 59 | } 60 | -------------------------------------------------------------------------------- /dynosaur_derive/src/traits.rs: -------------------------------------------------------------------------------- 1 | use crate::where_clauses::has_where_self_sized; 2 | use proc_macro2::{Span, TokenStream}; 3 | use quote::quote; 4 | use syn::{punctuated::Punctuated, Ident, ItemTrait, Token, TraitItem, TraitItemType}; 5 | 6 | /// Remove Self: Sized fns 7 | pub(crate) fn dyn_compatible_items( 8 | item_trait_items: &[TraitItem], 9 | ) -> impl Iterator { 10 | item_trait_items 11 | .iter() 12 | .filter_map(|trait_item| match trait_item { 13 | TraitItem::Fn(trait_item_fn) if has_where_self_sized(&trait_item_fn.sig) => None, 14 | _ => Some(trait_item), 15 | }) 16 | } 17 | 18 | pub(crate) fn trait_item_erased_name(trait_ident: &Ident) -> Ident { 19 | Ident::new(&format!("Erased{}", trait_ident), Span::call_site()) 20 | } 21 | 22 | pub(crate) struct StructTraitParams { 23 | pub(crate) struct_params: TokenStream, 24 | pub(crate) struct_with_bounds_params: TokenStream, 25 | pub(crate) trait_params: TokenStream, 26 | } 27 | 28 | pub(crate) fn struct_trait_params(item_trait: &ItemTrait) -> StructTraitParams { 29 | let mut struct_params: Punctuated<_, Token![,]> = Punctuated::new(); 30 | let mut struct_with_bounds_params: Punctuated<_, Token![,]> = Punctuated::new(); 31 | let mut trait_params: Punctuated<_, Token![,]> = Punctuated::new(); 32 | 33 | struct_params.push(quote! { 'dynosaur_struct }); 34 | struct_with_bounds_params.push(quote! { 'dynosaur_struct }); 35 | item_trait.generics.params.iter().for_each(|item| { 36 | struct_params.push(quote! { #item }); 37 | struct_with_bounds_params.push(quote! { #item }); 38 | trait_params.push(quote! { #item }); 39 | }); 40 | item_trait.items.iter().for_each(|item| match item { 41 | TraitItem::Type(TraitItemType { ident, bounds, .. }) => { 42 | struct_params.push(quote! { #ident }); 43 | struct_with_bounds_params.push(quote! { #ident: #bounds }); 44 | trait_params.push(quote! { #ident = #ident }); 45 | } 46 | _ => {} 47 | }); 48 | 49 | StructTraitParams { 50 | struct_params: quote! { <#struct_params> }, 51 | struct_with_bounds_params: quote! { <#struct_with_bounds_params> }, 52 | // only this can be empty as others struct params include 'dynosaur 53 | trait_params: if trait_params.is_empty() { 54 | quote! {} 55 | } else { 56 | quote! { <#trait_params> } 57 | }, 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /dynosaur_derive/src/where_clauses.rs: -------------------------------------------------------------------------------- 1 | use syn::punctuated::Punctuated; 2 | use syn::visit::Visit; 3 | use syn::{PredicateType, Signature, Type, TypeParamBound, WhereClause, WherePredicate}; 4 | 5 | pub(crate) fn where_clause_or_default(clause: &mut Option) -> &mut WhereClause { 6 | clause.get_or_insert_with(|| WhereClause { 7 | where_token: Default::default(), 8 | predicates: Punctuated::new(), 9 | }) 10 | } 11 | 12 | pub(crate) fn has_where_self_sized(sig: &Signature) -> bool { 13 | let mut visitor = SelfSized(false); 14 | visitor.visit_signature(sig); 15 | visitor.0 16 | } 17 | 18 | struct SelfSized(bool); 19 | 20 | impl Visit<'_> for SelfSized { 21 | fn visit_where_clause(&mut self, clause: &WhereClause) { 22 | self.0 |= clause 23 | .predicates 24 | .iter() 25 | .find(|predicate| match predicate { 26 | WherePredicate::Type(PredicateType { 27 | bounded_ty: Type::Path(type_path), 28 | bounds, 29 | .. 30 | }) => { 31 | type_path.path.get_ident().map(|ident| ident.to_string()) 32 | == Some(String::from("Self")) 33 | && bounds 34 | .iter() 35 | .find(|bound| match bound { 36 | TypeParamBound::Trait(trait_bound) 37 | if trait_bound 38 | .path 39 | .get_ident() 40 | .map(|ident| ident.to_string()) 41 | == Some(String::from("Sized")) => 42 | { 43 | true 44 | } 45 | _ => false, 46 | }) 47 | .is_some() 48 | } 49 | 50 | _ => false, 51 | }) 52 | .is_some(); 53 | } 54 | } 55 | --------------------------------------------------------------------------------