@@ -3098,16 +3098,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30983098 fields : & [ Ident ] ,
30993099 expr : & ' tcx hir:: Expr < ' tcx > ,
31003100 ) -> Ty < ' tcx > {
3101+ use rustc_target:: abi:: OffsetOfIdx :: * ;
3102+
31013103 let container = self . to_ty ( container) . normalized ;
31023104
31033105 let mut field_indices = Vec :: with_capacity ( fields. len ( ) ) ;
31043106 let mut current_container = container;
3107+ let mut fields = fields. into_iter ( ) ;
31053108
3106- for & field in fields {
3109+ while let Some ( & field) = fields. next ( ) {
31073110 let container = self . structurally_resolve_type ( expr. span , current_container) ;
31083111
31093112 match container. kind ( ) {
3110- ty:: Adt ( container_def, args) if !container_def. is_enum ( ) => {
3113+ ty:: Adt ( container_def, args) if container_def. is_enum ( ) => {
3114+ let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
3115+ let ( ident, _def_scope) =
3116+ self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
3117+
3118+ if let Some ( ( index, variant) ) = container_def. variants ( )
3119+ . iter_enumerated ( )
3120+ . find ( |( _, v) | v. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == ident)
3121+ {
3122+ let Some ( & subfield) = fields. next ( ) else {
3123+ let mut err = type_error_struct ! (
3124+ self . tcx( ) . sess,
3125+ ident. span,
3126+ container,
3127+ E0795 ,
3128+ "`{ident}` is an enum variant; expected field at end of `offset_of`" ,
3129+ ) ;
3130+ err. span_label ( field. span , "enum variant" ) ;
3131+ err. emit ( ) ;
3132+ break ;
3133+ } ;
3134+ let ( subident, sub_def_scope) =
3135+ self . tcx . adjust_ident_and_get_scope ( subfield, variant. def_id , block) ;
3136+
3137+ if let Some ( ( subindex, field) ) = variant. fields
3138+ . iter_enumerated ( )
3139+ . find ( |( _, f) | f. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == subident)
3140+ {
3141+ let field_ty = self . field_ty ( expr. span , field, args) ;
3142+
3143+ // FIXME: DSTs with static alignment should be allowed
3144+ self . require_type_is_sized ( field_ty, expr. span , traits:: MiscObligation ) ;
3145+
3146+ if field. vis . is_accessible_from ( sub_def_scope, self . tcx ) {
3147+ self . tcx . check_stability ( field. did , Some ( expr. hir_id ) , expr. span , None ) ;
3148+ } else {
3149+ self . private_field_err ( ident, container_def. did ( ) ) . emit ( ) ;
3150+ }
3151+
3152+ // Save the index of all fields regardless of their visibility in case
3153+ // of error recovery.
3154+ field_indices. push ( Variant ( index) ) ;
3155+ field_indices. push ( Field ( subindex) ) ;
3156+ current_container = field_ty;
3157+
3158+ continue ;
3159+ }
3160+ }
3161+ }
3162+ ty:: Adt ( container_def, args) => {
31113163 let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
31123164 let ( ident, def_scope) =
31133165 self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
@@ -3130,7 +3182,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31303182
31313183 // Save the index of all fields regardless of their visibility in case
31323184 // of error recovery.
3133- field_indices. push ( index) ;
3185+ field_indices. push ( Field ( index) ) ;
31343186 current_container = field_ty;
31353187
31363188 continue ;
@@ -3144,7 +3196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31443196 self . require_type_is_sized ( ty, expr. span , traits:: MiscObligation ) ;
31453197 }
31463198 if let Some ( & field_ty) = tys. get ( index) {
3147- field_indices. push ( index. into ( ) ) ;
3199+ field_indices. push ( Field ( index. into ( ) ) ) ;
31483200 current_container = field_ty;
31493201
31503202 continue ;
0 commit comments