@@ -112,13 +112,13 @@ pub(super) fn op_to_const<'tcx>(
112112 ecx : & CompileTimeEvalContext < ' _ , ' tcx > ,
113113 op : & OpTy < ' tcx > ,
114114) -> ConstValue < ' tcx > {
115+ // Handle ZST consistently and early.
116+ if op. layout . is_zst ( ) {
117+ return ConstValue :: ZeroSized ;
118+ }
119+
115120 // We do not have value optimizations for everything.
116121 // Only scalars and slices, since they are very common.
117- // Note that further down we turn scalars of uninitialized bits back to `ByRef`. These can result
118- // from scalar unions that are initialized with one of their zero sized variants. We could
119- // instead allow `ConstValue::Scalar` to store `ScalarMaybeUninit`, but that would affect all
120- // the usual cases of extracting e.g. a `usize`, without there being a real use case for the
121- // `Undef` situation.
122122 let try_as_immediate = match op. layout . abi {
123123 Abi :: Scalar ( abi:: Scalar :: Initialized { .. } ) => true ,
124124 Abi :: ScalarPair ( ..) => match op. layout . ty . kind ( ) {
@@ -134,7 +134,7 @@ pub(super) fn op_to_const<'tcx>(
134134 let immediate = if try_as_immediate {
135135 Right ( ecx. read_immediate ( op) . expect ( "normalization works on validated constants" ) )
136136 } else {
137- // It is guaranteed that any non-slice scalar pair is actually ByRef here.
137+ // It is guaranteed that any non-slice scalar pair is actually `Indirect` here.
138138 // When we come back from raw const eval, we are always by-ref. The only way our op here is
139139 // by-val is if we are in destructure_mir_constant, i.e., if this is (a field of) something that we
140140 // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
@@ -144,28 +144,15 @@ pub(super) fn op_to_const<'tcx>(
144144
145145 debug ! ( ?immediate) ;
146146
147- // We know `offset` is relative to the allocation, so we can use `into_parts`.
148- let to_const_value = |mplace : & MPlaceTy < ' _ > | {
149- debug ! ( "to_const_value(mplace: {:?})" , mplace) ;
150- match mplace. ptr ( ) . into_parts ( ) {
151- ( Some ( alloc_id) , offset) => ConstValue :: ByRef { alloc_id, offset } ,
152- ( None , offset) => {
153- assert ! ( mplace. layout. is_zst( ) ) ;
154- assert_eq ! (
155- offset. bytes( ) % mplace. layout. align. abi. bytes( ) ,
156- 0 ,
157- "this MPlaceTy must come from a validated constant, thus we can assume the \
158- alignment is correct",
159- ) ;
160- ConstValue :: ZeroSized
161- }
162- }
163- } ;
164147 match immediate {
165- Left ( ref mplace) => to_const_value ( mplace) ,
148+ Left ( ref mplace) => {
149+ // We know `offset` is relative to the allocation, so we can use `into_parts`.
150+ let ( alloc_id, offset) = mplace. ptr ( ) . into_parts ( ) ;
151+ let alloc_id = alloc_id. expect ( "cannot have `fake` place fot non-ZST type" ) ;
152+ ConstValue :: Indirect { alloc_id, offset }
153+ }
166154 // see comment on `let try_as_immediate` above
167155 Right ( imm) => match * imm {
168- _ if imm. layout . is_zst ( ) => ConstValue :: ZeroSized ,
169156 Immediate :: Scalar ( x) => ConstValue :: Scalar ( x) ,
170157 Immediate :: ScalarPair ( a, b) => {
171158 debug ! ( "ScalarPair(a: {:?}, b: {:?})" , a, b) ;
@@ -186,7 +173,7 @@ pub(super) fn op_to_const<'tcx>(
186173 let len: usize = len. try_into ( ) . unwrap ( ) ;
187174 ConstValue :: Slice { data, start, end : start + len }
188175 }
189- Immediate :: Uninit => to_const_value ( & op. assert_mem_place ( ) ) ,
176+ Immediate :: Uninit => bug ! ( "`Uninit` is not a valid value for {}" , op. layout . ty ) ,
190177 } ,
191178 }
192179}
0 commit comments