@@ -1963,15 +1963,43 @@ impl<'db> CtfeMachine<'db> {
19631963 let [ value] = args else {
19641964 return Err ( CtfeError :: NotConstEvaluable { origin } ) ;
19651965 } ;
1966- let bytes = self . const_as_bytes ( value, origin) ?;
1966+ let mut bytes = self . const_as_bytes ( value, origin) ?;
19671967 if let Some ( len) = array_len ( self . db , result_ty)
19681968 && bytes. len ( ) != len
19691969 {
1970- return Err ( CtfeError :: NotConstEvaluable { origin } ) ;
1970+ if let Some ( string_bytes) = self . fixed_string_bytes_for_len ( value, len) {
1971+ bytes = string_bytes;
1972+ } else {
1973+ return Err ( CtfeError :: NotConstEvaluable { origin } ) ;
1974+ }
19711975 }
19721976 Ok ( CtfeConstValue :: bytes ( result_ty, bytes) )
19731977 }
19741978
1979+ fn fixed_string_bytes_for_len (
1980+ & self ,
1981+ value : & CtfeConstValue < ' db > ,
1982+ len : usize ,
1983+ ) -> Option < Vec < u8 > > {
1984+ let value = self . expand_interned ( value. clone ( ) ) ;
1985+ let CtfeConstKind :: Bytes { ty, bytes } = & value. kind else {
1986+ return None ;
1987+ } ;
1988+ if !ty. is_string ( self . db ) {
1989+ return None ;
1990+ }
1991+
1992+ let mut out = vec ! [ 0u8 ; len] ;
1993+ let suffix = if bytes. len ( ) > len {
1994+ & bytes[ bytes. len ( ) - len..]
1995+ } else {
1996+ bytes. as_ref ( )
1997+ } ;
1998+ let offset = len - suffix. len ( ) ;
1999+ out[ offset..] . copy_from_slice ( suffix) ;
2000+ Some ( out)
2001+ }
2002+
19752003 fn eval_intrinsic_keccak (
19762004 & self ,
19772005 result_ty : TyId < ' db > ,
@@ -2922,6 +2950,26 @@ impl<'db> CtfeMachine<'db> {
29222950 value : CtfeConstValue < ' db > ,
29232951 origin : SemOrigin < ' db > ,
29242952 ) -> Result < CtfeValue < ' db > , CtfeError < ' db > > {
2953+ fn fixed_string_capacity_bytes < ' db > (
2954+ db : & ' db dyn HirAnalysisDb ,
2955+ ty : TyId < ' db > ,
2956+ ) -> Option < usize > {
2957+ if !ty. is_string ( db) {
2958+ return None ;
2959+ }
2960+ let ( _, args) = ty. decompose_ty_app ( db) ;
2961+ let len_ty = args. first ( ) . copied ( ) ?;
2962+ let TyData :: ConstTy ( const_ty) = len_ty. data ( db) else {
2963+ return None ;
2964+ } ;
2965+ match const_ty. data ( db) {
2966+ ConstTyData :: Evaluated ( EvaluatedConstTy :: LitInt ( int_id) , _) => {
2967+ int_id. data ( db) . to_usize ( )
2968+ }
2969+ _ => None ,
2970+ }
2971+ }
2972+
29252973 let value = self . expand_interned ( value) ;
29262974 match & value. kind {
29272975 CtfeConstKind :: Bool ( value) if int_ty_shape ( self . db , result_ty) . is_some ( ) => {
@@ -2941,6 +2989,36 @@ impl<'db> CtfeMachine<'db> {
29412989 CtfeConstKind :: Int { value, .. } if int_ty_shape ( self . db , result_ty) . is_some ( ) => Ok (
29422990 CtfeValue :: Value ( CtfeConstValue :: int ( self . db , result_ty, value. to_bigint ( ) ) ) ,
29432991 ) ,
2992+ CtfeConstKind :: Int { value, .. } if result_ty. is_string ( self . db ) => {
2993+ fixed_string_capacity_bytes ( self . db , result_ty)
2994+ . ok_or ( CtfeError :: NotConstEvaluable { origin } ) ?;
2995+ let word = value. to_u256 ( ) ;
2996+ Ok ( CtfeValue :: Value ( CtfeConstValue :: bytes (
2997+ result_ty,
2998+ word. to_be_bytes :: < 32 > ( ) . to_vec ( ) ,
2999+ ) ) )
3000+ }
3001+ CtfeConstKind :: Bytes { bytes, .. }
3002+ if matches ! ( int_ty_shape( self . db, result_ty) , Some ( ( _, false ) ) ) =>
3003+ {
3004+ let Some ( ( bits, false ) ) = int_ty_shape ( self . db , result_ty) else {
3005+ unreachable ! ( "match guard should ensure unsigned int shape" ) ;
3006+ } ;
3007+ let width = usize:: from ( bits / 8 ) ;
3008+ if bytes. len ( ) > width && bytes[ ..bytes. len ( ) - width] . iter ( ) . any ( |byte| * byte != 0 )
3009+ {
3010+ return Err ( CtfeError :: NotConstEvaluable { origin } ) ;
3011+ }
3012+ let suffix = if bytes. len ( ) > width {
3013+ & bytes[ bytes. len ( ) - width..]
3014+ } else {
3015+ bytes. as_ref ( )
3016+ } ;
3017+ let value = BigInt :: from ( BigUint :: from_bytes_be ( suffix) ) ;
3018+ Ok ( CtfeValue :: Value ( CtfeConstValue :: int (
3019+ self . db , result_ty, value,
3020+ ) ) )
3021+ }
29443022 CtfeConstKind :: Bytes { bytes, .. } => Ok ( CtfeValue :: Value ( CtfeConstValue :: bytes (
29453023 result_ty,
29463024 bytes. to_vec ( ) ,
0 commit comments