@@ -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 ;
@@ -3103,8 +3103,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3103
3103
fields : & [ Ident ] ,
3104
3104
expr : & ' tcx hir:: Expr < ' tcx > ,
3105
3105
) -> Ty < ' tcx > {
3106
- use rustc_target:: abi:: OffsetOfIdx :: * ;
3107
-
3108
3106
let container = self . to_ty ( container) . normalized ;
3109
3107
3110
3108
let mut field_indices = Vec :: with_capacity ( fields. len ( ) ) ;
@@ -3120,49 +3118,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3120
3118
let ( ident, _def_scope) =
3121
3119
self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
3122
3120
3123
- if let Some ( ( index, variant) ) = container_def. variants ( )
3121
+ let Some ( ( index, variant) ) = container_def. variants ( )
3124
3122
. 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) ;
3147
3149
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
+ } ;
3150
3165
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) ;
3156
3167
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 ) ;
3162
3170
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 ( ) ;
3165
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 ;
3166
3183
}
3167
3184
ty:: Adt ( container_def, args) => {
3168
3185
let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
@@ -3187,7 +3204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3187
3204
3188
3205
// Save the index of all fields regardless of their visibility in case
3189
3206
// of error recovery.
3190
- field_indices. push ( Field ( index) ) ;
3207
+ field_indices. push ( ( FIRST_VARIANT , index) ) ;
3191
3208
current_container = field_ty;
3192
3209
3193
3210
continue ;
@@ -3201,7 +3218,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3201
3218
self . require_type_is_sized ( ty, expr. span , traits:: MiscObligation ) ;
3202
3219
}
3203
3220
if let Some ( & field_ty) = tys. get ( index) {
3204
- field_indices. push ( Field ( index. into ( ) ) ) ;
3221
+ field_indices. push ( ( FIRST_VARIANT , index. into ( ) ) ) ;
3205
3222
current_container = field_ty;
3206
3223
3207
3224
continue ;
0 commit comments