11use crate :: middle:: resolve_bound_vars as rbv;
22use crate :: mir:: interpret:: { ErrorHandled , LitToConstInput , Scalar } ;
33use crate :: ty:: { self , GenericArgs , ParamEnv , ParamEnvAnd , Ty , TyCtxt , TypeVisitableExt } ;
4+ use either:: Either ;
45use rustc_data_structures:: intern:: Interned ;
56use rustc_error_messages:: MultiSpan ;
67use rustc_hir as hir;
@@ -312,14 +313,16 @@ impl<'tcx> Const<'tcx> {
312313 Self :: from_bits ( tcx, n as u128 , ParamEnv :: empty ( ) . and ( tcx. types . usize ) )
313314 }
314315
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))`.
316319 #[ inline]
317- pub fn eval (
320+ pub fn eval_valtree (
318321 self ,
319322 tcx : TyCtxt < ' tcx > ,
320323 param_env : ParamEnv < ' tcx > ,
321324 span : Span ,
322- ) -> Result < ( Ty < ' tcx > , ValTree < ' tcx > ) , ErrorHandled > {
325+ ) -> Result < ( Ty < ' tcx > , ValTree < ' tcx > ) , Either < Ty < ' tcx > , ErrorHandled > > {
323326 assert ! ( !self . has_escaping_bound_vars( ) , "escaping vars in {self:?}" ) ;
324327 match self . kind ( ) {
325328 ConstKind :: Unevaluated ( unevaluated) => {
@@ -328,26 +331,47 @@ impl<'tcx> Const<'tcx> {
328331 let ( param_env, unevaluated) = unevaluated. prepare_for_eval ( tcx, param_env) ;
329332 // try to resolve e.g. associated constants to their definition on an impl, and then
330333 // 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+ }
340341 }
341342 ConstKind :: Value ( ty, val) => Ok ( ( ty, val) ) ,
342- ConstKind :: Error ( g) => Err ( g. into ( ) ) ,
343+ ConstKind :: Error ( g) => Err ( Either :: Right ( g. into ( ) ) ) ,
343344 ConstKind :: Param ( _)
344345 | ConstKind :: Infer ( _)
345346 | ConstKind :: Bound ( _, _)
346347 | ConstKind :: Placeholder ( _)
347- | ConstKind :: Expr ( _) => Err ( ErrorHandled :: TooGeneric ( span) ) ,
348+ | ConstKind :: Expr ( _) => Err ( Either :: Right ( ErrorHandled :: TooGeneric ( span) ) ) ,
348349 }
349350 }
350351
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+
351375 /// Normalizes the constant to a value or an error if possible.
352376 #[ inline]
353377 pub fn normalize ( self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> Self {
0 commit comments