@@ -54,7 +54,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
54
54
use rustc_span:: hygiene:: DesugaringKind ;
55
55
use rustc_span:: source_map:: { Span , Spanned } ;
56
56
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
57
- use rustc_target:: abi:: FieldIdx ;
57
+ use rustc_target:: abi:: { FieldIdx , FIRST_VARIANT } ;
58
58
use rustc_target:: spec:: abi:: Abi :: RustIntrinsic ;
59
59
use rustc_trait_selection:: infer:: InferCtxtExt ;
60
60
use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
@@ -3107,12 +3107,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3107
3107
3108
3108
let mut field_indices = Vec :: with_capacity ( fields. len ( ) ) ;
3109
3109
let mut current_container = container;
3110
+ let mut fields = fields. into_iter ( ) ;
3110
3111
3111
- for & field in fields {
3112
+ while let Some ( & field) = fields. next ( ) {
3112
3113
let container = self . structurally_resolve_type ( expr. span , current_container) ;
3113
3114
3114
3115
match container. kind ( ) {
3115
- ty:: Adt ( container_def, args) if !container_def. is_enum ( ) => {
3116
+ ty:: Adt ( container_def, args) if container_def. is_enum ( ) => {
3117
+ let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
3118
+ let ( ident, _def_scope) =
3119
+ self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
3120
+
3121
+ let Some ( ( index, variant) ) = container_def. variants ( )
3122
+ . iter_enumerated ( )
3123
+ . find ( |( _, v) | v. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == ident) else {
3124
+ let mut err = type_error_struct ! (
3125
+ self . tcx( ) . sess,
3126
+ ident. span,
3127
+ container,
3128
+ E0599 ,
3129
+ "no variant named `{ident}` found for enum `{container}`" ,
3130
+ ) ;
3131
+ err. span_label ( field. span , "variant not found" ) ;
3132
+ err. emit ( ) ;
3133
+ break ;
3134
+ } ;
3135
+ let Some ( & subfield) = fields. next ( ) else {
3136
+ let mut err = type_error_struct ! (
3137
+ self . tcx( ) . sess,
3138
+ ident. span,
3139
+ container,
3140
+ E0795 ,
3141
+ "`{ident}` is an enum variant; expected field at end of `offset_of`" ,
3142
+ ) ;
3143
+ err. span_label ( field. span , "enum variant" ) ;
3144
+ err. emit ( ) ;
3145
+ break ;
3146
+ } ;
3147
+ let ( subident, sub_def_scope) =
3148
+ self . tcx . adjust_ident_and_get_scope ( subfield, variant. def_id , block) ;
3149
+
3150
+ let Some ( ( subindex, field) ) = variant. fields
3151
+ . iter_enumerated ( )
3152
+ . find ( |( _, f) | f. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == subident) else {
3153
+ let mut err = type_error_struct ! (
3154
+ self . tcx( ) . sess,
3155
+ ident. span,
3156
+ container,
3157
+ E0609 ,
3158
+ "no field named `{subfield}` on enum variant `{container}::{ident}`" ,
3159
+ ) ;
3160
+ err. span_label ( field. span , "this enum variant..." ) ;
3161
+ err. span_label ( subident. span , "...does not have this field" ) ;
3162
+ err. emit ( ) ;
3163
+ break ;
3164
+ } ;
3165
+
3166
+ let field_ty = self . field_ty ( expr. span , field, args) ;
3167
+
3168
+ // FIXME: DSTs with static alignment should be allowed
3169
+ self . require_type_is_sized ( field_ty, expr. span , traits:: MiscObligation ) ;
3170
+
3171
+ if field. vis . is_accessible_from ( sub_def_scope, self . tcx ) {
3172
+ self . tcx . check_stability ( field. did , Some ( expr. hir_id ) , expr. span , None ) ;
3173
+ } else {
3174
+ self . private_field_err ( ident, container_def. did ( ) ) . emit ( ) ;
3175
+ }
3176
+
3177
+ // Save the index of all fields regardless of their visibility in case
3178
+ // of error recovery.
3179
+ field_indices. push ( ( index, subindex) ) ;
3180
+ current_container = field_ty;
3181
+
3182
+ continue ;
3183
+ }
3184
+ ty:: Adt ( container_def, args) => {
3116
3185
let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
3117
3186
let ( ident, def_scope) =
3118
3187
self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
@@ -3135,7 +3204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3135
3204
3136
3205
// Save the index of all fields regardless of their visibility in case
3137
3206
// of error recovery.
3138
- field_indices. push ( index) ;
3207
+ field_indices. push ( ( FIRST_VARIANT , index) ) ;
3139
3208
current_container = field_ty;
3140
3209
3141
3210
continue ;
@@ -3149,7 +3218,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3149
3218
self . require_type_is_sized ( ty, expr. span , traits:: MiscObligation ) ;
3150
3219
}
3151
3220
if let Some ( & field_ty) = tys. get ( index) {
3152
- field_indices. push ( index. into ( ) ) ;
3221
+ field_indices. push ( ( FIRST_VARIANT , index. into ( ) ) ) ;
3153
3222
current_container = field_ty;
3154
3223
3155
3224
continue ;
0 commit comments