diff --git a/validator_derive/src/lib.rs b/validator_derive/src/lib.rs index 44a896e2..58bda3b8 100644 --- a/validator_derive/src/lib.rs +++ b/validator_derive/src/lib.rs @@ -211,7 +211,7 @@ impl ToTokens for ValidateField { let nested = if let Some(n) = self.nested { if n { - wrapper_closure(nested_tokens(&actual_field, &field_name_str)) + wrapper_closure(nested_tokens(&actual_field, &field_name_str, &self.crate_name)) } else { quote!() } diff --git a/validator_derive/src/tokens/nested.rs b/validator_derive/src/tokens/nested.rs index f4840e4c..2f96bed8 100644 --- a/validator_derive/src/tokens/nested.rs +++ b/validator_derive/src/tokens/nested.rs @@ -1,11 +1,15 @@ use quote::quote; +use crate::CrateName; + pub fn nested_tokens( field_name: &proc_macro2::TokenStream, field_name_str: &str, + crate_name: &CrateName, ) -> proc_macro2::TokenStream { quote! { if let std::collections::hash_map::Entry::Vacant(entry) = errors.0.entry(::std::borrow::Cow::Borrowed(#field_name_str)) { + use #crate_name::Validate; errors.merge_self(#field_name_str, (&#field_name).validate()); } } diff --git a/validator_derive_tests/tests/nested.rs b/validator_derive_tests/tests/nested.rs index 96ddd2c0..98cfc4b4 100644 --- a/validator_derive_tests/tests/nested.rs +++ b/validator_derive_tests/tests/nested.rs @@ -910,3 +910,30 @@ where let errors = errors.clone(); f(errors.errors().clone()); } + +/// Sometimes users may want to use absolute path on struct, and validate in other module +pub mod test_nest_field_with_absolute_path { + #[derive(validator::Validate)] + struct Parent { + #[validate(nested)] + child: Child, + #[validate(nested)] + child2: Child, + } + + #[derive(validator::Validate)] + struct Child { + #[validate(length(min = 1))] + value: String, + } + + #[test] + fn test() { + use validator::Validate; + let instance = Parent { + child: Child { value: String::from("1") }, + child2: Child { value: String::from("2") }, + }; + assert!(instance.validate().is_ok()); + } +}