@@ -80,12 +80,56 @@ macro_rules! define_dep_nodes {
80
80
}
81
81
82
82
/// This enum serves as an index into arrays built by `make_dep_kind_array`.
83
- #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , Encodable , Decodable ) ]
83
+ // This enum has more than u8::MAX variants so we need some kind of multi-byte
84
+ // encoding. The derived Encodable/Decodable uses leb128 encoding which is
85
+ // dense when only considering this enum. But DepKind is encoded in a larger
86
+ // struct, and there we can take advantage of the unused bits in the u16.
87
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash ) ]
84
88
#[ allow( non_camel_case_types) ]
89
+ #[ repr( u16 ) ]
85
90
pub enum DepKind {
86
91
$( $( #[ $attr] ) * $variant) ,*
87
92
}
88
93
94
+ impl DepKind {
95
+ // This const implements two things: A bounds check so that we can decode
96
+ // a DepKind from a u16 with just one check, and a const check that the
97
+ // discriminants of the variants have been assigned consecutively from 0
98
+ // so that just the one comparison suffices to check that the u16 can be
99
+ // transmuted to a DepKind.
100
+ const VARIANTS : u16 = {
101
+ let deps: & [ DepKind ] = & [ $( DepKind :: $variant, ) * ] ;
102
+ let mut i = 0 ;
103
+ while i < deps. len( ) {
104
+ if i as u16 != deps[ i] as u16 {
105
+ panic!( ) ;
106
+ }
107
+ i += 1 ;
108
+ }
109
+ deps. len( ) as u16
110
+ } ;
111
+ }
112
+
113
+ impl <S : rustc_serialize:: Encoder > rustc_serialize:: Encodable <S > for DepKind {
114
+ #[ inline]
115
+ fn encode( & self , s: & mut S ) {
116
+ s. emit_u16( * self as u16 ) ;
117
+ }
118
+ }
119
+
120
+ impl <D : rustc_serialize:: Decoder > rustc_serialize:: Decodable <D > for DepKind {
121
+ #[ inline]
122
+ fn decode( d: & mut D ) -> DepKind {
123
+ let discrim = d. read_u16( ) ;
124
+ assert!( discrim < DepKind :: VARIANTS ) ;
125
+ // SAFETY: DepKind::VARIANTS checks that the discriminant values permit
126
+ // this one check to soundly guard the transmute.
127
+ unsafe {
128
+ std:: mem:: transmute:: <u16 , DepKind >( discrim)
129
+ }
130
+ }
131
+ }
132
+
89
133
pub ( super ) fn dep_kind_from_label_string( label: & str ) -> Result <DepKind , ( ) > {
90
134
match label {
91
135
$( stringify!( $variant) => Ok ( DepKind :: $variant) , ) *
@@ -114,6 +158,8 @@ rustc_query_append!(define_dep_nodes![
114
158
[ ] fn CompileMonoItem ( ) -> ( ) ,
115
159
] ) ;
116
160
161
+ static_assert_size ! ( DepKind , 2 ) ;
162
+
117
163
// WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
118
164
// Be very careful changing this type signature!
119
165
pub ( crate ) fn make_compile_codegen_unit ( tcx : TyCtxt < ' _ > , name : Symbol ) -> DepNode {
0 commit comments