@@ -2340,14 +2340,41 @@ impl<'tcx> Const<'tcx> {
2340
2340
assert_eq ! ( self . ty, ty) ;
2341
2341
let size = tcx. layout_of ( param_env. with_reveal_all ( ) . and ( ty) ) . ok ( ) ?. size ;
2342
2342
// 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)
2344
2344
}
2345
2345
2346
2346
#[ inline]
2347
2347
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
2348
2348
/// unevaluated constant.
2349
2349
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 {
2351
2378
use crate :: mir:: interpret:: ErrorHandled ;
2352
2379
2353
2380
let param_env_and_substs = param_env. with_reveal_all ( ) . and ( substs) ;
@@ -2378,27 +2405,25 @@ impl<'tcx> Const<'tcx> {
2378
2405
// and we use the original type, so nothing from `substs`
2379
2406
// (which may be identity substs, see above),
2380
2407
// 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 ) ) ,
2384
2411
}
2385
2412
} else {
2386
- self
2413
+ None
2387
2414
}
2388
2415
}
2416
+ }
2389
2417
2418
+ impl < ' tcx > Const < ' tcx > {
2390
2419
#[ inline]
2391
2420
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 ( )
2397
2422
}
2398
2423
2399
2424
#[ inline]
2400
2425
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 )
2402
2427
}
2403
2428
2404
2429
#[ inline]
@@ -2411,7 +2436,8 @@ impl<'tcx> Const<'tcx> {
2411
2436
#[ inline]
2412
2437
/// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
2413
2438
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 ) )
2415
2441
}
2416
2442
}
2417
2443
@@ -2448,13 +2474,28 @@ static_assert_size!(ConstKind<'_>, 40);
2448
2474
2449
2475
impl < ' tcx > ConstKind < ' tcx > {
2450
2476
#[ 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 ( )
2453
2494
}
2454
2495
2455
2496
#[ 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 )
2458
2499
}
2459
2500
}
2460
2501
0 commit comments