@@ -25,15 +25,13 @@ use crate::traits::ObligationCtxt;
2525#[ instrument( skip( infcx) , level = "debug" ) ]
2626pub fn is_const_evaluatable < ' tcx > (
2727 infcx : & InferCtxt < ' tcx > ,
28- ct : ty:: Const < ' tcx > ,
28+ unexpanded_ct : ty:: Const < ' tcx > ,
2929 param_env : ty:: ParamEnv < ' tcx > ,
3030 span : Span ,
3131) -> Result < ( ) , NotConstEvaluatable > {
3232 let tcx = infcx. tcx ;
33- let uv = match ct. kind ( ) {
34- ty:: ConstKind :: Unevaluated ( uv) => uv,
35- // FIXME(generic_const_exprs): this seems wrong but I couldn't find a way to get this to trigger
36- ty:: ConstKind :: Expr ( _) => bug ! ( "unexpected expr in `is_const_evaluatable: {ct:?}" ) ,
33+ match unexpanded_ct. kind ( ) {
34+ ty:: ConstKind :: Unevaluated ( _) | ty:: ConstKind :: Expr ( _) => ( ) ,
3735 ty:: ConstKind :: Param ( _)
3836 | ty:: ConstKind :: Bound ( _, _)
3937 | ty:: ConstKind :: Placeholder ( _)
@@ -43,7 +41,7 @@ pub fn is_const_evaluatable<'tcx>(
4341 } ;
4442
4543 if tcx. features ( ) . generic_const_exprs {
46- let ct = tcx. expand_abstract_consts ( ct ) ;
44+ let ct = tcx. expand_abstract_consts ( unexpanded_ct ) ;
4745
4846 let is_anon_ct = if let ty:: ConstKind :: Unevaluated ( uv) = ct. kind ( ) {
4947 tcx. def_kind ( uv. def . did ) == DefKind :: AnonConst
@@ -62,18 +60,40 @@ pub fn is_const_evaluatable<'tcx>(
6260 }
6361 }
6462
65- let concrete = infcx. const_eval_resolve ( param_env, uv, Some ( span) ) ;
66- match concrete {
67- Err ( ErrorHandled :: TooGeneric ) => Err ( NotConstEvaluatable :: Error (
68- infcx
69- . tcx
70- . sess
71- . delay_span_bug ( span, "Missing value for constant, but no error reported?" ) ,
72- ) ) ,
73- Err ( ErrorHandled :: Reported ( e) ) => Err ( NotConstEvaluatable :: Error ( e) ) ,
74- Ok ( _) => Ok ( ( ) ) ,
63+ match unexpanded_ct. kind ( ) {
64+ ty:: ConstKind :: Expr ( _) => {
65+ // FIXME(generic_const_exprs): we have a `ConstKind::Expr` which is fully concrete, but
66+ // currently it is not possible to evaluate `ConstKind::Expr` so we are unable to tell if it
67+ // is evaluatable or not. For now we just ICE until this is implemented this.
68+ Err ( NotConstEvaluatable :: Error ( tcx. sess . delay_span_bug (
69+ span,
70+ "evaluating `ConstKind::Expr` is not currently supported" ,
71+ ) ) )
72+ }
73+ ty:: ConstKind :: Unevaluated ( uv) => {
74+ let concrete = infcx. const_eval_resolve ( param_env, uv, Some ( span) ) ;
75+ match concrete {
76+ Err ( ErrorHandled :: TooGeneric ) => {
77+ Err ( NotConstEvaluatable :: Error ( infcx. tcx . sess . delay_span_bug (
78+ span,
79+ "Missing value for constant, but no error reported?" ,
80+ ) ) )
81+ }
82+ Err ( ErrorHandled :: Reported ( e) ) => Err ( NotConstEvaluatable :: Error ( e) ) ,
83+ Ok ( _) => Ok ( ( ) ) ,
84+ }
85+ }
86+ _ => bug ! ( "unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`" ) ,
7587 }
7688 } else {
89+ let uv = match unexpanded_ct. kind ( ) {
90+ ty:: ConstKind :: Unevaluated ( uv) => uv,
91+ ty:: ConstKind :: Expr ( _) => {
92+ bug ! ( "`ConstKind::Expr` without `feature(generic_const_exprs)` enabled" )
93+ }
94+ _ => bug ! ( "unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`" ) ,
95+ } ;
96+
7797 // FIXME: We should only try to evaluate a given constant here if it is fully concrete
7898 // as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`.
7999 //
@@ -92,7 +112,7 @@ pub fn is_const_evaluatable<'tcx>(
92112 && satisfied_from_param_env (
93113 tcx,
94114 infcx,
95- tcx. expand_abstract_consts ( ct ) ,
115+ tcx. expand_abstract_consts ( unexpanded_ct ) ,
96116 param_env,
97117 ) =>
98118 {
@@ -152,6 +172,7 @@ fn satisfied_from_param_env<'tcx>(
152172 impl < ' a , ' tcx > TypeVisitor < ' tcx > for Visitor < ' a , ' tcx > {
153173 type BreakTy = ( ) ;
154174 fn visit_const ( & mut self , c : ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
175+ debug ! ( "is_const_evaluatable: candidate={:?}" , c) ;
155176 if let Ok ( ( ) ) = self . infcx . commit_if_ok ( |_| {
156177 let ocx = ObligationCtxt :: new_in_snapshot ( self . infcx ) ;
157178 if let Ok ( ( ) ) = ocx. eq ( & ObligationCause :: dummy ( ) , self . param_env , c. ty ( ) , self . ct . ty ( ) )
@@ -187,13 +208,14 @@ fn satisfied_from_param_env<'tcx>(
187208 let result = b_ct. visit_with ( & mut v) ;
188209
189210 if let ControlFlow :: Break ( ( ) ) = result {
190- debug ! ( "is_const_evaluatable: abstract_const ~~> ok " ) ;
211+ debug ! ( "is_const_evaluatable: yes " ) ;
191212 return true ;
192213 }
193214 }
194215 _ => { } // don't care
195216 }
196217 }
197218
219+ debug ! ( "is_const_evaluatable: no" ) ;
198220 false
199221}
0 commit comments