@@ -53,8 +53,7 @@ use proc_macro2::{Span, TokenStream};
5353use quote:: { quote, ToTokens } ;
5454use syn:: {
5555 parse_quote, spanned:: Spanned as _, Attribute , Data , DataEnum , DataStruct , DataUnion ,
56- DeriveInput , Error , Expr , ExprLit , ExprUnary , GenericParam , Ident , Lit , Meta , Path , Type , UnOp ,
57- WherePredicate ,
56+ DeriveInput , Error , Expr , ExprLit , GenericParam , Ident , Lit , Meta , Path , Type , WherePredicate ,
5857} ;
5958
6059use crate :: { repr:: * , util:: * } ;
@@ -1100,84 +1099,6 @@ fn derive_from_zeros_struct(
11001099 . build ( )
11011100}
11021101
1103- /// Returns `Ok(index)` if variant `index` of the enum has a discriminant of
1104- /// zero. If `Err(bool)` is returned, the boolean is true if the enum has
1105- /// unknown discriminants (e.g. discriminants set to const expressions which we
1106- /// can't evaluate in a proc macro). If the enum has unknown discriminants, then
1107- /// it might have a zero variant that we just can't detect.
1108- fn find_zero_variant ( enm : & DataEnum ) -> Result < usize , bool > {
1109- // Discriminants can be anywhere in the range [i128::MIN, u128::MAX] because
1110- // the discriminant type may be signed or unsigned. Since we only care about
1111- // tracking the discriminant when it's less than or equal to zero, we can
1112- // avoid u128 -> i128 conversions and bounds checking by making the "next
1113- // discriminant" value implicitly negative.
1114- // Technically 64 bits is enough, but 128 is better for future compatibility
1115- // with https://github.com/rust-lang/rust/issues/56071
1116- let mut next_negative_discriminant = Some ( 0 ) ;
1117-
1118- // Sometimes we encounter explicit discriminants that we can't know the
1119- // value of (e.g. a constant expression that requires evaluation). These
1120- // could evaluate to zero or a negative number, but we can't assume that
1121- // they do (no false positives allowed!). So we treat them like strictly-
1122- // positive values that can't result in any zero variants, and track whether
1123- // we've encountered any unknown discriminants.
1124- let mut has_unknown_discriminants = false ;
1125-
1126- for ( i, v) in enm. variants . iter ( ) . enumerate ( ) {
1127- match v. discriminant . as_ref ( ) {
1128- // Implicit discriminant
1129- None => {
1130- match next_negative_discriminant. as_mut ( ) {
1131- Some ( 0 ) => return Ok ( i) ,
1132- // n is nonzero so subtraction is always safe
1133- Some ( n) => * n -= 1 ,
1134- None => ( ) ,
1135- }
1136- }
1137- // Explicit positive discriminant
1138- Some ( ( _, Expr :: Lit ( ExprLit { lit : Lit :: Int ( int) , .. } ) ) ) => {
1139- match int. base10_parse :: < u128 > ( ) . ok ( ) {
1140- Some ( 0 ) => return Ok ( i) ,
1141- Some ( _) => next_negative_discriminant = None ,
1142- None => {
1143- // Numbers should never fail to parse, but just in case:
1144- has_unknown_discriminants = true ;
1145- next_negative_discriminant = None ;
1146- }
1147- }
1148- }
1149- // Explicit negative discriminant
1150- Some ( ( _, Expr :: Unary ( ExprUnary { op : UnOp :: Neg ( _) , expr, .. } ) ) ) => match & * * expr {
1151- Expr :: Lit ( ExprLit { lit : Lit :: Int ( int) , .. } ) => {
1152- match int. base10_parse :: < u128 > ( ) . ok ( ) {
1153- Some ( 0 ) => return Ok ( i) ,
1154- // x is nonzero so subtraction is always safe
1155- Some ( x) => next_negative_discriminant = Some ( x - 1 ) ,
1156- None => {
1157- // Numbers should never fail to parse, but just in
1158- // case:
1159- has_unknown_discriminants = true ;
1160- next_negative_discriminant = None ;
1161- }
1162- }
1163- }
1164- // Unknown negative discriminant (e.g. const repr)
1165- _ => {
1166- has_unknown_discriminants = true ;
1167- next_negative_discriminant = None ;
1168- }
1169- } ,
1170- // Unknown discriminant (e.g. const expr)
1171- _ => {
1172- has_unknown_discriminants = true ;
1173- next_negative_discriminant = None ;
1174- }
1175- }
1176- }
1177-
1178- Err ( has_unknown_discriminants)
1179- }
1180-
11811102/// An enum is `FromZeros` if:
11821103/// - one of the variants has a discriminant of `0`
11831104/// - that variant's fields are all `FromZeros`
@@ -1199,7 +1120,7 @@ fn derive_from_zeros_enum(
11991120 | Repr :: Compound ( Spanned { t : CompoundRepr :: Rust , span : _ } , _) => return Err ( Error :: new ( Span :: call_site ( ) , "must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout" ) ) ,
12001121 }
12011122
1202- let zero_variant = match find_zero_variant ( enm) {
1123+ let zero_variant = match r#enum :: find_zero_variant ( enm) {
12031124 Ok ( index) => enm. variants . iter ( ) . nth ( index) . unwrap ( ) ,
12041125 // Has unknown variants
12051126 Err ( true ) => {
0 commit comments