@@ -80,12 +80,56 @@ macro_rules! define_dep_nodes {
8080 }
8181
8282 /// 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 ) ]
8488 #[ allow( non_camel_case_types) ]
89+ #[ repr( u16 ) ]
8590 pub enum DepKind {
8691 $( $( #[ $attr] ) * $variant) ,*
8792 }
8893
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+
89133 pub ( super ) fn dep_kind_from_label_string( label: & str ) -> Result <DepKind , ( ) > {
90134 match label {
91135 $( stringify!( $variant) => Ok ( DepKind :: $variant) , ) *
@@ -114,6 +158,8 @@ rustc_query_append!(define_dep_nodes![
114158 [ ] fn CompileMonoItem ( ) -> ( ) ,
115159] ) ;
116160
161+ static_assert_size ! ( DepKind , 2 ) ;
162+
117163// WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
118164// Be very careful changing this type signature!
119165pub ( crate ) fn make_compile_codegen_unit ( tcx : TyCtxt < ' _ > , name : Symbol ) -> DepNode {
0 commit comments