@@ -2340,14 +2340,41 @@ impl<'tcx> Const<'tcx> {
23402340 assert_eq ! ( self . ty, ty) ;
23412341 let size = tcx. layout_of ( param_env. with_reveal_all ( ) . and ( ty) ) . ok ( ) ?. size ;
23422342 // if `ty` does not depend on generic parameters, use an empty param_env
2343- self . eval ( tcx, param_env) . val . try_to_bits ( size)
2343+ self . val . eval ( tcx, param_env) . try_to_bits ( size)
23442344 }
23452345
23462346 #[ inline]
23472347 /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
23482348 /// unevaluated constant.
23492349 pub fn eval ( & self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> & Const < ' tcx > {
2350- if let ConstKind :: Unevaluated ( def, substs, promoted) = self . val {
2350+ if let Some ( val) = self . val . try_eval ( tcx, param_env) {
2351+ match val {
2352+ Ok ( val) => Const :: from_value ( tcx, val, self . ty ) ,
2353+ Err ( ErrorReported ) => tcx. const_error ( self . ty ) ,
2354+ }
2355+ } else {
2356+ self
2357+ }
2358+ }
2359+ }
2360+
2361+ impl < ' tcx > ConstKind < ' tcx > {
2362+ #[ inline]
2363+ /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
2364+ /// unevaluated constant.
2365+ pub fn eval ( self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> Self {
2366+ self . try_eval ( tcx, param_env) . and_then ( Result :: ok) . map ( ConstKind :: Value ) . unwrap_or ( self )
2367+ }
2368+
2369+ #[ inline]
2370+ /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
2371+ // return None
2372+ pub fn try_eval (
2373+ self ,
2374+ tcx : TyCtxt < ' tcx > ,
2375+ param_env : ParamEnv < ' tcx > ,
2376+ ) -> Option < Result < ConstValue < ' tcx > , ErrorReported > > {
2377+ if let ConstKind :: Unevaluated ( def, substs, promoted) = self {
23512378 use crate :: mir:: interpret:: ErrorHandled ;
23522379
23532380 let param_env_and_substs = param_env. with_reveal_all ( ) . and ( substs) ;
@@ -2378,27 +2405,25 @@ impl<'tcx> Const<'tcx> {
23782405 // and we use the original type, so nothing from `substs`
23792406 // (which may be identity substs, see above),
23802407 // can leak through `val` into the const we return.
2381- Ok ( val) => Const :: from_value ( tcx , val, self . ty ) ,
2382- Err ( ErrorHandled :: TooGeneric | ErrorHandled :: Linted ) => self ,
2383- Err ( ErrorHandled :: Reported ( ErrorReported ) ) => tcx . const_error ( self . ty ) ,
2408+ Ok ( val) => Some ( Ok ( val) ) ,
2409+ Err ( ErrorHandled :: TooGeneric | ErrorHandled :: Linted ) => None ,
2410+ Err ( ErrorHandled :: Reported ( e ) ) => Some ( Err ( e ) ) ,
23842411 }
23852412 } else {
2386- self
2413+ None
23872414 }
23882415 }
2416+ }
23892417
2418+ impl < ' tcx > Const < ' tcx > {
23902419 #[ inline]
23912420 pub fn try_eval_bool ( & self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> Option < bool > {
2392- self . try_eval_bits ( tcx, param_env, tcx. types . bool ) . and_then ( |v| match v {
2393- 0 => Some ( false ) ,
2394- 1 => Some ( true ) ,
2395- _ => None ,
2396- } )
2421+ self . val . eval ( tcx, param_env) . try_to_bool ( )
23972422 }
23982423
23992424 #[ inline]
24002425 pub fn try_eval_usize ( & self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> Option < u64 > {
2401- self . try_eval_bits ( tcx, param_env, tcx . types . usize ) . map ( |v| v as u64 )
2426+ self . val . eval ( tcx, param_env) . try_to_usize ( tcx )
24022427 }
24032428
24042429 #[ inline]
@@ -2411,7 +2436,8 @@ impl<'tcx> Const<'tcx> {
24112436 #[ inline]
24122437 /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
24132438 pub fn eval_usize ( & self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> u64 {
2414- self . eval_bits ( tcx, param_env, tcx. types . usize ) as u64
2439+ self . try_eval_usize ( tcx, param_env)
2440+ . unwrap_or_else ( || bug ! ( "expected usize, got {:#?}" , self ) )
24152441 }
24162442}
24172443
@@ -2448,13 +2474,28 @@ static_assert_size!(ConstKind<'_>, 40);
24482474
24492475impl < ' tcx > ConstKind < ' tcx > {
24502476 #[ inline]
2451- pub fn try_to_scalar ( & self ) -> Option < Scalar > {
2452- if let ConstKind :: Value ( val) = self { val. try_to_scalar ( ) } else { None }
2477+ pub fn try_to_value ( self ) -> Option < ConstValue < ' tcx > > {
2478+ if let ConstKind :: Value ( val) = self { Some ( val) } else { None }
2479+ }
2480+
2481+ #[ inline]
2482+ pub fn try_to_scalar ( self ) -> Option < Scalar > {
2483+ self . try_to_value ( ) ?. try_to_scalar ( )
2484+ }
2485+
2486+ #[ inline]
2487+ pub fn try_to_bits ( self , size : Size ) -> Option < u128 > {
2488+ self . try_to_value ( ) ?. try_to_bits ( size)
2489+ }
2490+
2491+ #[ inline]
2492+ pub fn try_to_bool ( self ) -> Option < bool > {
2493+ self . try_to_value ( ) ?. try_to_bool ( )
24532494 }
24542495
24552496 #[ inline]
2456- pub fn try_to_bits ( & self , size : Size ) -> Option < u128 > {
2457- if let ConstKind :: Value ( val ) = self { val . try_to_bits ( size ) } else { None }
2497+ pub fn try_to_usize ( self , tcx : TyCtxt < ' tcx > ) -> Option < u64 > {
2498+ self . try_to_value ( ) ? . try_to_usize ( tcx )
24582499 }
24592500}
24602501
0 commit comments