@@ -2342,29 +2342,39 @@ impl<'tcx> ConstantKind<'tcx> {
2342
2342
}
2343
2343
2344
2344
#[ 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
- }
2345
+ pub fn eval (
2346
+ self ,
2347
+ tcx : TyCtxt < ' tcx > ,
2348
+ param_env : ty:: ParamEnv < ' tcx > ,
2349
+ span : Option < Span > ,
2350
+ ) -> Result < interpret:: ConstValue < ' tcx > , ErrorHandled > {
2351
+ let uneval = match self {
2352
+ ConstantKind :: Ty ( c) => {
2353
+ if let ty:: ConstKind :: Unevaluated ( uv) = c. kind ( ) {
2354
+ // Avoid the round-trip via valtree, evaluate directly to ConstValue.
2355
+ uv. expand ( )
2353
2356
} else {
2354
- self
2357
+ // It's already a valtree, or an error.
2358
+ let val = c. eval ( tcx, param_env, span) ?;
2359
+ return Ok ( tcx. valtree_to_const_val ( ( self . ty ( ) , val) ) ) ;
2355
2360
}
2356
2361
}
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
- }
2362
+ ConstantKind :: Unevaluated ( uneval, _) => uneval,
2363
+ ConstantKind :: Val ( val, _) => return Ok ( val) ,
2364
+ } ;
2365
+ // FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
2366
+ tcx. const_eval_resolve ( param_env, uneval, span)
2367
+ }
2368
+
2369
+ /// Normalizes the constant to a value or an error if possible.
2370
+ #[ inline]
2371
+ pub fn normalize ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> Self {
2372
+ match self . eval ( tcx, param_env, None ) {
2373
+ Ok ( val) => Self :: Val ( val, self . ty ( ) ) ,
2374
+ Err ( ErrorHandled :: Reported ( guar) ) => {
2375
+ Self :: Ty ( ty:: Const :: new_error ( tcx, guar. into ( ) , self . ty ( ) ) )
2367
2376
}
2377
+ Err ( ErrorHandled :: TooGeneric ) => self ,
2368
2378
}
2369
2379
}
2370
2380
@@ -2406,35 +2416,35 @@ impl<'tcx> ConstantKind<'tcx> {
2406
2416
}
2407
2417
2408
2418
#[ 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
- }
2419
+ pub fn try_eval_scalar (
2420
+ self ,
2421
+ tcx : TyCtxt < ' tcx > ,
2422
+ param_env : ty:: ParamEnv < ' tcx > ,
2423
+ ) -> Option < Scalar > {
2424
+ self . eval ( tcx, param_env, None ) . ok ( ) ?. try_to_scalar ( )
2425
+ }
2426
+
2427
+ #[ inline]
2428
+ pub fn try_eval_scalar_int (
2429
+ self ,
2430
+ tcx : TyCtxt < ' tcx > ,
2431
+ param_env : ty:: ParamEnv < ' tcx > ,
2432
+ ) -> Option < ScalarInt > {
2433
+ self . try_eval_scalar ( tcx, param_env) ?. try_to_int ( ) . ok ( )
2434
+ }
2435
+
2436
+ #[ inline]
2437
+ pub fn try_eval_bool ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> Option < bool > {
2438
+ self . try_eval_scalar_int ( tcx, param_env) ?. try_into ( ) . ok ( )
2420
2439
}
2421
2440
2422
2441
#[ inline]
2423
2442
pub fn try_eval_target_usize (
2424
- & self ,
2443
+ self ,
2425
2444
tcx : TyCtxt < ' tcx > ,
2426
2445
param_env : ty:: ParamEnv < ' tcx > ,
2427
2446
) -> 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
- }
2447
+ self . try_eval_scalar_int ( tcx, param_env) ?. try_to_target_usize ( tcx) . ok ( )
2438
2448
}
2439
2449
2440
2450
#[ inline]
@@ -2610,6 +2620,11 @@ impl<'tcx> UnevaluatedConst<'tcx> {
2610
2620
pub fn new ( def : DefId , args : GenericArgsRef < ' tcx > ) -> UnevaluatedConst < ' tcx > {
2611
2621
UnevaluatedConst { def, args, promoted : Default :: default ( ) }
2612
2622
}
2623
+
2624
+ #[ inline]
2625
+ pub fn from_instance ( instance : ty:: Instance < ' tcx > ) -> Self {
2626
+ UnevaluatedConst :: new ( instance. def_id ( ) , instance. args )
2627
+ }
2613
2628
}
2614
2629
2615
2630
/// A collection of projections into user types.
0 commit comments