1- use rustc_abi:: { FieldIdx , FieldsShape , Size , TagEncoding , VariantIdx , Variants } ;
1+ use rustc_abi:: { BackendRepr , FieldIdx , FieldsShape , Size , TagEncoding , VariantIdx , Variants } ;
22use rustc_middle:: mir:: interpret:: {
33 AllocId , AllocRange , Allocation , CtfeProvenance , GlobalAlloc , Pointer , Provenance , Scalar ,
44} ;
@@ -259,7 +259,7 @@ pub fn read_scalar_int_constant<'tcx>(
259259 } ) ;
260260 }
261261
262- if let TyKind :: Adt ( adt_def, substs ) = ty. kind ( ) {
262+ if let TyKind :: Adt ( adt_def, _ ) = ty. kind ( ) {
263263 if adt_def. is_enum ( ) {
264264 // A scalar enum constant is the enum's physical ABI carrier, not
265265 // necessarily its source-level discriminant. Niche-encoded enums
@@ -281,44 +281,8 @@ pub fn read_scalar_int_constant<'tcx>(
281281 return scalar_int_to_oomir_constant ( tcx, scalar_int, carrier_ty) ;
282282 }
283283
284- let variant = adt_def
285- . variants ( )
286- . iter ( )
287- . next ( )
288- . ok_or_else ( || format ! ( "Transparent ADT {:?} has no variants" , ty) ) ?;
289- let non_zst_fields = variant
290- . fields
291- . iter ( )
292- . filter ( |field_def| {
293- !tcx. layout_of ( PseudoCanonicalInput {
294- typing_env : TypingEnv :: post_analysis ( tcx, field_def. did ) ,
295- value : field_def. ty ( tcx, substs) . skip_norm_wip ( ) ,
296- } )
297- . map ( |layout| layout. is_zst ( ) )
298- . unwrap_or ( false )
299- } )
300- . collect :: < Vec < _ > > ( ) ;
301-
302- if non_zst_fields. len ( ) != 1 {
303- return Err ( format ! (
304- "Transparent ADT {:?} has {} non-ZST fields, expected exactly one" ,
305- ty,
306- non_zst_fields. len( )
307- ) ) ;
308- }
309-
310- let field_def = non_zst_fields[ 0 ] ;
311- let unnormalized_field_ty = field_def. ty ( tcx, substs) ;
312- let field_ty = tcx
313- . try_normalize_erasing_regions ( TypingEnv :: fully_monomorphized ( ) , unnormalized_field_ty)
314- . map_err ( |error| {
315- format ! (
316- "Could not normalize constant field {} of type {:?}: {:?}" ,
317- field_def. ident( tcx) ,
318- unnormalized_field_ty,
319- error
320- )
321- } ) ?;
284+ let field_ty = scalar_struct_field_ty ( tcx, ty) ?
285+ . ok_or_else ( || format ! ( "Scalar constant ADT {ty:?} did not have one non-ZST field" ) ) ?;
322286 // A scalar ADT is carried using the bits of its one non-ZST field.
323287 // Keep that physical carrier here and let value-representation
324288 // adaptation reconstruct the nominal JVM object at the use site.
@@ -332,6 +296,57 @@ pub fn read_scalar_int_constant<'tcx>(
332296 scalar_int_to_oomir_constant ( tcx, scalar_int, ty)
333297}
334298
299+ fn scalar_struct_field_ty < ' tcx > (
300+ tcx : TyCtxt < ' tcx > ,
301+ ty : Ty < ' tcx > ,
302+ ) -> Result < Option < Ty < ' tcx > > , String > {
303+ let TyKind :: Adt ( adt_def, substs) = ty. kind ( ) else {
304+ return Ok ( None ) ;
305+ } ;
306+ if !adt_def. is_struct ( ) {
307+ return Ok ( None ) ;
308+ }
309+ let layout = tcx
310+ . layout_of ( TypingEnv :: fully_monomorphized ( ) . as_query_input ( ty) )
311+ . map_err ( |error| format ! ( "Could not determine constant layout for {ty:?}: {error:?}" ) ) ?;
312+ if !matches ! ( layout. backend_repr, BackendRepr :: Scalar ( _) ) {
313+ return Ok ( None ) ;
314+ }
315+
316+ let variant = adt_def
317+ . variants ( )
318+ . iter ( )
319+ . next ( )
320+ . ok_or_else ( || format ! ( "Scalar ADT {ty:?} has no variants" ) ) ?;
321+ let non_zst_fields = variant
322+ . fields
323+ . iter ( )
324+ . filter ( |field_def| {
325+ !tcx. layout_of ( PseudoCanonicalInput {
326+ typing_env : TypingEnv :: post_analysis ( tcx, field_def. did ) ,
327+ value : field_def. ty ( tcx, substs) . skip_norm_wip ( ) ,
328+ } )
329+ . map ( |layout| layout. is_zst ( ) )
330+ . unwrap_or ( false )
331+ } )
332+ . collect :: < Vec < _ > > ( ) ;
333+ let [ field_def] = non_zst_fields. as_slice ( ) else {
334+ return Err ( format ! (
335+ "Scalar ADT {ty:?} has {} non-ZST fields, expected exactly one" ,
336+ non_zst_fields. len( )
337+ ) ) ;
338+ } ;
339+ let field_ty = field_def. ty ( tcx, substs) ;
340+ tcx. try_normalize_erasing_regions ( TypingEnv :: fully_monomorphized ( ) , field_ty)
341+ . map ( Some )
342+ . map_err ( |error| {
343+ format ! (
344+ "Could not normalize constant field {} of type {field_ty:?}: {error:?}" ,
345+ field_def. ident( tcx)
346+ )
347+ } )
348+ }
349+
335350pub fn read_zero_sized_constant < ' tcx > (
336351 tcx : TyCtxt < ' tcx > ,
337352 ty : Ty < ' tcx > ,
@@ -513,6 +528,22 @@ pub fn read_pointer_constant<'tcx>(
513528 oomir_data_types : & mut HashMap < String , oomir:: DataType > ,
514529 instance : Instance < ' tcx > ,
515530) -> Result < oomir:: Constant , String > {
531+ let ty = EarlyBinder :: bind ( tcx, ty)
532+ . instantiate ( tcx, instance. args )
533+ . skip_norm_wip ( ) ;
534+ let ty = tcx
535+ . try_normalize_erasing_regions (
536+ TypingEnv :: fully_monomorphized ( ) ,
537+ rustc_middle:: ty:: Unnormalized :: new_wip ( ty) ,
538+ )
539+ . unwrap_or ( ty) ;
540+ if let TyKind :: Pat ( inner, _) = ty. kind ( ) {
541+ return read_pointer_constant ( tcx, pointer, * inner, oomir_data_types, instance) ;
542+ }
543+ if let Some ( field_ty) = scalar_struct_field_ty ( tcx, ty) ? {
544+ return read_pointer_constant ( tcx, pointer, field_ty, oomir_data_types, instance) ;
545+ }
546+
516547 match ty. kind ( ) {
517548 TyKind :: FnPtr ( ..) => {
518549 read_function_pointer_constant ( tcx, pointer, ty, oomir_data_types, instance)
@@ -1183,9 +1214,20 @@ pub fn read_constant_value_from_memory<'tcx>(
11831214 oomir_data_types,
11841215 instance,
11851216 ) ?;
1186- let pointee_type =
1187- ty_to_oomir_type ( * inner_ty, tcx, oomir_data_types, instance) ;
1188- Ok ( oomir:: Constant :: Array ( Box :: new ( pointee_type) , vec ! [ value] ) )
1217+ if matches ! ( oomir:: Type :: from_constant( & value) , oomir:: Type :: Pointer ( _) )
1218+ {
1219+ // A static reference is already its stable address. Keep that
1220+ // Pointer carrier rather than adding a pointer-to-pointer cell.
1221+ Ok ( value)
1222+ } else {
1223+ pointer_constant_for_pointee (
1224+ tcx,
1225+ * inner_ty,
1226+ value,
1227+ oomir_data_types,
1228+ instance,
1229+ )
1230+ }
11891231 }
11901232 }
11911233 }
0 commit comments