1
1
use crate :: middle:: resolve_bound_vars as rbv;
2
2
use crate :: mir:: interpret:: { ErrorHandled , LitToConstInput , Scalar } ;
3
3
use crate :: ty:: { self , GenericArgs , ParamEnv , ParamEnvAnd , Ty , TyCtxt , TypeVisitableExt } ;
4
+ use either:: Either ;
4
5
use rustc_data_structures:: intern:: Interned ;
5
6
use rustc_error_messages:: MultiSpan ;
6
7
use rustc_hir as hir;
@@ -312,14 +313,16 @@ impl<'tcx> Const<'tcx> {
312
313
Self :: from_bits ( tcx, n as u128 , ParamEnv :: empty ( ) . and ( tcx. types . usize ) )
313
314
}
314
315
315
- /// Returns the evaluated constant
316
+ /// Returns the evaluated constant as a valtree;
317
+ /// if that fails due to a valtree-incompatible type, indicate which type that is
318
+ /// by returning `Err(Left(bad_type))`.
316
319
#[ inline]
317
- pub fn eval (
320
+ pub fn eval_valtree (
318
321
self ,
319
322
tcx : TyCtxt < ' tcx > ,
320
323
param_env : ParamEnv < ' tcx > ,
321
324
span : Span ,
322
- ) -> Result < ( Ty < ' tcx > , ValTree < ' tcx > ) , ErrorHandled > {
325
+ ) -> Result < ( Ty < ' tcx > , ValTree < ' tcx > ) , Either < Ty < ' tcx > , ErrorHandled > > {
323
326
assert ! ( !self . has_escaping_bound_vars( ) , "escaping vars in {self:?}" ) ;
324
327
match self . kind ( ) {
325
328
ConstKind :: Unevaluated ( unevaluated) => {
@@ -328,26 +331,47 @@ impl<'tcx> Const<'tcx> {
328
331
let ( param_env, unevaluated) = unevaluated. prepare_for_eval ( tcx, param_env) ;
329
332
// try to resolve e.g. associated constants to their definition on an impl, and then
330
333
// evaluate the const.
331
- let Ok ( c) = tcx. const_eval_resolve_for_typeck ( param_env, unevaluated, span) ? else {
332
- // This can happen when we run on ill-typed code.
333
- let e = tcx. dcx ( ) . span_delayed_bug (
334
- span,
335
- "`ty::Const::eval` called on a non-valtree-compatible type" ,
336
- ) ;
337
- return Err ( e. into ( ) ) ;
338
- } ;
339
- Ok ( ( tcx. type_of ( unevaluated. def ) . instantiate ( tcx, unevaluated. args ) , c) )
334
+ match tcx. const_eval_resolve_for_typeck ( param_env, unevaluated, span) {
335
+ Ok ( Ok ( c) ) => {
336
+ Ok ( ( tcx. type_of ( unevaluated. def ) . instantiate ( tcx, unevaluated. args ) , c) )
337
+ }
338
+ Ok ( Err ( bad_ty) ) => Err ( Either :: Left ( bad_ty) ) ,
339
+ Err ( err) => Err ( Either :: Right ( err. into ( ) ) ) ,
340
+ }
340
341
}
341
342
ConstKind :: Value ( ty, val) => Ok ( ( ty, val) ) ,
342
- ConstKind :: Error ( g) => Err ( g. into ( ) ) ,
343
+ ConstKind :: Error ( g) => Err ( Either :: Right ( g. into ( ) ) ) ,
343
344
ConstKind :: Param ( _)
344
345
| ConstKind :: Infer ( _)
345
346
| ConstKind :: Bound ( _, _)
346
347
| ConstKind :: Placeholder ( _)
347
- | ConstKind :: Expr ( _) => Err ( ErrorHandled :: TooGeneric ( span) ) ,
348
+ | ConstKind :: Expr ( _) => Err ( Either :: Right ( ErrorHandled :: TooGeneric ( span) ) ) ,
348
349
}
349
350
}
350
351
352
+ /// Returns the evaluated constant
353
+ #[ inline]
354
+ pub fn eval (
355
+ self ,
356
+ tcx : TyCtxt < ' tcx > ,
357
+ param_env : ParamEnv < ' tcx > ,
358
+ span : Span ,
359
+ ) -> Result < ( Ty < ' tcx > , ValTree < ' tcx > ) , ErrorHandled > {
360
+ self . eval_valtree ( tcx, param_env, span) . map_err ( |err| {
361
+ match err {
362
+ Either :: Right ( err) => err,
363
+ Either :: Left ( _bad_ty) => {
364
+ // This can happen when we run on ill-typed code.
365
+ let e = tcx. dcx ( ) . span_delayed_bug (
366
+ span,
367
+ "`ty::Const::eval` called on a non-valtree-compatible type" ,
368
+ ) ;
369
+ e. into ( )
370
+ }
371
+ }
372
+ } )
373
+ }
374
+
351
375
/// Normalizes the constant to a value or an error if possible.
352
376
#[ inline]
353
377
pub fn normalize ( self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> Self {
0 commit comments