@@ -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 ;
@@ -3098,8 +3098,6 @@ 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-
31033101 let container = self . to_ty ( container) . normalized ;
31043102
31053103 let mut field_indices = Vec :: with_capacity ( fields. len ( ) ) ;
@@ -3115,49 +3113,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31153113 let ( ident, _def_scope) =
31163114 self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
31173115
3118- if let Some ( ( index, variant) ) = container_def. variants ( )
3116+ let Some ( ( index, variant) ) = container_def. variants ( )
31193117 . 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) ;
3118+ . find ( |( _, v) | v. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == ident) else {
3119+ let mut err = type_error_struct ! (
3120+ self . tcx( ) . sess,
3121+ ident. span,
3122+ container,
3123+ E0599 ,
3124+ "no variant named `{ident}` found for enum `{container}`" ,
3125+ ) ;
3126+ err. span_label ( field. span , "variant not found" ) ;
3127+ err. emit ( ) ;
3128+ break ;
3129+ } ;
3130+ let Some ( & subfield) = fields. next ( ) else {
3131+ let mut err = type_error_struct ! (
3132+ self . tcx( ) . sess,
3133+ ident. span,
3134+ container,
3135+ E0795 ,
3136+ "`{ident}` is an enum variant; expected field at end of `offset_of`" ,
3137+ ) ;
3138+ err. span_label ( field. span , "enum variant" ) ;
3139+ err. emit ( ) ;
3140+ break ;
3141+ } ;
3142+ let ( subident, sub_def_scope) =
3143+ self . tcx . adjust_ident_and_get_scope ( subfield, variant. def_id , block) ;
31423144
3143- // FIXME: DSTs with static alignment should be allowed
3144- self . require_type_is_sized ( field_ty, expr. span , traits:: MiscObligation ) ;
3145+ let Some ( ( subindex, field) ) = variant. fields
3146+ . iter_enumerated ( )
3147+ . find ( |( _, f) | f. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == subident) else {
3148+ let mut err = type_error_struct ! (
3149+ self . tcx( ) . sess,
3150+ ident. span,
3151+ container,
3152+ E0609 ,
3153+ "no field named `{subfield}` on enum variant `{container}::{ident}`" ,
3154+ ) ;
3155+ err. span_label ( field. span , "this enum variant..." ) ;
3156+ err. span_label ( subident. span , "...does not have this field" ) ;
3157+ err. emit ( ) ;
3158+ break ;
3159+ } ;
31453160
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- }
3161+ let field_ty = self . field_ty ( expr. span , field, args) ;
31513162
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;
3163+ // FIXME: DSTs with static alignment should be allowed
3164+ self . require_type_is_sized ( field_ty, expr. span , traits:: MiscObligation ) ;
31573165
3158- continue ;
3159- }
3166+ if field. vis . is_accessible_from ( sub_def_scope, self . tcx ) {
3167+ self . tcx . check_stability ( field. did , Some ( expr. hir_id ) , expr. span , None ) ;
3168+ } else {
3169+ self . private_field_err ( ident, container_def. did ( ) ) . emit ( ) ;
31603170 }
3171+
3172+ // Save the index of all fields regardless of their visibility in case
3173+ // of error recovery.
3174+ field_indices. push ( ( index, subindex) ) ;
3175+ current_container = field_ty;
3176+
3177+ continue ;
31613178 }
31623179 ty:: Adt ( container_def, args) => {
31633180 let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
@@ -3182,7 +3199,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31823199
31833200 // Save the index of all fields regardless of their visibility in case
31843201 // of error recovery.
3185- field_indices. push ( Field ( index) ) ;
3202+ field_indices. push ( ( FIRST_VARIANT , index) ) ;
31863203 current_container = field_ty;
31873204
31883205 continue ;
@@ -3196,7 +3213,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31963213 self . require_type_is_sized ( ty, expr. span , traits:: MiscObligation ) ;
31973214 }
31983215 if let Some ( & field_ty) = tys. get ( index) {
3199- field_indices. push ( Field ( index. into ( ) ) ) ;
3216+ field_indices. push ( ( FIRST_VARIANT , index. into ( ) ) ) ;
32003217 current_container = field_ty;
32013218
32023219 continue ;
0 commit comments