@@ -11,7 +11,8 @@ use rustc_middle::{
11
11
use rustc_span:: { source_map:: DUMMY_SP , symbol:: Symbol } ;
12
12
13
13
use 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 ,
15
16
} ;
16
17
17
18
mod error;
@@ -132,42 +133,39 @@ fn const_to_valtree_inner<'tcx>(
132
133
}
133
134
}
134
135
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 > (
140
139
tcx : TyCtxt < ' tcx > ,
141
140
param_env : ty:: ParamEnv < ' tcx > ,
142
141
val : ty:: Const < ' tcx > ,
143
- ) -> mir:: DestructuredConst < ' tcx > {
142
+ ) -> InterpResult < ' tcx , mir:: DestructuredConst < ' tcx > > {
144
143
trace ! ( "destructure_const: {:?}" , val) ;
145
144
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 ) ? ;
147
146
148
147
// We go to `usize` as we cannot allocate anything bigger anyway.
149
148
let ( field_count, variant, down) = match val. ty ( ) . kind ( ) {
150
149
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
- }
154
150
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) ? ;
157
153
( def. variants [ variant] . fields . len ( ) , Some ( variant) , down)
158
154
}
159
155
ty:: Tuple ( substs) => ( substs. len ( ) , None , op) ,
160
156
_ => bug ! ( "cannot destructure constant {:?}" , val) ,
161
157
} ;
162
158
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) ;
169
167
170
- mir:: DestructuredConst { variant, fields }
168
+ Ok ( mir:: DestructuredConst { variant, fields } )
171
169
}
172
170
173
171
pub ( crate ) fn deref_const < ' tcx > (
0 commit comments