diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/rust/zerofrom-derive/src/visitor.rs | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/zerofrom-derive/src/visitor.rs')
-rw-r--r-- | third_party/rust/zerofrom-derive/src/visitor.rs | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/third_party/rust/zerofrom-derive/src/visitor.rs b/third_party/rust/zerofrom-derive/src/visitor.rs new file mode 100644 index 0000000000..4204b7c68d --- /dev/null +++ b/third_party/rust/zerofrom-derive/src/visitor.rs @@ -0,0 +1,120 @@ +// 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::HashMap; +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 HashMap<Ident, Option<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 let Some(maybe_borrowed) = self.typarams.get(ident) { + self.found_typarams = true; + if maybe_borrowed.is_some() { + self.found_lifetimes = 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: &HashMap<Ident, Option<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::HashMap; + use syn::{parse_quote, Ident}; + + use super::check_type_for_parameters; + fn make_typarams(params: &[&str]) -> HashMap<Ident, Option<Ident>> { + params + .iter() + .map(|x| (Ident::new(x, Span::call_site()), None)) + .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)); + } +} |