@@ -13,7 +13,7 @@ use rustc_hir::def::DefKind;
13
13
use rustc_index:: vec:: IndexVec ;
14
14
use rustc_infer:: infer:: InferCtxt ;
15
15
use rustc_middle:: mir;
16
- use rustc_middle:: mir:: interpret:: ErrorHandled ;
16
+ use rustc_middle:: mir:: interpret:: { ConstValue , ErrorHandled } ;
17
17
use rustc_middle:: thir;
18
18
use rustc_middle:: thir:: abstract_const:: { self , Node , NodeId , NotConstEvaluatable } ;
19
19
use rustc_middle:: ty:: subst:: { Subst , SubstsRef } ;
@@ -33,7 +33,8 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
33
33
param_env : ty:: ParamEnv < ' tcx > ,
34
34
span : Span ,
35
35
) -> Result < ( ) , NotConstEvaluatable > {
36
- debug ! ( "is_const_evaluatable({:?})" , uv) ;
36
+ debug ! ( "param_env: {:#?}" , param_env) ;
37
+
37
38
if infcx. tcx . features ( ) . generic_const_exprs {
38
39
let tcx = infcx. tcx ;
39
40
match AbstractConst :: new ( tcx, uv) ? {
@@ -225,6 +226,61 @@ impl<'tcx> AbstractConst<'tcx> {
225
226
Node :: Binop ( _, _, _) | Node :: UnaryOp ( _, _) | Node :: FunctionCall ( _, _) => node,
226
227
}
227
228
}
229
+
230
+ /// Used for diagnostics only.
231
+ /// Tries to create a String of an `AbstractConst` while recursively applying substs. This
232
+ /// will fail for `AbstractConst`s that contain `Leaf`s including inference variables or errors,
233
+ /// and any non-Leaf `Node`s other than `BinOp` and `UnOp`.
234
+ pub ( crate ) fn try_print_with_replacing_substs ( mut self , tcx : TyCtxt < ' tcx > ) -> Option < String > {
235
+ // try to replace substs
236
+ while let abstract_const:: Node :: Leaf ( ct) = self . root ( tcx) {
237
+ match AbstractConst :: from_const ( tcx, ct) {
238
+ Ok ( Some ( act) ) => self = act,
239
+ Ok ( None ) => break ,
240
+ Err ( _) => bug ! ( "should be able to create AbstractConst here" ) ,
241
+ }
242
+ }
243
+
244
+ match self . root ( tcx) {
245
+ abstract_const:: Node :: Leaf ( ct) => match ct. val {
246
+ ty:: ConstKind :: Error ( _) | ty:: ConstKind :: Infer ( _) => return None ,
247
+ ty:: ConstKind :: Param ( c) => return Some ( format ! ( "{}" , c) ) ,
248
+ ty:: ConstKind :: Value ( ConstValue :: Scalar ( scalar) ) => match scalar. to_i64 ( ) {
249
+ Ok ( s) => return Some ( format ! ( "{}" , s) ) ,
250
+ Err ( _) => return None ,
251
+ } ,
252
+ _ => return None ,
253
+ } ,
254
+ abstract_const:: Node :: Binop ( op, l, r) => {
255
+ let op = match op. try_as_string ( ) {
256
+ Some ( o) => o,
257
+ None => return None ,
258
+ } ;
259
+
260
+ let left = self . subtree ( l) . try_print_with_replacing_substs ( tcx) ;
261
+ debug ! ( ?left) ;
262
+
263
+ let right = self . subtree ( r) . try_print_with_replacing_substs ( tcx) ;
264
+ debug ! ( ?right) ;
265
+
266
+ match ( left, right) {
267
+ ( Some ( l) , Some ( r) ) => {
268
+ return Some ( format ! ( "{} {} {}" , l, op, r) ) ;
269
+ }
270
+ _ => return None ,
271
+ }
272
+ }
273
+ abstract_const:: Node :: UnaryOp ( op, v) => {
274
+ match self . subtree ( v) . try_print_with_replacing_substs ( tcx) {
275
+ Some ( operand) => {
276
+ return Some ( format ! ( "{}{}" , op, operand) ) ;
277
+ }
278
+ None => return None ,
279
+ }
280
+ }
281
+ _ => return None ,
282
+ }
283
+ }
228
284
}
229
285
230
286
struct AbstractConstBuilder < ' a , ' tcx > {
0 commit comments