summaryrefslogtreecommitdiffstats
path: root/vendor/zerofrom-derive
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:32 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:32 +0000
commit4547b622d8d29df964fa2914213088b148c498fc (patch)
tree9fc6b25f3c3add6b745be9a2400a6e96140046e9 /vendor/zerofrom-derive
parentReleasing progress-linux version 1.66.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-4547b622d8d29df964fa2914213088b148c498fc.tar.xz
rustc-4547b622d8d29df964fa2914213088b148c498fc.zip
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/zerofrom-derive')
-rw-r--r--vendor/zerofrom-derive/.cargo-checksum.json1
-rw-r--r--vendor/zerofrom-derive/Cargo.lock122
-rw-r--r--vendor/zerofrom-derive/Cargo.toml60
-rw-r--r--vendor/zerofrom-derive/LICENSE51
-rw-r--r--vendor/zerofrom-derive/README.md7
-rw-r--r--vendor/zerofrom-derive/examples/zf_derive.rs91
-rw-r--r--vendor/zerofrom-derive/src/lib.rs175
-rw-r--r--vendor/zerofrom-derive/src/visitor.rs114
8 files changed, 621 insertions, 0 deletions
diff --git a/vendor/zerofrom-derive/.cargo-checksum.json b/vendor/zerofrom-derive/.cargo-checksum.json
new file mode 100644
index 000000000..b2c225988
--- /dev/null
+++ b/vendor/zerofrom-derive/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"518b7b3432c0807e6ae3f3220676b5ff9500e7a48f8145e38e36ad8941dd3d12","Cargo.toml":"45eacd80b97736ce0d6d29269194b7beff53b4c14220eb8cad66715218561335","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"11a51a5a18692b4ba67b60b556c06cce8b0c81a0c7dd82f818893207840fb052","examples/zf_derive.rs":"d8d6aac643e8edd1cdebafdff1e32dfefab7c887a762f75f55dc19f5d7404338","src/lib.rs":"cd26afbef8efcc9faf232802d7af417bd7b97fe2ebe8f06cd04a6b920ec76e2f","src/visitor.rs":"644492b09434a35d715f4d32c72db3184a9c05f26177d7492e816f063b25663c"},"package":"2e8aa86add9ddbd2409c1ed01e033cd457d79b1b1229b64922c25095c595e829"} \ No newline at end of file
diff --git a/vendor/zerofrom-derive/Cargo.lock b/vendor/zerofrom-derive/Cargo.lock
new file mode 100644
index 000000000..6e6667eae
--- /dev/null
+++ b/vendor/zerofrom-derive/Cargo.lock
@@ -0,0 +1,122 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.47"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.145"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "syn"
+version = "1.0.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.12.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
+[[package]]
+name = "yoke"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fe1d55ca72c32d573bfbd5cb2f0ca65a497854c44762957a6d3da96041a5184"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "zerofrom",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79e9355fccf72b04b7deaa99ce7a0f6630530acf34045391b74460fcd714de54"
+dependencies = [
+ "zerofrom-derive 0.1.0",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8785f47d6062c1932866147f91297286a9f350b3070e9d9f0b6078e37d623c1a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "zerovec"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9d919a74c17749ccb17beaf6405562e413cd94e98ba52ca1e64bbe7eefbd8b8"
+dependencies = [
+ "yoke",
+ "zerofrom",
+]
diff --git a/vendor/zerofrom-derive/Cargo.toml b/vendor/zerofrom-derive/Cargo.toml
new file mode 100644
index 000000000..3966434c6
--- /dev/null
+++ b/vendor/zerofrom-derive/Cargo.toml
@@ -0,0 +1,60 @@
+# 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 = "2018"
+name = "zerofrom-derive"
+version = "0.1.1"
+authors = ["Manish Goregaokar <manishsmail@gmail.com>"]
+description = "Custom derive for the zerofrom crate"
+keywords = [
+ "zerocopy",
+ "serialization",
+ "lifetime",
+ "borrow",
+]
+categories = [
+ "data-structures",
+ "memory-management",
+ "caching",
+ "no-std",
+]
+license = "Unicode-DFS-2016"
+repository = "https://github.com/unicode-org/icu4x"
+resolver = "2"
+
+[lib]
+path = "src/lib.rs"
+proc_macro = true
+
+[dependencies.proc-macro2]
+version = "1.0.27"
+
+[dependencies.quote]
+version = "1.0.9"
+
+[dependencies.syn]
+version = "1.0.73"
+features = [
+ "derive",
+ "fold",
+]
+
+[dependencies.synstructure]
+version = "0.12.4"
+
+[dev-dependencies.zerofrom]
+version = "0.1"
+features = ["derive"]
+
+[dev-dependencies.zerovec]
+version = "0.9"
+features = ["yoke"]
diff --git a/vendor/zerofrom-derive/LICENSE b/vendor/zerofrom-derive/LICENSE
new file mode 100644
index 000000000..9858d01ab
--- /dev/null
+++ b/vendor/zerofrom-derive/LICENSE
@@ -0,0 +1,51 @@
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+
+See Terms of Use <https://www.unicode.org/copyright.html>
+for definitions of Unicode Inc.’s Data Files and Software.
+
+NOTICE TO USER: Carefully read the following legal agreement.
+BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
+DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
+YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
+TERMS AND CONDITIONS OF THIS AGREEMENT.
+IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
+THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2022 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation
+(the "Data Files") or Unicode software and any associated documentation
+(the "Software") to deal in the Data Files or Software
+without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, and/or sell copies of
+the Data Files or Software, and to permit persons to whom the Data Files
+or Software are furnished to do so, provided that either
+(a) this copyright and permission notice appear with all copies
+of the Data Files or Software, or
+(b) this copyright and permission notice appear in associated
+Documentation.
+
+THE DATA FILES AND SOFTWARE ARE 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 OF THIRD PARTY RIGHTS.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
+NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
+
+—
+
+Portions of ICU4X may have been adapted from ICU4C and/or ICU4J.
+ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation and others.
diff --git a/vendor/zerofrom-derive/README.md b/vendor/zerofrom-derive/README.md
new file mode 100644
index 000000000..28e1a3a77
--- /dev/null
+++ b/vendor/zerofrom-derive/README.md
@@ -0,0 +1,7 @@
+# zerofrom-derive [![crates.io](https://img.shields.io/crates/v/zerofrom-derive)](https://crates.io/crates/zerofrom-derive)
+
+Custom derives for `ZeroFrom` from the `zerofrom` crate.
+
+## More Information
+
+For more information on development, authorship, contributing etc. please visit [`ICU4X home page`](https://github.com/unicode-org/icu4x).
diff --git a/vendor/zerofrom-derive/examples/zf_derive.rs b/vendor/zerofrom-derive/examples/zf_derive.rs
new file mode 100644
index 000000000..2df26d943
--- /dev/null
+++ b/vendor/zerofrom-derive/examples/zf_derive.rs
@@ -0,0 +1,91 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+#![allow(unused)]
+
+use std::borrow::Cow;
+use zerofrom::ZeroFrom;
+use zerovec::{maps::ZeroMapKV, ule::AsULE, VarZeroVec, ZeroMap, ZeroVec};
+
+#[derive(ZeroFrom, Copy, Clone)]
+pub struct IntExample {
+ x: u32,
+}
+
+#[derive(ZeroFrom, Copy, Clone)]
+pub struct GenericsExample<T> {
+ x: u32,
+ y: T,
+}
+
+#[derive(ZeroFrom, Copy, Clone)]
+pub struct GenericsExampleWithDefault<T, U = usize> {
+ x: T,
+ y: U,
+}
+
+#[derive(ZeroFrom)]
+pub struct CowExample<'a> {
+ x: u8,
+ y: &'a str,
+ z: Cow<'a, str>,
+ w: Cow<'a, [u8]>,
+}
+
+#[derive(ZeroFrom)]
+pub struct ZeroVecExample<'a> {
+ var: VarZeroVec<'a, str>,
+ vec: ZeroVec<'a, u16>,
+}
+
+#[derive(ZeroFrom)]
+pub struct ZeroVecExampleWithGenerics<'a, T: AsULE> {
+ gen: ZeroVec<'a, T>,
+ vec: ZeroVec<'a, u16>,
+ bare: T,
+}
+
+#[derive(ZeroFrom)]
+pub struct HasTuples<'data> {
+ pub bar: (&'data str, &'data str),
+}
+
+pub fn assert_zf_tuples<'b, 'data>(x: &'b HasTuples<'data>) -> HasTuples<'b> {
+ HasTuples::zero_from(x)
+}
+pub fn assert_zf_generics<'a, 'b>(
+ x: &'b ZeroVecExampleWithGenerics<'a, u8>,
+) -> ZeroVecExampleWithGenerics<'b, u8> {
+ ZeroVecExampleWithGenerics::<'b, u8>::zero_from(x)
+}
+
+#[derive(ZeroFrom)]
+pub struct ZeroMapGenericExample<'a, T: for<'b> ZeroMapKV<'b> + ?Sized> {
+ map: ZeroMap<'a, str, T>,
+}
+
+pub fn assert_zf_map<'a, 'b>(
+ x: &'b ZeroMapGenericExample<'a, str>,
+) -> ZeroMapGenericExample<'b, str> {
+ ZeroMapGenericExample::zero_from(x)
+}
+
+#[derive(Clone, ZeroFrom)]
+pub struct CloningZF1 {
+ #[zerofrom(clone)] // Vec is not ZeroFrom, so it needs to be cloned
+ vec: Vec<u8>,
+}
+
+#[derive(Clone, ZeroFrom)]
+pub struct CloningZF2<'data> {
+ #[zerofrom(clone)] // Cow is ZeroFrom, but we force a clone
+ cow: Cow<'data, str>,
+}
+
+#[derive(ZeroFrom)]
+pub enum CloningZF3<'data> {
+ Cow(#[zerofrom(clone)] Cow<'data, str>),
+}
+
+fn main() {}
diff --git a/vendor/zerofrom-derive/src/lib.rs b/vendor/zerofrom-derive/src/lib.rs
new file mode 100644
index 000000000..63fd58aae
--- /dev/null
+++ b/vendor/zerofrom-derive/src/lib.rs
@@ -0,0 +1,175 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+//! Custom derives for `ZeroFrom` from the `zerofrom` crate.
+
+// https://github.com/unicode-org/icu4x/blob/main/docs/process/boilerplate.md#library-annotations
+#![cfg_attr(
+ not(test),
+ deny(
+ clippy::indexing_slicing,
+ clippy::unwrap_used,
+ clippy::expect_used,
+ clippy::panic,
+ clippy::exhaustive_structs,
+ clippy::exhaustive_enums,
+ missing_debug_implementations,
+ )
+)]
+
+use proc_macro::TokenStream;
+use proc_macro2::{Span, TokenStream as TokenStream2};
+use quote::quote;
+use syn::spanned::Spanned;
+use syn::{parse_macro_input, parse_quote, DeriveInput, Ident, Lifetime, Type, WherePredicate};
+use synstructure::Structure;
+
+mod visitor;
+
+/// Custom derive for `zerofrom::ZeroFrom`,
+///
+/// This implements `ZeroFrom<Ty> for Ty` for types
+/// without a lifetime parameter, and `ZeroFrom<Ty<'data>> for Ty<'static>`
+/// for types with a lifetime parameter.
+///
+/// Apply the `#[zerofrom(clone)]` attribute to a field if it doesn't implement
+/// Copy or ZeroFrom; this data will be cloned when the struct is zero_from'ed.
+#[proc_macro_derive(ZeroFrom, attributes(zerofrom))]
+pub fn zf_derive(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+ TokenStream::from(zf_derive_impl(&input))
+}
+
+fn has_clone_attr(attrs: &[syn::Attribute]) -> bool {
+ attrs.iter().any(|a| {
+ if let Ok(i) = a.parse_args::<Ident>() {
+ if i == "clone" {
+ return true;
+ }
+ }
+ false
+ })
+}
+
+fn zf_derive_impl(input: &DeriveInput) -> TokenStream2 {
+ let tybounds = input
+ .generics
+ .type_params()
+ .map(|ty| {
+ // Strip out param defaults, we don't need them in the impl
+ let mut ty = ty.clone();
+ ty.eq_token = None;
+ ty.default = None;
+ ty
+ })
+ .collect::<Vec<_>>();
+ let typarams = tybounds
+ .iter()
+ .map(|ty| ty.ident.clone())
+ .collect::<Vec<_>>();
+ let lts = input.generics.lifetimes().count();
+ let name = &input.ident;
+ let structure = Structure::new(input);
+
+ if lts == 0 {
+ let has_clone = structure
+ .variants()
+ .iter()
+ .flat_map(|variant| variant.bindings().iter())
+ .any(|binding| has_clone_attr(&binding.ast().attrs));
+ let (clone, clone_trait) = if has_clone {
+ (quote!(this.clone()), quote!(Clone))
+ } else {
+ (quote!(*this), quote!(Copy))
+ };
+ let bounds: Vec<WherePredicate> = typarams
+ .iter()
+ .map(|ty| parse_quote!(#ty: #clone_trait + 'static))
+ .collect();
+ quote! {
+ impl<'zf, #(#tybounds),*> zerofrom::ZeroFrom<'zf, #name<#(#typarams),*>> for #name<#(#typarams),*> where #(#bounds),* {
+ fn zero_from(this: &'zf Self) -> Self {
+ #clone
+ }
+ }
+ }
+ } else {
+ if lts != 1 {
+ return syn::Error::new(
+ input.generics.span(),
+ "derive(ZeroFrom) cannot have multiple lifetime parameters",
+ )
+ .to_compile_error();
+ }
+
+ let generics_env = typarams.iter().cloned().collect();
+
+ let mut zf_bounds: Vec<WherePredicate> = vec![];
+ let body = structure.each_variant(|vi| {
+ vi.construct(|f, i| {
+ let binding = format!("__binding_{}", i);
+ let field = Ident::new(&binding, Span::call_site());
+
+ if has_clone_attr(&f.attrs) {
+ quote! {
+ #field.clone()
+ }
+ } else {
+ let fty = replace_lifetime(&f.ty, custom_lt("'zf"));
+ let lifetime_ty = replace_lifetime(&f.ty, custom_lt("'zf_inner"));
+
+ let (has_ty, has_lt) = visitor::check_type_for_parameters(&f.ty, &generics_env);
+ if has_ty {
+ // For types without type parameters, the compiler can figure out that the field implements
+ // ZeroFrom on its own. However, if there are type parameters, there may be complex preconditions
+ // to `FieldTy: ZeroFrom` that need to be satisfied. We get them to be satisfied by requiring
+ // `FieldTy<'zf>: ZeroFrom<'zf, FieldTy<'zf_inner>>`
+ if has_lt {
+ zf_bounds
+ .push(parse_quote!(#fty: zerofrom::ZeroFrom<'zf, #lifetime_ty>));
+ } else {
+ zf_bounds.push(parse_quote!(#fty: zerofrom::ZeroFrom<'zf, #fty>));
+ }
+ }
+ if has_ty || has_lt {
+ // By doing this we essentially require ZF to be implemented
+ // on all fields
+ quote! {
+ <#fty as zerofrom::ZeroFrom<'zf, #lifetime_ty>>::zero_from(#field)
+ }
+ } else {
+ // No lifetimes, so we can just copy
+ quote! { *#field }
+ }
+ }
+ })
+ });
+
+ quote! {
+ impl<'zf, 'zf_inner, #(#tybounds),*> zerofrom::ZeroFrom<'zf, #name<'zf_inner, #(#typarams),*>> for #name<'zf, #(#typarams),*>
+ where
+ #(#zf_bounds,)* {
+ fn zero_from(this: &'zf #name<'zf_inner, #(#typarams),*>) -> Self {
+ match *this { #body }
+ }
+ }
+ }
+ }
+}
+
+fn custom_lt(s: &str) -> Lifetime {
+ Lifetime::new(s, Span::call_site())
+}
+
+fn replace_lifetime(x: &Type, lt: Lifetime) -> Type {
+ use syn::fold::Fold;
+ struct ReplaceLifetime(Lifetime);
+
+ impl Fold for ReplaceLifetime {
+ fn fold_lifetime(&mut self, _: Lifetime) -> Lifetime {
+ self.0.clone()
+ }
+ }
+ ReplaceLifetime(lt).fold_type(x.clone())
+}
diff --git a/vendor/zerofrom-derive/src/visitor.rs b/vendor/zerofrom-derive/src/visitor.rs
new file mode 100644
index 000000000..ce65f7d6d
--- /dev/null
+++ b/vendor/zerofrom-derive/src/visitor.rs
@@ -0,0 +1,114 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+//! Visitor for determining whether a type has type and non-static lifetime parameters
+//! (duplicated in yoke/derive/src/visitor.rs)
+
+use std::collections::HashSet;
+use syn::visit::{visit_lifetime, visit_type, visit_type_path, Visit};
+use syn::{Ident, Lifetime, Type, TypePath};
+
+struct TypeVisitor<'a> {
+ /// The type parameters in scope
+ typarams: &'a HashSet<Ident>,
+ /// Whether we found a type parameter
+ found_typarams: bool,
+ /// Whether we found a non-'static lifetime parameter
+ found_lifetimes: bool,
+}
+
+impl<'a, 'ast> Visit<'ast> for TypeVisitor<'a> {
+ fn visit_lifetime(&mut self, lt: &'ast Lifetime) {
+ if lt.ident != "static" {
+ self.found_lifetimes = true;
+ }
+ visit_lifetime(self, lt)
+ }
+ fn visit_type_path(&mut self, ty: &'ast TypePath) {
+ // We only need to check ty.path.get_ident() and not ty.qself or any
+ // generics in ty.path because the visitor will eventually visit those
+ // types on its own
+ if let Some(ident) = ty.path.get_ident() {
+ if self.typarams.contains(ident) {
+ self.found_typarams = true;
+ }
+ }
+
+ visit_type_path(self, ty)
+ }
+}
+
+/// Checks if a type has type or lifetime parameters, given the local context of
+/// named type parameters. Returns (has_type_params, has_lifetime_params)
+pub fn check_type_for_parameters(ty: &Type, typarams: &HashSet<Ident>) -> (bool, bool) {
+ let mut visit = TypeVisitor {
+ typarams,
+ found_typarams: false,
+ found_lifetimes: false,
+ };
+ visit_type(&mut visit, ty);
+
+ (visit.found_typarams, visit.found_lifetimes)
+}
+
+#[cfg(test)]
+mod tests {
+ use proc_macro2::Span;
+ use std::collections::HashSet;
+ use syn::{parse_quote, Ident};
+
+ use super::check_type_for_parameters;
+ fn make_typarams(params: &[&str]) -> HashSet<Ident> {
+ params
+ .iter()
+ .map(|x| Ident::new(x, Span::call_site()))
+ .collect()
+ }
+
+ #[test]
+ fn test_simple_type() {
+ let environment = make_typarams(&["T", "U", "V"]);
+
+ let ty = parse_quote!(Foo<'a, T>);
+ let check = check_type_for_parameters(&ty, &environment);
+ assert_eq!(check, (true, true));
+
+ let ty = parse_quote!(Foo<T>);
+ let check = check_type_for_parameters(&ty, &environment);
+ assert_eq!(check, (true, false));
+
+ let ty = parse_quote!(Foo<'static, T>);
+ let check = check_type_for_parameters(&ty, &environment);
+ assert_eq!(check, (true, false));
+
+ let ty = parse_quote!(Foo<'a>);
+ let check = check_type_for_parameters(&ty, &environment);
+ assert_eq!(check, (false, true));
+
+ let ty = parse_quote!(Foo<'a, Bar<U>, Baz<(V, u8)>>);
+ let check = check_type_for_parameters(&ty, &environment);
+ assert_eq!(check, (true, true));
+
+ let ty = parse_quote!(Foo<'a, W>);
+ let check = check_type_for_parameters(&ty, &environment);
+ assert_eq!(check, (false, true));
+ }
+
+ #[test]
+ fn test_assoc_types() {
+ let environment = make_typarams(&["T"]);
+
+ let ty = parse_quote!(<Foo as SomeTrait<'a, T>>::Output);
+ let check = check_type_for_parameters(&ty, &environment);
+ assert_eq!(check, (true, true));
+
+ let ty = parse_quote!(<Foo as SomeTrait<'static, T>>::Output);
+ let check = check_type_for_parameters(&ty, &environment);
+ assert_eq!(check, (true, false));
+
+ let ty = parse_quote!(<T as SomeTrait<'static, Foo>>::Output);
+ let check = check_type_for_parameters(&ty, &environment);
+ assert_eq!(check, (true, false));
+ }
+}