@@ -2299,18 +2299,6 @@ impl<'tcx> ConstantKind<'tcx> {
2299
2299
}
2300
2300
}
2301
2301
2302
- #[ inline]
2303
- pub fn try_to_value ( self , tcx : TyCtxt < ' tcx > ) -> Option < interpret:: ConstValue < ' tcx > > {
2304
- match self {
2305
- ConstantKind :: Ty ( c) => match c. kind ( ) {
2306
- ty:: ConstKind :: Value ( valtree) => Some ( tcx. valtree_to_const_val ( ( c. ty ( ) , valtree) ) ) ,
2307
- _ => None ,
2308
- } ,
2309
- ConstantKind :: Val ( val, _) => Some ( val) ,
2310
- ConstantKind :: Unevaluated ( ..) => None ,
2311
- }
2312
- }
2313
-
2314
2302
#[ inline]
2315
2303
pub fn try_to_scalar ( self ) -> Option < Scalar > {
2316
2304
match self {
@@ -2342,37 +2330,55 @@ impl<'tcx> ConstantKind<'tcx> {
2342
2330
}
2343
2331
2344
2332
#[ inline]
2345
- pub fn eval ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> Self {
2346
- match self {
2347
- Self :: Ty ( c) => {
2348
- if let Some ( val) = c. try_eval_for_mir ( tcx, param_env) {
2349
- match val {
2350
- Ok ( val) => Self :: Val ( val, c. ty ( ) ) ,
2351
- Err ( guar) => Self :: Ty ( ty:: Const :: new_error ( tcx, guar, self . ty ( ) ) ) ,
2352
- }
2333
+ pub fn eval (
2334
+ self ,
2335
+ tcx : TyCtxt < ' tcx > ,
2336
+ param_env : ty:: ParamEnv < ' tcx > ,
2337
+ span : Option < Span > ,
2338
+ ) -> Result < interpret:: ConstValue < ' tcx > , ErrorHandled > {
2339
+ let uneval = match self {
2340
+ ConstantKind :: Ty ( c) => {
2341
+ if let ty:: ConstKind :: Unevaluated ( uv) = c. kind ( ) {
2342
+ // Avoid the round-trip via valtree, evaluate directly to ConstValue.
2343
+ uv. expand ( )
2353
2344
} else {
2354
- self
2355
- }
2356
- }
2357
- Self :: Val ( _, _) => self ,
2358
- Self :: Unevaluated ( uneval, ty) => {
2359
- // FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
2360
- match tcx. const_eval_resolve ( param_env, uneval, None ) {
2361
- Ok ( val) => Self :: Val ( val, ty) ,
2362
- Err ( ErrorHandled :: TooGeneric ) => self ,
2363
- Err ( ErrorHandled :: Reported ( guar) ) => {
2364
- Self :: Ty ( ty:: Const :: new_error ( tcx, guar. into ( ) , ty) )
2365
- }
2345
+ // It's already a valtree, or an error.
2346
+ let val = c. eval ( tcx, param_env, span) ?;
2347
+ return Ok ( tcx. valtree_to_const_val ( ( self . ty ( ) , val) ) ) ;
2366
2348
}
2367
2349
}
2350
+ ConstantKind :: Unevaluated ( uneval, _) => uneval,
2351
+ ConstantKind :: Val ( val, _) => return Ok ( val) ,
2352
+ } ;
2353
+ // FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
2354
+ tcx. const_eval_resolve ( param_env, uneval, span)
2355
+ }
2356
+
2357
+ /// Normalizes the constant to a value if possible.
2358
+ #[ inline]
2359
+ pub fn normalize ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> Self {
2360
+ match self . eval ( tcx, param_env, None ) {
2361
+ Ok ( val) => Self :: Val ( val, self . ty ( ) ) ,
2362
+ Err ( _) => self ,
2368
2363
}
2369
2364
}
2370
2365
2371
- /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
2372
2366
#[ inline]
2373
- pub fn eval_bits ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > , ty : Ty < ' tcx > ) -> u128 {
2374
- self . try_eval_bits ( tcx, param_env, ty)
2375
- . unwrap_or_else ( || bug ! ( "expected bits of {:#?}, got {:#?}" , ty, self ) )
2367
+ pub fn try_eval_scalar (
2368
+ self ,
2369
+ tcx : TyCtxt < ' tcx > ,
2370
+ param_env : ty:: ParamEnv < ' tcx > ,
2371
+ ) -> Option < Scalar > {
2372
+ self . eval ( tcx, param_env, None ) . ok ( ) ?. try_to_scalar ( )
2373
+ }
2374
+
2375
+ #[ inline]
2376
+ pub fn try_eval_scalar_int (
2377
+ self ,
2378
+ tcx : TyCtxt < ' tcx > ,
2379
+ param_env : ty:: ParamEnv < ' tcx > ,
2380
+ ) -> Option < ScalarInt > {
2381
+ self . try_eval_scalar ( tcx, param_env) ?. try_to_int ( ) . ok ( )
2376
2382
}
2377
2383
2378
2384
#[ inline]
@@ -2382,59 +2388,38 @@ impl<'tcx> ConstantKind<'tcx> {
2382
2388
param_env : ty:: ParamEnv < ' tcx > ,
2383
2389
ty : Ty < ' tcx > ,
2384
2390
) -> Option < u128 > {
2385
- match self {
2386
- Self :: Ty ( ct) => ct. try_eval_bits ( tcx, param_env, ty) ,
2387
- Self :: Val ( val, t) => {
2388
- assert_eq ! ( * t, ty) ;
2389
- let size =
2390
- tcx. layout_of ( param_env. with_reveal_all_normalized ( tcx) . and ( ty) ) . ok ( ) ?. size ;
2391
- val. try_to_bits ( size)
2392
- }
2393
- Self :: Unevaluated ( uneval, ty) => {
2394
- match tcx. const_eval_resolve ( param_env, * uneval, None ) {
2395
- Ok ( val) => {
2396
- let size = tcx
2397
- . layout_of ( param_env. with_reveal_all_normalized ( tcx) . and ( * ty) )
2398
- . ok ( ) ?
2399
- . size ;
2400
- val. try_to_bits ( size)
2401
- }
2402
- Err ( _) => None ,
2403
- }
2404
- }
2405
- }
2391
+ let int = self . try_eval_scalar_int ( tcx, param_env) ?;
2392
+ assert_eq ! ( self . ty( ) , ty) ;
2393
+ let size = tcx. layout_of ( param_env. with_reveal_all_normalized ( tcx) . and ( ty) ) . ok ( ) ?. size ;
2394
+ int. to_bits ( size) . ok ( )
2406
2395
}
2407
2396
2397
+ /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
2408
2398
#[ inline]
2409
- pub fn try_eval_bool ( & self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> Option < bool > {
2410
- match self {
2411
- Self :: Ty ( ct) => ct. try_eval_bool ( tcx, param_env) ,
2412
- Self :: Val ( val, _) => val. try_to_bool ( ) ,
2413
- Self :: Unevaluated ( uneval, _) => {
2414
- match tcx. const_eval_resolve ( param_env, * uneval, None ) {
2415
- Ok ( val) => val. try_to_bool ( ) ,
2416
- Err ( _) => None ,
2417
- }
2418
- }
2419
- }
2399
+ pub fn eval_bits ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > , ty : Ty < ' tcx > ) -> u128 {
2400
+ self . try_eval_bits ( tcx, param_env, ty)
2401
+ . unwrap_or_else ( || bug ! ( "expected bits of {:#?}, got {:#?}" , ty, self ) )
2420
2402
}
2421
2403
2422
2404
#[ inline]
2423
2405
pub fn try_eval_target_usize (
2424
- & self ,
2406
+ self ,
2425
2407
tcx : TyCtxt < ' tcx > ,
2426
2408
param_env : ty:: ParamEnv < ' tcx > ,
2427
2409
) -> Option < u64 > {
2428
- match self {
2429
- Self :: Ty ( ct) => ct. try_eval_target_usize ( tcx, param_env) ,
2430
- Self :: Val ( val, _) => val. try_to_target_usize ( tcx) ,
2431
- Self :: Unevaluated ( uneval, _) => {
2432
- match tcx. const_eval_resolve ( param_env, * uneval, None ) {
2433
- Ok ( val) => val. try_to_target_usize ( tcx) ,
2434
- Err ( _) => None ,
2435
- }
2436
- }
2437
- }
2410
+ self . try_eval_scalar_int ( tcx, param_env) ?. try_to_target_usize ( tcx) . ok ( )
2411
+ }
2412
+
2413
+ #[ inline]
2414
+ /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
2415
+ pub fn eval_target_usize ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> u64 {
2416
+ self . try_eval_target_usize ( tcx, param_env)
2417
+ . unwrap_or_else ( || bug ! ( "expected usize, got {:#?}" , self ) )
2418
+ }
2419
+
2420
+ #[ inline]
2421
+ pub fn try_eval_bool ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> Option < bool > {
2422
+ self . try_eval_scalar_int ( tcx, param_env) ?. try_into ( ) . ok ( )
2438
2423
}
2439
2424
2440
2425
#[ inline]
@@ -2576,7 +2561,7 @@ impl<'tcx> ConstantKind<'tcx> {
2576
2561
}
2577
2562
}
2578
2563
2579
- pub fn from_const ( c : ty:: Const < ' tcx > , tcx : TyCtxt < ' tcx > ) -> Self {
2564
+ pub fn from_ty_const ( c : ty:: Const < ' tcx > , tcx : TyCtxt < ' tcx > ) -> Self {
2580
2565
match c. kind ( ) {
2581
2566
ty:: ConstKind :: Value ( valtree) => {
2582
2567
let const_val = tcx. valtree_to_const_val ( ( c. ty ( ) , valtree) ) ;
@@ -2610,6 +2595,11 @@ impl<'tcx> UnevaluatedConst<'tcx> {
2610
2595
pub fn new ( def : DefId , args : GenericArgsRef < ' tcx > ) -> UnevaluatedConst < ' tcx > {
2611
2596
UnevaluatedConst { def, args, promoted : Default :: default ( ) }
2612
2597
}
2598
+
2599
+ #[ inline]
2600
+ pub fn from_instance ( instance : ty:: Instance < ' tcx > ) -> Self {
2601
+ UnevaluatedConst :: new ( instance. def_id ( ) , instance. args )
2602
+ }
2613
2603
}
2614
2604
2615
2605
/// A collection of projections into user types.
@@ -2884,7 +2874,7 @@ fn pretty_print_const_value<'tcx>(
2884
2874
}
2885
2875
}
2886
2876
( ConstValue :: ByRef { alloc, offset } , ty:: Array ( t, n) ) if * t == u8_type => {
2887
- let n = n. try_to_bits ( tcx. data_layout . pointer_size ) . unwrap ( ) ;
2877
+ let n = n. try_to_target_usize ( tcx) . unwrap ( ) ;
2888
2878
// cast is ok because we already checked for pointer size (32 or 64 bit) above
2889
2879
let range = AllocRange { start : offset, size : Size :: from_bytes ( n) } ;
2890
2880
let byte_str = alloc. inner ( ) . get_bytes_strip_provenance ( & tcx, range) . unwrap ( ) ;
0 commit comments