@@ -9,7 +9,7 @@ use crate::ty::adjustment::PointerCast;
99use crate :: ty:: codec:: { TyDecoder , TyEncoder } ;
1010use crate :: ty:: fold:: { FallibleTypeFolder , TypeFoldable , TypeVisitor } ;
1111use crate :: ty:: print:: { FmtPrinter , Printer } ;
12- use crate :: ty:: subst:: { InternalSubsts , Subst , SubstsRef } ;
12+ use crate :: ty:: subst:: { GenericArg , InternalSubsts , Subst , SubstsRef } ;
1313use crate :: ty:: { self , List , Ty , TyCtxt } ;
1414use crate :: ty:: { AdtDef , InstanceDef , Region , ScalarInt , UserTypeAnnotationIndex } ;
1515
@@ -2901,14 +2901,19 @@ impl<'tcx> ConstantKind<'tcx> {
29012901
29022902 /// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
29032903 /// 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)
29062910 }
29072911
29082912 #[ instrument( skip( tcx) , level = "debug" ) ]
29092913 fn from_opt_const_arg_anon_const (
29102914 tcx : TyCtxt < ' tcx > ,
29112915 def : ty:: WithOptConstParam < LocalDefId > ,
2916+ param_env : ty:: ParamEnv < ' tcx > ,
29122917 ) -> Self {
29132918 let body_id = match tcx. hir ( ) . get_by_def_id ( def. did ) {
29142919 hir:: Node :: AnonConst ( ac) => ac. body ,
@@ -2921,11 +2926,72 @@ impl<'tcx> ConstantKind<'tcx> {
29212926 let expr = & tcx. hir ( ) . body ( body_id) . value ;
29222927 debug ! ( ?expr) ;
29232928
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+
29242938 let ty = tcx. type_of ( def. def_id_for_type_of ( ) ) ;
29252939
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
29292995 let ty_const = tcx. mk_const ( ty:: ConstS {
29302996 val : ty:: ConstKind :: Unevaluated ( ty:: Unevaluated {
29312997 def : def. to_global ( ) ,
@@ -2934,6 +3000,7 @@ impl<'tcx> ConstantKind<'tcx> {
29343000 } ) ,
29353001 ty,
29363002 } ) ;
3003+
29373004 Self :: Ty ( ty_const)
29383005 }
29393006 }
0 commit comments