@@ -38,51 +38,80 @@ fn parse_attributes(field: &syn::Field) -> Attributes {
38
38
attrs
39
39
}
40
40
41
+ pub ( crate ) fn hash_stable_derive ( s : synstructure:: Structure < ' _ > ) -> proc_macro2:: TokenStream {
42
+ hash_stable_derive_with_mode ( s, HashStableMode :: Normal )
43
+ }
44
+
41
45
pub ( crate ) fn hash_stable_generic_derive (
42
- mut s : synstructure:: Structure < ' _ > ,
46
+ s : synstructure:: Structure < ' _ > ,
43
47
) -> proc_macro2:: TokenStream {
44
- let generic: syn:: GenericParam = parse_quote ! ( __CTX) ;
45
- s. add_bounds ( synstructure:: AddBounds :: Generics ) ;
46
- s. add_impl_generic ( generic) ;
47
- s. add_where_predicate ( parse_quote ! { __CTX: crate :: HashStableContext } ) ;
48
+ hash_stable_derive_with_mode ( s, HashStableMode :: Generic )
49
+ }
48
50
49
- let discriminant = hash_stable_discriminant ( & mut s) ;
50
- let body = hash_stable_body ( & mut s) ;
51
+ pub ( crate ) fn hash_stable_no_context_derive (
52
+ s : synstructure:: Structure < ' _ > ,
53
+ ) -> proc_macro2:: TokenStream {
54
+ hash_stable_derive_with_mode ( s, HashStableMode :: NoContext )
55
+ }
51
56
52
- s. bound_impl (
53
- quote ! ( :: rustc_data_structures:: stable_hasher:: HashStable <__CTX>) ,
54
- quote ! {
55
- #[ inline]
56
- fn hash_stable(
57
- & self ,
58
- __hcx: & mut __CTX,
59
- __hasher: & mut :: rustc_data_structures:: stable_hasher:: StableHasher ) {
60
- #discriminant
61
- match * self { #body }
62
- }
63
- } ,
64
- )
57
+ enum HashStableMode {
58
+ // Use the query-system aware stable hashing context.
59
+ Normal ,
60
+ // Emit a generic implementation that uses a crate-local `StableHashingContext`
61
+ // trait, when the crate is upstream of `rustc_middle`.
62
+ Generic ,
63
+ // Emit a hash-stable implementation that takes no context,
64
+ // and emits per-field where clauses for (almost-)perfect derives.
65
+ NoContext ,
65
66
}
66
67
67
- pub ( crate ) fn hash_stable_derive ( mut s : synstructure:: Structure < ' _ > ) -> proc_macro2:: TokenStream {
68
- let generic: syn:: GenericParam = parse_quote ! ( ' __ctx) ;
69
- s. add_bounds ( synstructure:: AddBounds :: Generics ) ;
68
+ fn hash_stable_derive_with_mode (
69
+ mut s : synstructure:: Structure < ' _ > ,
70
+ mode : HashStableMode ,
71
+ ) -> proc_macro2:: TokenStream {
72
+ let generic: syn:: GenericParam = match mode {
73
+ HashStableMode :: Normal => parse_quote ! ( ' __ctx) ,
74
+ HashStableMode :: Generic | HashStableMode :: NoContext => parse_quote ! ( __CTX) ,
75
+ } ;
76
+
77
+ // no_context impl is able to derive by-field, which is closer to a perfect derive.
78
+ s. add_bounds ( match mode {
79
+ HashStableMode :: Normal | HashStableMode :: Generic => synstructure:: AddBounds :: Generics ,
80
+ HashStableMode :: NoContext => synstructure:: AddBounds :: Fields ,
81
+ } ) ;
82
+
83
+ // For generic impl, add `where __CTX: HashStableContext`.
84
+ match mode {
85
+ HashStableMode :: Normal => { }
86
+ HashStableMode :: Generic => {
87
+ s. add_where_predicate ( parse_quote ! { __CTX: crate :: HashStableContext } ) ;
88
+ }
89
+ HashStableMode :: NoContext => { }
90
+ }
91
+
70
92
s. add_impl_generic ( generic) ;
71
93
72
94
let discriminant = hash_stable_discriminant ( & mut s) ;
73
95
let body = hash_stable_body ( & mut s) ;
74
96
97
+ let context: syn:: Type = match mode {
98
+ HashStableMode :: Normal => {
99
+ parse_quote ! ( :: rustc_query_system:: ich:: StableHashingContext <' __ctx>)
100
+ }
101
+ HashStableMode :: Generic | HashStableMode :: NoContext => parse_quote ! ( __CTX) ,
102
+ } ;
103
+
75
104
s. bound_impl (
76
105
quote ! (
77
106
:: rustc_data_structures:: stable_hasher:: HashStable <
78
- :: rustc_query_system :: ich :: StableHashingContext < ' __ctx> ,
107
+ #context
79
108
>
80
109
) ,
81
110
quote ! {
82
111
#[ inline]
83
112
fn hash_stable(
84
113
& self ,
85
- __hcx: & mut :: rustc_query_system :: ich :: StableHashingContext < ' __ctx> ,
114
+ __hcx: & mut #context ,
86
115
__hasher: & mut :: rustc_data_structures:: stable_hasher:: StableHasher ) {
87
116
#discriminant
88
117
match * self { #body }
0 commit comments