@@ -13,7 +13,7 @@ use rustc_hir::def::DefKind;
1313use rustc_index:: vec:: IndexVec ;
1414use rustc_infer:: infer:: InferCtxt ;
1515use rustc_middle:: mir;
16- use rustc_middle:: mir:: interpret:: ErrorHandled ;
16+ use rustc_middle:: mir:: interpret:: { ConstValue , ErrorHandled } ;
1717use rustc_middle:: thir;
1818use rustc_middle:: thir:: abstract_const:: { self , Node , NodeId , NotConstEvaluatable } ;
1919use rustc_middle:: ty:: subst:: { Subst , SubstsRef } ;
@@ -33,7 +33,8 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
3333 param_env : ty:: ParamEnv < ' tcx > ,
3434 span : Span ,
3535) -> Result < ( ) , NotConstEvaluatable > {
36- debug ! ( "is_const_evaluatable({:?})" , uv) ;
36+ debug ! ( "param_env: {:#?}" , param_env) ;
37+
3738 if infcx. tcx . features ( ) . generic_const_exprs {
3839 let tcx = infcx. tcx ;
3940 match AbstractConst :: new ( tcx, uv) ? {
@@ -225,6 +226,61 @@ impl<'tcx> AbstractConst<'tcx> {
225226 Node :: Binop ( _, _, _) | Node :: UnaryOp ( _, _) | Node :: FunctionCall ( _, _) => node,
226227 }
227228 }
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+ }
228284}
229285
230286struct AbstractConstBuilder < ' a , ' tcx > {
0 commit comments