@@ -11,7 +11,8 @@ use rustc_middle::{
1111use rustc_span:: { source_map:: DUMMY_SP , symbol:: Symbol } ;
1212
1313use crate :: interpret:: {
14- intern_const_alloc_recursive, ConstValue , InternKind , InterpCx , MPlaceTy , MemPlaceMeta , Scalar ,
14+ intern_const_alloc_recursive, ConstValue , InternKind , InterpCx , InterpResult , MPlaceTy ,
15+ MemPlaceMeta , Scalar ,
1516} ;
1617
1718mod error;
@@ -132,42 +133,39 @@ fn const_to_valtree_inner<'tcx>(
132133 }
133134}
134135
135- /// This function uses `unwrap` copiously, because an already validated constant
136- /// must have valid fields and can thus never fail outside of compiler bugs. However, it is
137- /// invoked from the pretty printer, where it can receive enums with no variants and e.g.
138- /// `read_discriminant` needs to be able to handle that.
139- pub ( crate ) fn destructure_const < ' tcx > (
136+ /// This function should never fail for validated constants. However, it is also invoked from the
137+ /// pretty printer which might attempt to format invalid constants and in that case it might fail.
138+ pub ( crate ) fn try_destructure_const < ' tcx > (
140139 tcx : TyCtxt < ' tcx > ,
141140 param_env : ty:: ParamEnv < ' tcx > ,
142141 val : ty:: Const < ' tcx > ,
143- ) -> mir:: DestructuredConst < ' tcx > {
142+ ) -> InterpResult < ' tcx , mir:: DestructuredConst < ' tcx > > {
144143 trace ! ( "destructure_const: {:?}" , val) ;
145144 let ecx = mk_eval_cx ( tcx, DUMMY_SP , param_env, false ) ;
146- let op = ecx. const_to_op ( val, None ) . unwrap ( ) ;
145+ let op = ecx. const_to_op ( val, None ) ? ;
147146
148147 // We go to `usize` as we cannot allocate anything bigger anyway.
149148 let ( field_count, variant, down) = match val. ty ( ) . kind ( ) {
150149 ty:: Array ( _, len) => ( usize:: try_from ( len. eval_usize ( tcx, param_env) ) . unwrap ( ) , None , op) ,
151- ty:: Adt ( def, _) if def. variants . is_empty ( ) => {
152- return mir:: DestructuredConst { variant : None , fields : & [ ] } ;
153- }
154150 ty:: Adt ( def, _) => {
155- let variant = ecx. read_discriminant ( & op) . unwrap ( ) . 1 ;
156- let down = ecx. operand_downcast ( & op, variant) . unwrap ( ) ;
151+ let variant = ecx. read_discriminant ( & op) ? . 1 ;
152+ let down = ecx. operand_downcast ( & op, variant) ? ;
157153 ( def. variants [ variant] . fields . len ( ) , Some ( variant) , down)
158154 }
159155 ty:: Tuple ( substs) => ( substs. len ( ) , None , op) ,
160156 _ => bug ! ( "cannot destructure constant {:?}" , val) ,
161157 } ;
162158
163- let fields_iter = ( 0 ..field_count) . map ( |i| {
164- let field_op = ecx. operand_field ( & down, i) . unwrap ( ) ;
165- let val = op_to_const ( & ecx, & field_op) ;
166- ty:: Const :: from_value ( tcx, val, field_op. layout . ty )
167- } ) ;
168- let fields = tcx. arena . alloc_from_iter ( fields_iter) ;
159+ let fields = ( 0 ..field_count)
160+ . map ( |i| {
161+ let field_op = ecx. operand_field ( & down, i) ?;
162+ let val = op_to_const ( & ecx, & field_op) ;
163+ Ok ( ty:: Const :: from_value ( tcx, val, field_op. layout . ty ) )
164+ } )
165+ . collect :: < InterpResult < ' tcx , Vec < _ > > > ( ) ?;
166+ let fields = tcx. arena . alloc_from_iter ( fields) ;
169167
170- mir:: DestructuredConst { variant, fields }
168+ Ok ( mir:: DestructuredConst { variant, fields } )
171169}
172170
173171pub ( crate ) fn deref_const < ' tcx > (
0 commit comments