@@ -9,7 +9,7 @@ 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:: { InternalSubsts , 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
@@ -2901,14 +2901,19 @@ impl<'tcx> ConstantKind<'tcx> {
2901
2901
2902
2902
/// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
2903
2903
/// converted to a constant, everything else becomes `Unevaluated`.
2904
- pub fn from_anon_const ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) -> Self {
2905
- Self :: from_opt_const_arg_anon_const ( tcx, ty:: WithOptConstParam :: unknown ( def_id) )
2904
+ pub fn from_anon_const (
2905
+ tcx : TyCtxt < ' tcx > ,
2906
+ def_id : LocalDefId ,
2907
+ param_env : ty:: ParamEnv < ' tcx > ,
2908
+ ) -> Self {
2909
+ Self :: from_opt_const_arg_anon_const ( tcx, ty:: WithOptConstParam :: unknown ( def_id) , param_env)
2906
2910
}
2907
2911
2908
2912
#[ instrument( skip( tcx) , level = "debug" ) ]
2909
2913
fn from_opt_const_arg_anon_const (
2910
2914
tcx : TyCtxt < ' tcx > ,
2911
2915
def : ty:: WithOptConstParam < LocalDefId > ,
2916
+ param_env : ty:: ParamEnv < ' tcx > ,
2912
2917
) -> Self {
2913
2918
let body_id = match tcx. hir ( ) . get_by_def_id ( def. did ) {
2914
2919
hir:: Node :: AnonConst ( ac) => ac. body ,
@@ -2921,11 +2926,72 @@ impl<'tcx> ConstantKind<'tcx> {
2921
2926
let expr = & tcx. hir ( ) . body ( body_id) . value ;
2922
2927
debug ! ( ?expr) ;
2923
2928
2929
+ // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
2930
+ // currently have to be wrapped in curly brackets, so it's necessary to special-case.
2931
+ let expr = match & expr. kind {
2932
+ hir:: ExprKind :: Block ( block, _) if block. stmts . is_empty ( ) && block. expr . is_some ( ) => {
2933
+ block. expr . as_ref ( ) . unwrap ( )
2934
+ }
2935
+ _ => expr,
2936
+ } ;
2937
+
2924
2938
let ty = tcx. type_of ( def. def_id_for_type_of ( ) ) ;
2925
2939
2926
- match Self :: try_eval_lit_or_param ( tcx, ty, expr) {
2927
- Some ( v) => v,
2928
- None => {
2940
+ // FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
2941
+ // does not provide the parents generics to anonymous constants. We still allow generic const
2942
+ // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
2943
+ // ever try to substitute the generic parameters in their bodies.
2944
+ //
2945
+ // While this doesn't happen as these constants are always used as `ty::ConstKind::Param`, it does
2946
+ // cause issues if we were to remove that special-case and try to evaluate the constant instead.
2947
+ use hir:: { def:: DefKind :: ConstParam , def:: Res , ExprKind , Path , QPath } ;
2948
+ match expr. kind {
2949
+ ExprKind :: Path ( QPath :: Resolved ( _, & Path { res : Res :: Def ( ConstParam , def_id) , .. } ) ) => {
2950
+ // Find the name and index of the const parameter by indexing the generics of
2951
+ // the parent item and construct a `ParamConst`.
2952
+ let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id. expect_local ( ) ) ;
2953
+ let item_id = tcx. hir ( ) . get_parent_node ( hir_id) ;
2954
+ let item_def_id = tcx. hir ( ) . local_def_id ( item_id) ;
2955
+ let generics = tcx. generics_of ( item_def_id. to_def_id ( ) ) ;
2956
+ let index = generics. param_def_id_to_index [ & def_id] ;
2957
+ let name = tcx. hir ( ) . name ( hir_id) ;
2958
+ let ty_const = tcx. mk_const ( ty:: ConstS {
2959
+ val : ty:: ConstKind :: Param ( ty:: ParamConst :: new ( index, name) ) ,
2960
+ ty,
2961
+ } ) ;
2962
+
2963
+ return Self :: Ty ( ty_const) ;
2964
+ }
2965
+ _ => { }
2966
+ }
2967
+
2968
+ let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def. did ) ;
2969
+ let parent_substs = if let Some ( parent_hir_id) = tcx. hir ( ) . find_parent_node ( hir_id) {
2970
+ if let Some ( parent_did) = tcx. hir ( ) . opt_local_def_id ( parent_hir_id) {
2971
+ InternalSubsts :: identity_for_item ( tcx, parent_did. to_def_id ( ) )
2972
+ } else {
2973
+ tcx. mk_substs ( Vec :: < GenericArg < ' tcx > > :: new ( ) . into_iter ( ) )
2974
+ }
2975
+ } else {
2976
+ tcx. mk_substs ( Vec :: < GenericArg < ' tcx > > :: new ( ) . into_iter ( ) )
2977
+ } ;
2978
+ debug ! ( ?parent_substs) ;
2979
+
2980
+ let did = def. did . to_def_id ( ) ;
2981
+ let child_substs = InternalSubsts :: identity_for_item ( tcx, did) ;
2982
+ let substs = tcx. mk_substs ( parent_substs. into_iter ( ) . chain ( child_substs. into_iter ( ) ) ) ;
2983
+ debug ! ( ?substs) ;
2984
+
2985
+ let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def. did ) ;
2986
+ let span = tcx. hir ( ) . span ( hir_id) ;
2987
+ let uneval = ty:: Unevaluated :: new ( def. to_global ( ) , substs) ;
2988
+ debug ! ( ?span, ?param_env) ;
2989
+
2990
+ match tcx. const_eval_resolve ( param_env, uneval, Some ( span) ) {
2991
+ Ok ( val) => Self :: Val ( val, ty) ,
2992
+ Err ( _) => {
2993
+ // Error was handled in `const_eval_resolve`. Here we just create a
2994
+ // new unevaluated const and error hard later in codegen
2929
2995
let ty_const = tcx. mk_const ( ty:: ConstS {
2930
2996
val : ty:: ConstKind :: Unevaluated ( ty:: Unevaluated {
2931
2997
def : def. to_global ( ) ,
@@ -2934,6 +3000,7 @@ impl<'tcx> ConstantKind<'tcx> {
2934
3000
} ) ,
2935
3001
ty,
2936
3002
} ) ;
3003
+
2937
3004
Self :: Ty ( ty_const)
2938
3005
}
2939
3006
}
0 commit comments