@@ -54,7 +54,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
5454use rustc_span:: hygiene:: DesugaringKind ;
5555use rustc_span:: source_map:: { Span , Spanned } ;
5656use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
57- use rustc_target:: abi:: FieldIdx ;
57+ use rustc_target:: abi:: { FieldIdx , FIRST_VARIANT } ;
5858use rustc_target:: spec:: abi:: Abi :: RustIntrinsic ;
5959use rustc_trait_selection:: infer:: InferCtxtExt ;
6060use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
@@ -3107,12 +3107,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31073107
31083108 let mut field_indices = Vec :: with_capacity ( fields. len ( ) ) ;
31093109 let mut current_container = container;
3110+ let mut fields = fields. into_iter ( ) ;
31103111
3111- for & field in fields {
3112+ while let Some ( & field) = fields. next ( ) {
31123113 let container = self . structurally_resolve_type ( expr. span , current_container) ;
31133114
31143115 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) => {
31163185 let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
31173186 let ( ident, def_scope) =
31183187 self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
@@ -3135,7 +3204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31353204
31363205 // Save the index of all fields regardless of their visibility in case
31373206 // of error recovery.
3138- field_indices. push ( index) ;
3207+ field_indices. push ( ( FIRST_VARIANT , index) ) ;
31393208 current_container = field_ty;
31403209
31413210 continue ;
@@ -3149,7 +3218,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31493218 self . require_type_is_sized ( ty, expr. span , traits:: MiscObligation ) ;
31503219 }
31513220 if let Some ( & field_ty) = tys. get ( index) {
3152- field_indices. push ( index. into ( ) ) ;
3221+ field_indices. push ( ( FIRST_VARIANT , index. into ( ) ) ) ;
31533222 current_container = field_ty;
31543223
31553224 continue ;
0 commit comments