@@ -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,59 @@ 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, param_env) = match self {
2340
+ ConstantKind :: Ty ( c) => {
2341
+ if let ty:: ConstKind :: Unevaluated ( uneval) = c. kind ( ) {
2342
+ // Avoid the round-trip via valtree, evaluate directly to ConstValue.
2343
+ let ( param_env, uneval) = uneval. prepare_for_eval ( tcx, param_env) ;
2344
+ ( uneval. expand ( ) , param_env)
2353
2345
} else {
2354
- self
2346
+ // It's already a valtree, or an error.
2347
+ let val = c. eval ( tcx, param_env, span) ?;
2348
+ return Ok ( tcx. valtree_to_const_val ( ( self . ty ( ) , val) ) ) ;
2355
2349
}
2356
2350
}
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
- }
2366
- }
2351
+ ConstantKind :: Unevaluated ( uneval, _) => ( uneval, param_env) ,
2352
+ ConstantKind :: Val ( val, _) => return Ok ( val) ,
2353
+ } ;
2354
+ // FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
2355
+ tcx. const_eval_resolve ( param_env, uneval, span)
2356
+ }
2357
+
2358
+ /// Normalizes the constant to a value or an error if possible.
2359
+ #[ inline]
2360
+ pub fn normalize ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> Self {
2361
+ match self . eval ( tcx, param_env, None ) {
2362
+ Ok ( val) => Self :: Val ( val, self . ty ( ) ) ,
2363
+ Err ( ErrorHandled :: Reported ( guar) ) => {
2364
+ Self :: Ty ( ty:: Const :: new_error ( tcx, guar. into ( ) , self . ty ( ) ) )
2367
2365
}
2366
+ Err ( ErrorHandled :: TooGeneric ) => self ,
2368
2367
}
2369
2368
}
2370
2369
2371
- /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
2372
2370
#[ 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 ) )
2371
+ pub fn try_eval_scalar (
2372
+ self ,
2373
+ tcx : TyCtxt < ' tcx > ,
2374
+ param_env : ty:: ParamEnv < ' tcx > ,
2375
+ ) -> Option < Scalar > {
2376
+ self . eval ( tcx, param_env, None ) . ok ( ) ?. try_to_scalar ( )
2377
+ }
2378
+
2379
+ #[ inline]
2380
+ pub fn try_eval_scalar_int (
2381
+ self ,
2382
+ tcx : TyCtxt < ' tcx > ,
2383
+ param_env : ty:: ParamEnv < ' tcx > ,
2384
+ ) -> Option < ScalarInt > {
2385
+ self . try_eval_scalar ( tcx, param_env) ?. try_to_int ( ) . ok ( )
2376
2386
}
2377
2387
2378
2388
#[ inline]
@@ -2382,59 +2392,38 @@ impl<'tcx> ConstantKind<'tcx> {
2382
2392
param_env : ty:: ParamEnv < ' tcx > ,
2383
2393
ty : Ty < ' tcx > ,
2384
2394
) -> 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
- }
2395
+ let int = self . try_eval_scalar_int ( tcx, param_env) ?;
2396
+ assert_eq ! ( self . ty( ) , ty) ;
2397
+ let size = tcx. layout_of ( param_env. with_reveal_all_normalized ( tcx) . and ( ty) ) . ok ( ) ?. size ;
2398
+ int. to_bits ( size) . ok ( )
2406
2399
}
2407
2400
2401
+ /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
2408
2402
#[ 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
- }
2403
+ pub fn eval_bits ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > , ty : Ty < ' tcx > ) -> u128 {
2404
+ self . try_eval_bits ( tcx, param_env, ty)
2405
+ . unwrap_or_else ( || bug ! ( "expected bits of {:#?}, got {:#?}" , ty, self ) )
2420
2406
}
2421
2407
2422
2408
#[ inline]
2423
2409
pub fn try_eval_target_usize (
2424
- & self ,
2410
+ self ,
2425
2411
tcx : TyCtxt < ' tcx > ,
2426
2412
param_env : ty:: ParamEnv < ' tcx > ,
2427
2413
) -> 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
- }
2414
+ self . try_eval_scalar_int ( tcx, param_env) ?. try_to_target_usize ( tcx) . ok ( )
2415
+ }
2416
+
2417
+ #[ inline]
2418
+ /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
2419
+ pub fn eval_target_usize ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> u64 {
2420
+ self . try_eval_target_usize ( tcx, param_env)
2421
+ . unwrap_or_else ( || bug ! ( "expected usize, got {:#?}" , self ) )
2422
+ }
2423
+
2424
+ #[ inline]
2425
+ pub fn try_eval_bool ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> Option < bool > {
2426
+ self . try_eval_scalar_int ( tcx, param_env) ?. try_into ( ) . ok ( )
2438
2427
}
2439
2428
2440
2429
#[ inline]
@@ -2576,7 +2565,7 @@ impl<'tcx> ConstantKind<'tcx> {
2576
2565
}
2577
2566
}
2578
2567
2579
- pub fn from_const ( c : ty:: Const < ' tcx > , tcx : TyCtxt < ' tcx > ) -> Self {
2568
+ pub fn from_ty_const ( c : ty:: Const < ' tcx > , tcx : TyCtxt < ' tcx > ) -> Self {
2580
2569
match c. kind ( ) {
2581
2570
ty:: ConstKind :: Value ( valtree) => {
2582
2571
let const_val = tcx. valtree_to_const_val ( ( c. ty ( ) , valtree) ) ;
@@ -2610,6 +2599,11 @@ impl<'tcx> UnevaluatedConst<'tcx> {
2610
2599
pub fn new ( def : DefId , args : GenericArgsRef < ' tcx > ) -> UnevaluatedConst < ' tcx > {
2611
2600
UnevaluatedConst { def, args, promoted : Default :: default ( ) }
2612
2601
}
2602
+
2603
+ #[ inline]
2604
+ pub fn from_instance ( instance : ty:: Instance < ' tcx > ) -> Self {
2605
+ UnevaluatedConst :: new ( instance. def_id ( ) , instance. args )
2606
+ }
2613
2607
}
2614
2608
2615
2609
/// A collection of projections into user types.
@@ -2884,7 +2878,7 @@ fn pretty_print_const_value<'tcx>(
2884
2878
}
2885
2879
}
2886
2880
( 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 ( ) ;
2881
+ let n = n. try_to_target_usize ( tcx) . unwrap ( ) ;
2888
2882
// cast is ok because we already checked for pointer size (32 or 64 bit) above
2889
2883
let range = AllocRange { start : offset, size : Size :: from_bytes ( n) } ;
2890
2884
let byte_str = alloc. inner ( ) . get_bytes_strip_provenance ( & tcx, range) . unwrap ( ) ;
0 commit comments