@@ -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 ;
@@ -3103,8 +3103,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31033103 fields : & [ Ident ] ,
31043104 expr : & ' tcx hir:: Expr < ' tcx > ,
31053105 ) -> Ty < ' tcx > {
3106- use rustc_target:: abi:: OffsetOfIdx :: * ;
3107-
31083106 let container = self . to_ty ( container) . normalized ;
31093107
31103108 let mut field_indices = Vec :: with_capacity ( fields. len ( ) ) ;
@@ -3120,49 +3118,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31203118 let ( ident, _def_scope) =
31213119 self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
31223120
3123- if let Some ( ( index, variant) ) = container_def. variants ( )
3121+ let Some ( ( index, variant) ) = container_def. variants ( )
31243122 . iter_enumerated ( )
3125- . find ( |( _, v) | v. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == ident)
3126- {
3127- let Some ( & subfield) = fields. next ( ) else {
3128- let mut err = type_error_struct ! (
3129- self . tcx( ) . sess,
3130- ident. span,
3131- container,
3132- E0795 ,
3133- "`{ident}` is an enum variant; expected field at end of `offset_of`" ,
3134- ) ;
3135- err. span_label ( field. span , "enum variant" ) ;
3136- err. emit ( ) ;
3137- break ;
3138- } ;
3139- let ( subident, sub_def_scope) =
3140- self . tcx . adjust_ident_and_get_scope ( subfield, variant. def_id , block) ;
3141-
3142- if let Some ( ( subindex, field) ) = variant. fields
3143- . iter_enumerated ( )
3144- . find ( |( _, f) | f. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == subident)
3145- {
3146- let field_ty = self . field_ty ( expr. span , field, args) ;
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) ;
31473149
3148- // FIXME: DSTs with static alignment should be allowed
3149- self . require_type_is_sized ( field_ty, expr. span , traits:: MiscObligation ) ;
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+ } ;
31503165
3151- if field. vis . is_accessible_from ( sub_def_scope, self . tcx ) {
3152- self . tcx . check_stability ( field. did , Some ( expr. hir_id ) , expr. span , None ) ;
3153- } else {
3154- self . private_field_err ( ident, container_def. did ( ) ) . emit ( ) ;
3155- }
3166+ let field_ty = self . field_ty ( expr. span , field, args) ;
31563167
3157- // Save the index of all fields regardless of their visibility in case
3158- // of error recovery.
3159- field_indices. push ( Variant ( index) ) ;
3160- field_indices. push ( Field ( subindex) ) ;
3161- current_container = field_ty;
3168+ // FIXME: DSTs with static alignment should be allowed
3169+ self . require_type_is_sized ( field_ty, expr. span , traits:: MiscObligation ) ;
31623170
3163- continue ;
3164- }
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 ( ) ;
31653175 }
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 ;
31663183 }
31673184 ty:: Adt ( container_def, args) => {
31683185 let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
@@ -3187,7 +3204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31873204
31883205 // Save the index of all fields regardless of their visibility in case
31893206 // of error recovery.
3190- field_indices. push ( Field ( index) ) ;
3207+ field_indices. push ( ( FIRST_VARIANT , index) ) ;
31913208 current_container = field_ty;
31923209
31933210 continue ;
@@ -3201,7 +3218,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32013218 self . require_type_is_sized ( ty, expr. span , traits:: MiscObligation ) ;
32023219 }
32033220 if let Some ( & field_ty) = tys. get ( index) {
3204- field_indices. push ( Field ( index. into ( ) ) ) ;
3221+ field_indices. push ( ( FIRST_VARIANT , index. into ( ) ) ) ;
32053222 current_container = field_ty;
32063223
32073224 continue ;
0 commit comments