summaryrefslogtreecommitdiffstats
path: root/vendor/gix-macros
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
commitc23a457e72abe608715ac76f076f47dc42af07a5 (patch)
tree2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /vendor/gix-macros
parentReleasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz
rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-macros')
-rw-r--r--vendor/gix-macros/.cargo-checksum.json1
-rw-r--r--vendor/gix-macros/CHANGELOG.md42
-rw-r--r--vendor/gix-macros/Cargo.toml48
-rw-r--r--vendor/gix-macros/LICENSE-APACHE191
-rw-r--r--vendor/gix-macros/LICENSE-MIT21
-rw-r--r--vendor/gix-macros/src/lib.rs25
-rw-r--r--vendor/gix-macros/src/momo.rs300
7 files changed, 628 insertions, 0 deletions
diff --git a/vendor/gix-macros/.cargo-checksum.json b/vendor/gix-macros/.cargo-checksum.json
new file mode 100644
index 000000000..34830fc82
--- /dev/null
+++ b/vendor/gix-macros/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"4e41a2cd2233b9444744d8c1a6ba04749a4f3020229a7bb8f27c9cb65881907c","Cargo.toml":"c164d4484f913884402cef2f7dd43ec3e28306f716ca07fca180be49cf735e5c","LICENSE-APACHE":"cb4780590812826851ba250f90bed0ed19506ec98f6865a0e2e20bbf62391ff9","LICENSE-MIT":"49df47913ab2beafe8dc45607877ae64198bf0eee64aaad3e82ed9e4d27424e8","src/lib.rs":"e6d25ecd41fc4c87d46295b9752a6a0f61034ef5d0e44962b43906da18e12d4d","src/momo.rs":"104edc9f2c8dc3c0d14adbdd19b0e21131f7738459f6be7f4f39955e7cfaf950"},"package":"9d8acb5ee668d55f0f2d19a320a3f9ef67a6999ad483e11135abcc2464ed18b6"} \ No newline at end of file
diff --git a/vendor/gix-macros/CHANGELOG.md b/vendor/gix-macros/CHANGELOG.md
new file mode 100644
index 000000000..d1c24c0ac
--- /dev/null
+++ b/vendor/gix-macros/CHANGELOG.md
@@ -0,0 +1,42 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## 0.1.0 (2023-09-08)
+
+The initial release with support for the `momo` proc-macro.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 14 commits contributed to the release over the course of 13 calendar days.
+ - 0 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Prepare changelogs for release ([`375db06`](https://github.com/Byron/gitoxide/commit/375db06a8442378c3f7a922fae38e2a6694d9d04))
+ - Merge branch 'feat/gix-momo' ([`a1ed6a1`](https://github.com/Byron/gitoxide/commit/a1ed6a1aacae02a167b7ec44e1a47411a2194ff7))
+ - Consolidate compile tests ([`d76efdd`](https://github.com/Byron/gitoxide/commit/d76efddf5afb73563ce7e837cf975cedd01e979c))
+ - Revert to use `item_fn.span()` ([`72545e9`](https://github.com/Byron/gitoxide/commit/72545e971c894de511a723f6d5515f637a84f28f))
+ - Fix ui test `error_if_ineffective` ([`9be2622`](https://github.com/Byron/gitoxide/commit/9be26220876498df4d1add77da45c415268a77dc))
+ - Add test-suite for failure modes ([`c8e7324`](https://github.com/Byron/gitoxide/commit/c8e732430f3740348ccedd0dc1a9a28b06a0adee))
+ - Remove `TODO` in `gix-macros/src/lib.rs` ([`c4ed7c1`](https://github.com/Byron/gitoxide/commit/c4ed7c180e3ec1ff75cb10d78d4b8eed3b75be2f))
+ - Improve docs ([`705f2f3`](https://github.com/Byron/gitoxide/commit/705f2f34f1fa95d767646b154f41d2a6ce65ad10))
+ - Refactor ([`48a2088`](https://github.com/Byron/gitoxide/commit/48a20888d158b94811074a09a8c57ff5c8410769))
+ - Feat `momo`: Rm unnecessary `#[allow(unused_mut)]` on generated inner fn ([`b619456`](https://github.com/Byron/gitoxide/commit/b6194568e1d3042305f472103e1c00549cc4ccb9))
+ - Feat `momo`: Support parsing pattern in params ([`b5f78be`](https://github.com/Byron/gitoxide/commit/b5f78be06792153cd981c316a486974c000f1fd8))
+ - Dramatically simplify `gix_macros::momo` ([`c72eaa0`](https://github.com/Byron/gitoxide/commit/c72eaa05697a3e34adaa3ee90584dce4b5c00120))
+ - Remove `TryInto` support from `gix_macros::momo` ([`95a1626`](https://github.com/Byron/gitoxide/commit/95a16264b0a6f8c7d8e2acded3a4c9c170c2729b))
+ - Add new crate `gix-macros` ([`6dae9e9`](https://github.com/Byron/gitoxide/commit/6dae9e9d455ba5e3bf18c452789d07ff6cfaf392))
+</details>
+
diff --git a/vendor/gix-macros/Cargo.toml b/vendor/gix-macros/Cargo.toml
new file mode 100644
index 000000000..4cefc9fd9
--- /dev/null
+++ b/vendor/gix-macros/Cargo.toml
@@ -0,0 +1,48 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.65"
+name = "gix-macros"
+version = "0.1.0"
+authors = [
+ "Jiahao XU <Jiahao_XU@outlook.com>",
+ "Andre Bogus <bogusandre@gmail.com>",
+ "Sebastian Thiel <sebastian.thiel@icloud.com>",
+]
+include = [
+ "src/**/*",
+ "LICENSE-*",
+ "CHANGELOG.md",
+]
+description = "Proc-macro utilities for gix"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/Byron/gitoxide"
+
+[lib]
+proc_macro = true
+
+[dependencies.proc-macro2]
+version = "1.0"
+
+[dependencies.quote]
+version = "1.0"
+
+[dependencies.syn]
+version = "2.0"
+features = [
+ "full",
+ "fold",
+]
+
+[dev-dependencies.trybuild]
+version = "1.0"
diff --git a/vendor/gix-macros/LICENSE-APACHE b/vendor/gix-macros/LICENSE-APACHE
new file mode 100644
index 000000000..a51f59a06
--- /dev/null
+++ b/vendor/gix-macros/LICENSE-APACHE
@@ -0,0 +1,191 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ Copyright 2018-2021 Sebastian Thiel, and [contributors](https://github.com/byron/gitoxide/contributors)
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/gix-macros/LICENSE-MIT b/vendor/gix-macros/LICENSE-MIT
new file mode 100644
index 000000000..b58e818f1
--- /dev/null
+++ b/vendor/gix-macros/LICENSE-MIT
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018-2021 Sebastian Thiel, and [contributors](https://github.com/byron/gitoxide/contributors).
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/gix-macros/src/lib.rs b/vendor/gix-macros/src/lib.rs
new file mode 100644
index 000000000..4693a79e8
--- /dev/null
+++ b/vendor/gix-macros/src/lib.rs
@@ -0,0 +1,25 @@
+//! A crate of useful macros used in `gix` primarily.
+//!
+//! Note that within `gix-*` crates, monomorphization should never be used for convenience, but only for performance
+//! reasons. And in the latter case, manual denomophization should be considered if the trait in questions isn't called
+//! often enough or measurements indicate that `&dyn Trait` is increasing the runtime. Thus, `gix-*` crates should probably
+//! by default prefer using `&dyn` unless measurements indicate otherwise.
+use proc_macro::TokenStream;
+
+/// When applied to functions or methods, it will turn it into a wrapper that will immediately call
+/// a de-monomorphized implementation (i.e. one that uses `&dyn Trait`).
+///
+/// That way, the landing-pads for convenience will be as small as possible which then delegate to a single
+/// function or method for implementation.
+///
+/// The parameters using the following traits can be de-monomorphized:
+///
+/// * `Into`
+/// * `AsRef`
+/// * `AsMut`
+#[proc_macro_attribute]
+pub fn momo(_attrs: TokenStream, input: TokenStream) -> TokenStream {
+ momo::inner(input.into()).into()
+}
+
+mod momo;
diff --git a/vendor/gix-macros/src/momo.rs b/vendor/gix-macros/src/momo.rs
new file mode 100644
index 000000000..802f4b5b0
--- /dev/null
+++ b/vendor/gix-macros/src/momo.rs
@@ -0,0 +1,300 @@
+use std::collections::HashMap;
+
+use quote::quote;
+use syn::{punctuated::Punctuated, spanned::Spanned, *};
+
+pub(crate) fn inner(code: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
+ let fn_item: Item = match syn::parse2(code.clone()) {
+ Ok(input) => input,
+ Err(err) => return err.to_compile_error(),
+ };
+
+ if let Item::Fn(item_fn) = fn_item {
+ let ty_conversions = parse_generics(&item_fn.sig);
+ let (has_conversion_in_effect, argtypes, argexprs, has_self) = convert(&item_fn.sig.inputs, &ty_conversions);
+ if !has_conversion_in_effect {
+ return Error::new(
+ item_fn.span(),
+ "Couldn't apply a single conversion - momo is ineffective here",
+ )
+ .to_compile_error();
+ }
+
+ let uses_self = has_self
+ || item_fn.sig.inputs.iter().any(has_self_type)
+ || matches!(&item_fn.sig.output, ReturnType::Type(_, ty) if contains_self_type(ty));
+
+ let inner_ident = Ident::new(
+ // Use long qualifier to avoid name collision.
+ &format!("_{}_inner_generated_by_gix_macro_momo", item_fn.sig.ident),
+ proc_macro2::Span::call_site(),
+ );
+
+ let outer_sig = Signature {
+ inputs: argtypes,
+ ..item_fn.sig.clone()
+ };
+
+ let new_inner_item = Item::Fn(ItemFn {
+ // Remove doc comment since they will increase compile-time and
+ // also generates duplicate warning/error messages for the doc,
+ // especially if it contains doc-tests.
+ attrs: {
+ let mut attrs = item_fn.attrs.clone();
+ attrs.retain(|attr| {
+ let segments = &attr.path().segments;
+ !(segments.len() == 1 && segments[0].ident == "doc")
+ });
+ attrs
+ },
+ vis: Visibility::Inherited,
+ sig: Signature {
+ ident: inner_ident.clone(),
+ ..item_fn.sig
+ },
+ block: item_fn.block,
+ });
+
+ if uses_self {
+ // We can use `self` or `Self` inside function defined within
+ // the impl-fn, so instead declare two separate functions.
+ //
+ // Since it's an impl block, it's unlikely to have name conflict,
+ // though this won't work for impl-trait.
+ //
+ // This approach also make sure we can call the right function
+ // using `Self` qualifier.
+ let new_item = Item::Fn(ItemFn {
+ attrs: item_fn.attrs,
+ vis: item_fn.vis,
+ sig: outer_sig,
+ block: if has_self {
+ parse_quote!({ self.#inner_ident(#argexprs) })
+ } else {
+ parse_quote!({ Self::#inner_ident(#argexprs) })
+ },
+ });
+ quote!(#new_item #new_inner_item)
+ } else {
+ // Put the new inner function within the function block
+ // to avoid duplicate function name and support associated
+ // function that doesn't use `self` or `Self`.
+ let new_item = Item::Fn(ItemFn {
+ attrs: item_fn.attrs,
+ vis: item_fn.vis,
+ sig: outer_sig,
+ block: parse_quote!({
+ #new_inner_item
+
+ #inner_ident(#argexprs)
+ }),
+ });
+ quote!(#new_item)
+ }
+ } else {
+ Error::new(fn_item.span(), "expect a function").to_compile_error()
+ }
+}
+
+#[derive(Copy, Clone)]
+// All conversions we support. Check references to this type for an idea how to add more.
+enum Conversion<'a> {
+ Into(&'a Type),
+ AsRef(&'a Type),
+ AsMut(&'a Type),
+}
+
+impl<'a> Conversion<'a> {
+ fn conversion_expr(&self, i: &Ident) -> Expr {
+ match *self {
+ Conversion::Into(_) => parse_quote!(#i.into()),
+ Conversion::AsRef(_) => parse_quote!(#i.as_ref()),
+ Conversion::AsMut(_) => parse_quote!(#i.as_mut()),
+ }
+ }
+}
+
+fn parse_bounded_type(ty: &Type) -> Option<Ident> {
+ match &ty {
+ Type::Path(TypePath { qself: None, path }) if path.segments.len() == 1 => Some(path.segments[0].ident.clone()),
+ _ => None,
+ }
+}
+
+fn parse_bounds(bounds: &Punctuated<TypeParamBound, Token![+]>) -> Option<Conversion> {
+ if bounds.len() != 1 {
+ return None;
+ }
+ if let TypeParamBound::Trait(ref tb) = bounds.first().unwrap() {
+ if let Some(seg) = tb.path.segments.iter().last() {
+ if let PathArguments::AngleBracketed(ref gen_args) = seg.arguments {
+ if let GenericArgument::Type(ref arg_ty) = gen_args.args.first().unwrap() {
+ if seg.ident == "Into" {
+ return Some(Conversion::Into(arg_ty));
+ } else if seg.ident == "AsRef" {
+ return Some(Conversion::AsRef(arg_ty));
+ } else if seg.ident == "AsMut" {
+ return Some(Conversion::AsMut(arg_ty));
+ }
+ }
+ }
+ }
+ }
+ None
+}
+
+// create a map from generic type to Conversion
+fn parse_generics(decl: &Signature) -> HashMap<Ident, Conversion<'_>> {
+ let mut ty_conversions = HashMap::new();
+ for gp in decl.generics.params.iter() {
+ if let GenericParam::Type(ref tp) = gp {
+ if let Some(conversion) = parse_bounds(&tp.bounds) {
+ ty_conversions.insert(tp.ident.clone(), conversion);
+ }
+ }
+ }
+ if let Some(ref wc) = decl.generics.where_clause {
+ for wp in wc.predicates.iter() {
+ if let WherePredicate::Type(ref pt) = wp {
+ if let Some(ident) = parse_bounded_type(&pt.bounded_ty) {
+ if let Some(conversion) = parse_bounds(&pt.bounds) {
+ ty_conversions.insert(ident, conversion);
+ }
+ }
+ }
+ }
+ }
+ ty_conversions
+}
+
+fn convert<'a>(
+ inputs: &'a Punctuated<FnArg, Token![,]>,
+ ty_conversions: &HashMap<Ident, Conversion<'a>>,
+) -> (bool, Punctuated<FnArg, Token![,]>, Punctuated<Expr, Token![,]>, bool) {
+ let mut has_conversion_in_effect = false;
+ let mut argtypes = Punctuated::new();
+ let mut argexprs = Punctuated::new();
+ let mut has_self = false;
+ inputs.iter().enumerate().for_each(|(i, input)| match input.clone() {
+ FnArg::Receiver(receiver) => {
+ has_self = true;
+ argtypes.push(FnArg::Receiver(receiver));
+ }
+ FnArg::Typed(mut pat_type) => {
+ let pat_ident = match &mut *pat_type.pat {
+ Pat::Ident(pat_ident) if pat_ident.by_ref.is_none() && pat_ident.subpat.is_none() => pat_ident,
+ _ => {
+ pat_type.pat = Box::new(Pat::Ident(PatIdent {
+ ident: Ident::new(&format!("arg_{i}_gen_by_momo_"), proc_macro2::Span::call_site()),
+ attrs: Default::default(),
+ by_ref: None,
+ mutability: None,
+ subpat: None,
+ }));
+
+ if let Pat::Ident(pat_ident) = &mut *pat_type.pat {
+ pat_ident
+ } else {
+ panic!()
+ }
+ }
+ };
+ // Outer function type argument pat does not need mut unless its
+ // type is `impl AsMut`.
+ pat_ident.mutability = None;
+
+ let ident = &pat_ident.ident;
+
+ let to_expr = || parse_quote!(#ident);
+
+ match *pat_type.ty {
+ Type::ImplTrait(TypeImplTrait { ref bounds, .. }) => {
+ if let Some(conv) = parse_bounds(bounds) {
+ has_conversion_in_effect = true;
+ argexprs.push(conv.conversion_expr(ident));
+ if let Conversion::AsMut(_) = conv {
+ pat_ident.mutability = Some(Default::default());
+ }
+ } else {
+ argexprs.push(to_expr());
+ }
+ }
+ Type::Path(..) => {
+ if let Some(conv) = parse_bounded_type(&pat_type.ty).and_then(|ident| ty_conversions.get(&ident)) {
+ has_conversion_in_effect = true;
+ argexprs.push(conv.conversion_expr(ident));
+ if let Conversion::AsMut(_) = conv {
+ pat_ident.mutability = Some(Default::default());
+ }
+ } else {
+ argexprs.push(to_expr());
+ }
+ }
+ _ => {
+ argexprs.push(to_expr());
+ }
+ }
+
+ // Now that mutability is decided, push the type into argtypes
+ argtypes.push(FnArg::Typed(pat_type));
+ }
+ });
+ (has_conversion_in_effect, argtypes, argexprs, has_self)
+}
+
+fn contains_self_type_path(path: &Path) -> bool {
+ path.segments.iter().any(|segment| {
+ segment.ident == "Self"
+ || match &segment.arguments {
+ PathArguments::AngleBracketed(AngleBracketedGenericArguments { args, .. }) => {
+ args.iter().any(|generic_arg| match generic_arg {
+ GenericArgument::Type(ty) => contains_self_type(ty),
+ GenericArgument::Const(expr) => contains_self_type_expr(expr),
+ _ => false,
+ })
+ }
+ PathArguments::Parenthesized(ParenthesizedGenericArguments { inputs, output, .. }) => {
+ inputs.iter().any(contains_self_type)
+ || matches!(output, ReturnType::Type(_, ty) if contains_self_type(ty))
+ }
+ _ => false,
+ }
+ })
+}
+
+fn contains_self_type_expr(expr: &Expr) -> bool {
+ match expr {
+ Expr::Path(ExprPath { qself: Some(_), .. }) => true,
+ Expr::Path(ExprPath { path, .. }) => contains_self_type_path(path),
+ _ => false,
+ }
+}
+
+fn contains_self_type(input: &Type) -> bool {
+ match input {
+ Type::Array(TypeArray { elem, len, .. }) => {
+ // Call `matches!` first so that we can do tail call here
+ // as an optimization.
+ contains_self_type_expr(len) || contains_self_type(elem)
+ }
+ Type::Group(TypeGroup { elem, .. }) => contains_self_type(elem),
+ Type::Paren(TypeParen { elem, .. }) => contains_self_type(elem),
+ Type::Ptr(TypePtr { elem, .. }) => contains_self_type(elem),
+ Type::Reference(TypeReference { elem, .. }) => contains_self_type(elem),
+ Type::Slice(TypeSlice { elem, .. }) => contains_self_type(elem),
+
+ Type::Tuple(TypeTuple { elems, .. }) => elems.iter().any(contains_self_type),
+
+ Type::Path(TypePath { qself: Some(_), .. }) => true,
+ Type::Path(TypePath { path, .. }) => contains_self_type_path(path),
+
+ _ => false,
+ }
+}
+
+fn has_self_type(input: &FnArg) -> bool {
+ match input {
+ FnArg::Receiver(_) => true,
+ FnArg::Typed(PatType { ty, .. }) => contains_self_type(ty),
+ }
+}