@@ -3128,16 +3128,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3128
3128
fields : & [ Ident ] ,
3129
3129
expr : & ' tcx hir:: Expr < ' tcx > ,
3130
3130
) -> Ty < ' tcx > {
3131
+ use rustc_target:: abi:: OffsetOfIdx :: * ;
3132
+
3131
3133
let container = self . to_ty ( container) . normalized ;
3132
3134
3133
3135
let mut field_indices = Vec :: with_capacity ( fields. len ( ) ) ;
3134
3136
let mut current_container = container;
3137
+ let mut fields = fields. into_iter ( ) ;
3135
3138
3136
- for & field in fields {
3139
+ while let Some ( & field) = fields. next ( ) {
3137
3140
let container = self . structurally_resolve_type ( expr. span , current_container) ;
3138
3141
3139
3142
match container. kind ( ) {
3140
- ty:: Adt ( container_def, args) if !container_def. is_enum ( ) => {
3143
+ ty:: Adt ( container_def, args) if container_def. is_enum ( ) => {
3144
+ let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
3145
+ let ( ident, _def_scope) =
3146
+ self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
3147
+
3148
+ if let Some ( ( index, variant) ) = container_def. variants ( )
3149
+ . iter_enumerated ( )
3150
+ . find ( |( _, v) | v. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == ident)
3151
+ {
3152
+ let Some ( & subfield) = fields. next ( ) else {
3153
+ let mut err = type_error_struct ! (
3154
+ self . tcx( ) . sess,
3155
+ ident. span,
3156
+ container,
3157
+ E0795 ,
3158
+ "`{ident}` is an enum variant; expected field at end of `offset_of`" ,
3159
+ ) ;
3160
+ err. span_label ( field. span , "enum variant" ) ;
3161
+ err. emit ( ) ;
3162
+ break ;
3163
+ } ;
3164
+ let ( subident, sub_def_scope) =
3165
+ self . tcx . adjust_ident_and_get_scope ( subfield, variant. def_id , block) ;
3166
+
3167
+ if let Some ( ( subindex, field) ) = variant. fields
3168
+ . iter_enumerated ( )
3169
+ . find ( |( _, f) | f. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == subident)
3170
+ {
3171
+ let field_ty = self . field_ty ( expr. span , field, args) ;
3172
+
3173
+ // FIXME: DSTs with static alignment should be allowed
3174
+ self . require_type_is_sized ( field_ty, expr. span , traits:: MiscObligation ) ;
3175
+
3176
+ if field. vis . is_accessible_from ( sub_def_scope, self . tcx ) {
3177
+ self . tcx . check_stability ( field. did , Some ( expr. hir_id ) , expr. span , None ) ;
3178
+ } else {
3179
+ self . private_field_err ( ident, container_def. did ( ) ) . emit ( ) ;
3180
+ }
3181
+
3182
+ // Save the index of all fields regardless of their visibility in case
3183
+ // of error recovery.
3184
+ field_indices. push ( Variant ( index) ) ;
3185
+ field_indices. push ( Field ( subindex) ) ;
3186
+ current_container = field_ty;
3187
+
3188
+ continue ;
3189
+ }
3190
+ }
3191
+ }
3192
+ ty:: Adt ( container_def, args) => {
3141
3193
let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
3142
3194
let ( ident, def_scope) =
3143
3195
self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
@@ -3160,7 +3212,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3160
3212
3161
3213
// Save the index of all fields regardless of their visibility in case
3162
3214
// of error recovery.
3163
- field_indices. push ( index) ;
3215
+ field_indices. push ( Field ( index) ) ;
3164
3216
current_container = field_ty;
3165
3217
3166
3218
continue ;
@@ -3174,7 +3226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3174
3226
self . require_type_is_sized ( ty, expr. span , traits:: MiscObligation ) ;
3175
3227
}
3176
3228
if let Some ( & field_ty) = tys. get ( index) {
3177
- field_indices. push ( index. into ( ) ) ;
3229
+ field_indices. push ( Field ( index. into ( ) ) ) ;
3178
3230
current_container = field_ty;
3179
3231
3180
3232
continue ;
0 commit comments