@@ -2299,18 +2299,6 @@ impl<'tcx> ConstantKind<'tcx> {
22992299 }
23002300 }
23012301
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-
23142302 #[ inline]
23152303 pub fn try_to_scalar ( self ) -> Option < Scalar > {
23162304 match self {
@@ -2342,37 +2330,59 @@ impl<'tcx> ConstantKind<'tcx> {
23422330 }
23432331
23442332 #[ 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)
23532345 } 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) ) ) ;
23552349 }
23562350 }
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 ( ) ) )
23672365 }
2366+ Err ( ErrorHandled :: TooGeneric ) => self ,
23682367 }
23692368 }
23702369
2371- /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
23722370 #[ 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 ( )
23762386 }
23772387
23782388 #[ inline]
@@ -2382,59 +2392,38 @@ impl<'tcx> ConstantKind<'tcx> {
23822392 param_env : ty:: ParamEnv < ' tcx > ,
23832393 ty : Ty < ' tcx > ,
23842394 ) -> 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 ( )
24062399 }
24072400
2401+ /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
24082402 #[ 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 ) )
24202406 }
24212407
24222408 #[ inline]
24232409 pub fn try_eval_target_usize (
2424- & self ,
2410+ self ,
24252411 tcx : TyCtxt < ' tcx > ,
24262412 param_env : ty:: ParamEnv < ' tcx > ,
24272413 ) -> 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 ( )
24382427 }
24392428
24402429 #[ inline]
@@ -2576,7 +2565,7 @@ impl<'tcx> ConstantKind<'tcx> {
25762565 }
25772566 }
25782567
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 {
25802569 match c. kind ( ) {
25812570 ty:: ConstKind :: Value ( valtree) => {
25822571 let const_val = tcx. valtree_to_const_val ( ( c. ty ( ) , valtree) ) ;
@@ -2610,6 +2599,11 @@ impl<'tcx> UnevaluatedConst<'tcx> {
26102599 pub fn new ( def : DefId , args : GenericArgsRef < ' tcx > ) -> UnevaluatedConst < ' tcx > {
26112600 UnevaluatedConst { def, args, promoted : Default :: default ( ) }
26122601 }
2602+
2603+ #[ inline]
2604+ pub fn from_instance ( instance : ty:: Instance < ' tcx > ) -> Self {
2605+ UnevaluatedConst :: new ( instance. def_id ( ) , instance. args )
2606+ }
26132607}
26142608
26152609/// A collection of projections into user types.
@@ -2884,7 +2878,7 @@ fn pretty_print_const_value<'tcx>(
28842878 }
28852879 }
28862880 ( 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 ( ) ;
28882882 // cast is ok because we already checked for pointer size (32 or 64 bit) above
28892883 let range = AllocRange { start : offset, size : Size :: from_bytes ( n) } ;
28902884 let byte_str = alloc. inner ( ) . get_bytes_strip_provenance ( & tcx, range) . unwrap ( ) ;
0 commit comments