1
1
use cfg_if:: cfg_if;
2
2
use proc_macro2:: TokenStream ;
3
3
use quote:: { format_ident, quote} ;
4
+ use syn:: Generics ;
4
5
5
- use crate :: common:: models:: { ErrorTypeName , InnerType , ParseErrorTypeName , TypeName } ;
6
+ use crate :: common:: {
7
+ gen:: { add_bound_to_all_type_params, strip_trait_bounds_on_generics} ,
8
+ models:: { ErrorTypeName , InnerType , ParseErrorTypeName , TypeName } ,
9
+ } ;
6
10
7
11
/// Generate a name for the error which is used for FromStr trait implementation.
8
12
pub fn gen_parse_error_name ( type_name : & TypeName ) -> ParseErrorTypeName {
@@ -13,26 +17,33 @@ pub fn gen_parse_error_name(type_name: &TypeName) -> ParseErrorTypeName {
13
17
/// Generate an error which is used for FromStr trait implementation of non-string types (e.g.
14
18
/// floats or integers)
15
19
pub fn gen_def_parse_error (
16
- inner_type : impl Into < InnerType > ,
17
20
type_name : & TypeName ,
21
+ generics : & Generics ,
22
+ inner_type : impl Into < InnerType > ,
18
23
maybe_error_type_name : Option < & ErrorTypeName > ,
19
24
parse_error_type_name : & ParseErrorTypeName ,
20
25
) -> TokenStream {
21
26
let inner_type: InnerType = inner_type. into ( ) ;
22
27
let type_name_str = type_name. to_string ( ) ;
23
28
29
+ let generics_without_bounds = strip_trait_bounds_on_generics ( generics) ;
30
+ let generics_with_fromstr_bound = add_bound_to_all_type_params (
31
+ & generics_without_bounds,
32
+ syn:: parse_quote!( :: core:: str :: FromStr <Err : :: core:: fmt:: Debug >) ,
33
+ ) ;
34
+
24
35
let definition = if let Some ( error_type_name) = maybe_error_type_name {
25
36
quote ! {
26
- #[ derive( Debug ) ]
27
- pub enum #parse_error_type_name {
28
- Parse ( <#inner_type as :: core:: str :: FromStr >:: Err ) ,
29
- Validate ( #error_type_name) ,
30
- }
37
+ #[ derive( Debug ) ] // #[derive(Debug)]
38
+ pub enum #parse_error_type_name #generics_with_fromstr_bound { // pub enum ParseErrorFoo<T: ::core::str::FromStr<Err: ::core::fmt::Debug>> {
39
+ Parse ( <#inner_type as :: core:: str :: FromStr >:: Err ) , // Parse(<Foo as ::core::str::FromStr>::Err),
40
+ Validate ( #error_type_name) , // Validate(ErrorFoo),
41
+ } // }
31
42
32
- impl :: core:: fmt:: Display for #parse_error_type_name {
43
+ impl #generics_with_fromstr_bound :: core:: fmt:: Display for #parse_error_type_name #generics_without_bounds {
33
44
fn fmt( & self , f: & mut :: core:: fmt:: Formatter <' _>) -> :: core:: fmt:: Result {
34
45
match self {
35
- #parse_error_type_name:: Parse ( err) => write!( f, "Failed to parse {}: {}" , #type_name_str, err) ,
46
+ #parse_error_type_name:: Parse ( err) => write!( f, "Failed to parse {}: {:? }" , #type_name_str, err) ,
36
47
#parse_error_type_name:: Validate ( err) => write!( f, "Failed to parse {}: {}" , #type_name_str, err) ,
37
48
}
38
49
@@ -41,15 +52,15 @@ pub fn gen_def_parse_error(
41
52
}
42
53
} else {
43
54
quote ! {
44
- #[ derive( Debug ) ]
45
- pub enum #parse_error_type_name {
46
- Parse ( <#inner_type as :: core:: str :: FromStr >:: Err ) ,
47
- }
55
+ #[ derive( Debug ) ] // #[derive(Debug)
56
+ pub enum #parse_error_type_name #generics_with_fromstr_bound { // pub enum ParseErrorFoo<T: ::core::str::FromStr<Err: ::core::fmt::Debug>> {
57
+ Parse ( <#inner_type as :: core:: str :: FromStr >:: Err ) , // Parse(<Foo as ::core::str::FromStr>::Err),
58
+ } // }
48
59
49
- impl :: core:: fmt:: Display for #parse_error_type_name {
60
+ impl #generics_with_fromstr_bound :: core:: fmt:: Display for #parse_error_type_name #generics_without_bounds {
50
61
fn fmt( & self , f: & mut :: core:: fmt:: Formatter <' _>) -> :: core:: fmt:: Result {
51
62
match self {
52
- #parse_error_type_name:: Parse ( err) => write!( f, "Failed to parse {}: {}" , #type_name_str, err) ,
63
+ #parse_error_type_name:: Parse ( err) => write!( f, "Failed to parse {}: {:? }" , #type_name_str, err) ,
53
64
}
54
65
}
55
66
}
@@ -58,8 +69,12 @@ pub fn gen_def_parse_error(
58
69
59
70
cfg_if ! {
60
71
if #[ cfg( feature = "std" ) ] {
72
+ let generics_with_fromstr_and_debug_bounds = add_bound_to_all_type_params(
73
+ & generics_with_fromstr_bound,
74
+ syn:: parse_quote!( :: core:: fmt:: Debug ) ,
75
+ ) ;
61
76
let impl_std_error = quote! {
62
- impl :: std:: error:: Error for #parse_error_type_name {
77
+ impl #generics_with_fromstr_and_debug_bounds :: std:: error:: Error for #parse_error_type_name #generics_without_bounds {
63
78
fn source( & self ) -> Option <& ( dyn :: std:: error:: Error + ' static ) > {
64
79
None
65
80
}
0 commit comments