@@ -25,15 +25,13 @@ use crate::traits::ObligationCtxt;
25
25
#[ instrument( skip( infcx) , level = "debug" ) ]
26
26
pub fn is_const_evaluatable < ' tcx > (
27
27
infcx : & InferCtxt < ' tcx > ,
28
- ct : ty:: Const < ' tcx > ,
28
+ unexpanded_ct : ty:: Const < ' tcx > ,
29
29
param_env : ty:: ParamEnv < ' tcx > ,
30
30
span : Span ,
31
31
) -> Result < ( ) , NotConstEvaluatable > {
32
32
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 ( _) => ( ) ,
37
35
ty:: ConstKind :: Param ( _)
38
36
| ty:: ConstKind :: Bound ( _, _)
39
37
| ty:: ConstKind :: Placeholder ( _)
@@ -43,7 +41,7 @@ pub fn is_const_evaluatable<'tcx>(
43
41
} ;
44
42
45
43
if tcx. features ( ) . generic_const_exprs {
46
- let ct = tcx. expand_abstract_consts ( ct ) ;
44
+ let ct = tcx. expand_abstract_consts ( unexpanded_ct ) ;
47
45
48
46
let is_anon_ct = if let ty:: ConstKind :: Unevaluated ( uv) = ct. kind ( ) {
49
47
tcx. def_kind ( uv. def . did ) == DefKind :: AnonConst
@@ -62,18 +60,40 @@ pub fn is_const_evaluatable<'tcx>(
62
60
}
63
61
}
64
62
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:?}`" ) ,
75
87
}
76
88
} 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
+
77
97
// FIXME: We should only try to evaluate a given constant here if it is fully concrete
78
98
// as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`.
79
99
//
@@ -92,7 +112,7 @@ pub fn is_const_evaluatable<'tcx>(
92
112
&& satisfied_from_param_env (
93
113
tcx,
94
114
infcx,
95
- tcx. expand_abstract_consts ( ct ) ,
115
+ tcx. expand_abstract_consts ( unexpanded_ct ) ,
96
116
param_env,
97
117
) =>
98
118
{
@@ -152,6 +172,7 @@ fn satisfied_from_param_env<'tcx>(
152
172
impl < ' a , ' tcx > TypeVisitor < ' tcx > for Visitor < ' a , ' tcx > {
153
173
type BreakTy = ( ) ;
154
174
fn visit_const ( & mut self , c : ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
175
+ debug ! ( "is_const_evaluatable: candidate={:?}" , c) ;
155
176
if let Ok ( ( ) ) = self . infcx . commit_if_ok ( |_| {
156
177
let ocx = ObligationCtxt :: new_in_snapshot ( self . infcx ) ;
157
178
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>(
187
208
let result = b_ct. visit_with ( & mut v) ;
188
209
189
210
if let ControlFlow :: Break ( ( ) ) = result {
190
- debug ! ( "is_const_evaluatable: abstract_const ~~> ok " ) ;
211
+ debug ! ( "is_const_evaluatable: yes " ) ;
191
212
return true ;
192
213
}
193
214
}
194
215
_ => { } // don't care
195
216
}
196
217
}
197
218
219
+ debug ! ( "is_const_evaluatable: no" ) ;
198
220
false
199
221
}
0 commit comments