@@ -9,13 +9,13 @@ use crate::ty::adjustment::PointerCast;
9
9
use crate :: ty:: codec:: { TyDecoder , TyEncoder } ;
10
10
use crate :: ty:: fold:: { FallibleTypeFolder , TypeFoldable , TypeVisitor } ;
11
11
use crate :: ty:: print:: { FmtPrinter , Printer } ;
12
- use crate :: ty:: subst:: { Subst , SubstsRef } ;
12
+ use crate :: ty:: subst:: { GenericArg , InternalSubsts , Subst , SubstsRef } ;
13
13
use crate :: ty:: { self , List , Ty , TyCtxt } ;
14
14
use crate :: ty:: { AdtDef , InstanceDef , Region , ScalarInt , UserTypeAnnotationIndex } ;
15
15
16
16
use rustc_errors:: ErrorGuaranteed ;
17
17
use rustc_hir:: def:: { CtorKind , Namespace } ;
18
- use rustc_hir:: def_id:: { DefId , CRATE_DEF_INDEX } ;
18
+ use rustc_hir:: def_id:: { DefId , LocalDefId , CRATE_DEF_INDEX } ;
19
19
use rustc_hir:: { self , GeneratorKind } ;
20
20
use rustc_hir:: { self as hir, HirId } ;
21
21
use rustc_session:: Session ;
@@ -2921,6 +2921,16 @@ impl<'tcx> ConstantKind<'tcx> {
2921
2921
}
2922
2922
}
2923
2923
2924
+ pub fn try_val ( & self ) -> Option < ConstValue < ' tcx > > {
2925
+ match self {
2926
+ ConstantKind :: Ty ( c) => match c. val ( ) {
2927
+ ty:: ConstKind :: Value ( v) => Some ( v) ,
2928
+ _ => None ,
2929
+ } ,
2930
+ ConstantKind :: Val ( v, _) => Some ( * v) ,
2931
+ }
2932
+ }
2933
+
2924
2934
#[ inline]
2925
2935
pub fn try_to_value ( self ) -> Option < interpret:: ConstValue < ' tcx > > {
2926
2936
match self {
@@ -2949,6 +2959,32 @@ impl<'tcx> ConstantKind<'tcx> {
2949
2959
self . try_to_scalar_int ( ) ?. try_into ( ) . ok ( )
2950
2960
}
2951
2961
2962
+ #[ inline]
2963
+ pub fn eval ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> Self {
2964
+ match self {
2965
+ Self :: Ty ( c) => {
2966
+ // FIXME Need to use a different evaluation function that directly returns a `ConstValue`
2967
+ // if evaluation succeeds and does not create a ValTree first
2968
+ if let Some ( val) = c. val ( ) . try_eval ( tcx, param_env) {
2969
+ match val {
2970
+ Ok ( val) => Self :: Val ( val, c. ty ( ) ) ,
2971
+ Err ( _) => Self :: Ty ( tcx. const_error ( self . ty ( ) ) ) ,
2972
+ }
2973
+ } else {
2974
+ self
2975
+ }
2976
+ }
2977
+ Self :: Val ( _, _) => self ,
2978
+ }
2979
+ }
2980
+
2981
+ /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
2982
+ #[ inline]
2983
+ pub fn eval_bits ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > , ty : Ty < ' tcx > ) -> u128 {
2984
+ self . try_eval_bits ( tcx, param_env, ty)
2985
+ . unwrap_or_else ( || bug ! ( "expected bits of {:#?}, got {:#?}" , ty, self ) )
2986
+ }
2987
+
2952
2988
#[ inline]
2953
2989
pub fn try_eval_bits (
2954
2990
& self ,
@@ -2983,25 +3019,142 @@ impl<'tcx> ConstantKind<'tcx> {
2983
3019
}
2984
3020
}
2985
3021
3022
+ pub fn from_bits (
3023
+ tcx : TyCtxt < ' tcx > ,
3024
+ bits : u128 ,
3025
+ param_env_ty : ty:: ParamEnvAnd < ' tcx , Ty < ' tcx > > ,
3026
+ ) -> Self {
3027
+ let size = tcx
3028
+ . layout_of ( param_env_ty)
3029
+ . unwrap_or_else ( |e| {
3030
+ bug ! ( "could not compute layout for {:?}: {:?}" , param_env_ty. value, e)
3031
+ } )
3032
+ . size ;
3033
+ let cv = ConstValue :: Scalar ( Scalar :: from_uint ( bits, size) ) ;
3034
+
3035
+ Self :: Val ( cv, param_env_ty. value )
3036
+ }
3037
+
2986
3038
pub fn from_bool ( tcx : TyCtxt < ' tcx > , v : bool ) -> Self {
2987
3039
let cv = ConstValue :: from_bool ( v) ;
2988
3040
Self :: Val ( cv, tcx. types . bool )
2989
3041
}
2990
3042
2991
- pub fn from_zero_sized ( ty : Ty < ' tcx > ) -> Self {
3043
+ pub fn zero_sized ( ty : Ty < ' tcx > ) -> Self {
2992
3044
let cv = ConstValue :: Scalar ( Scalar :: ZST ) ;
2993
3045
Self :: Val ( cv, ty)
2994
3046
}
2995
3047
2996
3048
pub fn from_usize ( tcx : TyCtxt < ' tcx > , n : u64 ) -> Self {
2997
3049
let ty = tcx. types . usize ;
2998
- let size = tcx
2999
- . layout_of ( ty:: ParamEnv :: empty ( ) . and ( ty) )
3000
- . unwrap_or_else ( |e| bug ! ( "could not compute layout for {:?}: {:?}" , ty, e) )
3001
- . size ;
3002
- let cv = ConstValue :: Scalar ( Scalar :: from_uint ( n as u128 , size) ) ;
3050
+ Self :: from_bits ( tcx, n as u128 , ty:: ParamEnv :: empty ( ) . and ( ty) )
3051
+ }
3003
3052
3004
- Self :: Val ( cv, ty)
3053
+ /// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
3054
+ /// converted to a constant, everything else becomes `Unevaluated`.
3055
+ pub fn from_anon_const (
3056
+ tcx : TyCtxt < ' tcx > ,
3057
+ def_id : LocalDefId ,
3058
+ param_env : ty:: ParamEnv < ' tcx > ,
3059
+ ) -> Self {
3060
+ Self :: from_opt_const_arg_anon_const ( tcx, ty:: WithOptConstParam :: unknown ( def_id) , param_env)
3061
+ }
3062
+
3063
+ #[ instrument( skip( tcx) , level = "debug" ) ]
3064
+ fn from_opt_const_arg_anon_const (
3065
+ tcx : TyCtxt < ' tcx > ,
3066
+ def : ty:: WithOptConstParam < LocalDefId > ,
3067
+ param_env : ty:: ParamEnv < ' tcx > ,
3068
+ ) -> Self {
3069
+ let body_id = match tcx. hir ( ) . get_by_def_id ( def. did ) {
3070
+ hir:: Node :: AnonConst ( ac) => ac. body ,
3071
+ _ => span_bug ! (
3072
+ tcx. def_span( def. did. to_def_id( ) ) ,
3073
+ "from_anon_const can only process anonymous constants"
3074
+ ) ,
3075
+ } ;
3076
+
3077
+ let expr = & tcx. hir ( ) . body ( body_id) . value ;
3078
+ debug ! ( ?expr) ;
3079
+
3080
+ // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
3081
+ // currently have to be wrapped in curly brackets, so it's necessary to special-case.
3082
+ let expr = match & expr. kind {
3083
+ hir:: ExprKind :: Block ( block, _) if block. stmts . is_empty ( ) && block. expr . is_some ( ) => {
3084
+ block. expr . as_ref ( ) . unwrap ( )
3085
+ }
3086
+ _ => expr,
3087
+ } ;
3088
+
3089
+ let ty = tcx. type_of ( def. def_id_for_type_of ( ) ) ;
3090
+
3091
+ // FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
3092
+ // does not provide the parents generics to anonymous constants. We still allow generic const
3093
+ // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
3094
+ // ever try to substitute the generic parameters in their bodies.
3095
+ //
3096
+ // While this doesn't happen as these constants are always used as `ty::ConstKind::Param`, it does
3097
+ // cause issues if we were to remove that special-case and try to evaluate the constant instead.
3098
+ use hir:: { def:: DefKind :: ConstParam , def:: Res , ExprKind , Path , QPath } ;
3099
+ match expr. kind {
3100
+ ExprKind :: Path ( QPath :: Resolved ( _, & Path { res : Res :: Def ( ConstParam , def_id) , .. } ) ) => {
3101
+ // Find the name and index of the const parameter by indexing the generics of
3102
+ // the parent item and construct a `ParamConst`.
3103
+ let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id. expect_local ( ) ) ;
3104
+ let item_id = tcx. hir ( ) . get_parent_node ( hir_id) ;
3105
+ let item_def_id = tcx. hir ( ) . local_def_id ( item_id) ;
3106
+ let generics = tcx. generics_of ( item_def_id. to_def_id ( ) ) ;
3107
+ let index = generics. param_def_id_to_index [ & def_id] ;
3108
+ let name = tcx. hir ( ) . name ( hir_id) ;
3109
+ let ty_const = tcx. mk_const ( ty:: ConstS {
3110
+ val : ty:: ConstKind :: Param ( ty:: ParamConst :: new ( index, name) ) ,
3111
+ ty,
3112
+ } ) ;
3113
+
3114
+ return Self :: Ty ( ty_const) ;
3115
+ }
3116
+ _ => { }
3117
+ }
3118
+
3119
+ let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def. did ) ;
3120
+ let parent_substs = if let Some ( parent_hir_id) = tcx. hir ( ) . find_parent_node ( hir_id) {
3121
+ if let Some ( parent_did) = tcx. hir ( ) . opt_local_def_id ( parent_hir_id) {
3122
+ InternalSubsts :: identity_for_item ( tcx, parent_did. to_def_id ( ) )
3123
+ } else {
3124
+ tcx. mk_substs ( Vec :: < GenericArg < ' tcx > > :: new ( ) . into_iter ( ) )
3125
+ }
3126
+ } else {
3127
+ tcx. mk_substs ( Vec :: < GenericArg < ' tcx > > :: new ( ) . into_iter ( ) )
3128
+ } ;
3129
+ debug ! ( ?parent_substs) ;
3130
+
3131
+ let did = def. did . to_def_id ( ) ;
3132
+ let child_substs = InternalSubsts :: identity_for_item ( tcx, did) ;
3133
+ let substs = tcx. mk_substs ( parent_substs. into_iter ( ) . chain ( child_substs. into_iter ( ) ) ) ;
3134
+ debug ! ( ?substs) ;
3135
+
3136
+ let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def. did ) ;
3137
+ let span = tcx. hir ( ) . span ( hir_id) ;
3138
+ let uneval = ty:: Unevaluated :: new ( def. to_global ( ) , substs) ;
3139
+ debug ! ( ?span, ?param_env) ;
3140
+
3141
+ match tcx. const_eval_resolve ( param_env, uneval, Some ( span) ) {
3142
+ Ok ( val) => Self :: Val ( val, ty) ,
3143
+ Err ( _) => {
3144
+ // Error was handled in `const_eval_resolve`. Here we just create a
3145
+ // new unevaluated const and error hard later in codegen
3146
+ let ty_const = tcx. mk_const ( ty:: ConstS {
3147
+ val : ty:: ConstKind :: Unevaluated ( ty:: Unevaluated {
3148
+ def : def. to_global ( ) ,
3149
+ substs : InternalSubsts :: identity_for_item ( tcx, def. did . to_def_id ( ) ) ,
3150
+ promoted : None ,
3151
+ } ) ,
3152
+ ty,
3153
+ } ) ;
3154
+
3155
+ Self :: Ty ( ty_const)
3156
+ }
3157
+ }
3005
3158
}
3006
3159
}
3007
3160
0 commit comments