@@ -52,7 +52,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
52
52
use rustc_span:: hygiene:: DesugaringKind ;
53
53
use rustc_span:: source_map:: { Span , Spanned } ;
54
54
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
55
- use rustc_target:: abi:: FieldIdx ;
55
+ use rustc_target:: abi:: { FieldIdx , FIRST_VARIANT } ;
56
56
use rustc_target:: spec:: abi:: Abi :: RustIntrinsic ;
57
57
use rustc_trait_selection:: infer:: InferCtxtExt ;
58
58
use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
@@ -3128,8 +3128,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3128
3128
fields : & [ Ident ] ,
3129
3129
expr : & ' tcx hir:: Expr < ' tcx > ,
3130
3130
) -> Ty < ' tcx > {
3131
- use rustc_target:: abi:: OffsetOfIdx :: * ;
3132
-
3133
3131
let container = self . to_ty ( container) . normalized ;
3134
3132
3135
3133
let mut field_indices = Vec :: with_capacity ( fields. len ( ) ) ;
@@ -3145,49 +3143,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3145
3143
let ( ident, _def_scope) =
3146
3144
self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
3147
3145
3148
- if let Some ( ( index, variant) ) = container_def. variants ( )
3146
+ let Some ( ( index, variant) ) = container_def. variants ( )
3149
3147
. iter_enumerated ( )
3150
- . find ( |( _, v) | v. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == ident)
3151
- {
3152
- let Some ( & subfield) = fields. next ( ) else {
3153
- let mut err = type_error_struct ! (
3154
- self . tcx( ) . sess,
3155
- ident. span,
3156
- container,
3157
- E0795 ,
3158
- "`{ident}` is an enum variant; expected field at end of `offset_of`" ,
3159
- ) ;
3160
- err. span_label ( field. span , "enum variant" ) ;
3161
- err. emit ( ) ;
3162
- break ;
3163
- } ;
3164
- let ( subident, sub_def_scope) =
3165
- self . tcx . adjust_ident_and_get_scope ( subfield, variant. def_id , block) ;
3166
-
3167
- if let Some ( ( subindex, field) ) = variant. fields
3168
- . iter_enumerated ( )
3169
- . find ( |( _, f) | f. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == subident)
3170
- {
3171
- let field_ty = self . field_ty ( expr. span , field, args) ;
3148
+ . find ( |( _, v) | v. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == ident) else {
3149
+ let mut err = type_error_struct ! (
3150
+ self . tcx( ) . sess,
3151
+ ident. span,
3152
+ container,
3153
+ E0599 ,
3154
+ "no variant named `{ident}` found for enum `{container}`" ,
3155
+ ) ;
3156
+ err. span_label ( field. span , "variant not found" ) ;
3157
+ err. emit ( ) ;
3158
+ break ;
3159
+ } ;
3160
+ let Some ( & subfield) = fields. next ( ) else {
3161
+ let mut err = type_error_struct ! (
3162
+ self . tcx( ) . sess,
3163
+ ident. span,
3164
+ container,
3165
+ E0795 ,
3166
+ "`{ident}` is an enum variant; expected field at end of `offset_of`" ,
3167
+ ) ;
3168
+ err. span_label ( field. span , "enum variant" ) ;
3169
+ err. emit ( ) ;
3170
+ break ;
3171
+ } ;
3172
+ let ( subident, sub_def_scope) =
3173
+ self . tcx . adjust_ident_and_get_scope ( subfield, variant. def_id , block) ;
3172
3174
3173
- // FIXME: DSTs with static alignment should be allowed
3174
- self . require_type_is_sized ( field_ty, expr. span , traits:: MiscObligation ) ;
3175
+ let Some ( ( subindex, field) ) = variant. fields
3176
+ . iter_enumerated ( )
3177
+ . find ( |( _, f) | f. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == subident) else {
3178
+ let mut err = type_error_struct ! (
3179
+ self . tcx( ) . sess,
3180
+ ident. span,
3181
+ container,
3182
+ E0609 ,
3183
+ "no field named `{subfield}` on enum variant `{container}::{ident}`" ,
3184
+ ) ;
3185
+ err. span_label ( field. span , "this enum variant..." ) ;
3186
+ err. span_label ( subident. span , "...does not have this field" ) ;
3187
+ err. emit ( ) ;
3188
+ break ;
3189
+ } ;
3175
3190
3176
- if field. vis . is_accessible_from ( sub_def_scope, self . tcx ) {
3177
- self . tcx . check_stability ( field. did , Some ( expr. hir_id ) , expr. span , None ) ;
3178
- } else {
3179
- self . private_field_err ( ident, container_def. did ( ) ) . emit ( ) ;
3180
- }
3191
+ let field_ty = self . field_ty ( expr. span , field, args) ;
3181
3192
3182
- // Save the index of all fields regardless of their visibility in case
3183
- // of error recovery.
3184
- field_indices. push ( Variant ( index) ) ;
3185
- field_indices. push ( Field ( subindex) ) ;
3186
- current_container = field_ty;
3193
+ // FIXME: DSTs with static alignment should be allowed
3194
+ self . require_type_is_sized ( field_ty, expr. span , traits:: MiscObligation ) ;
3187
3195
3188
- continue ;
3189
- }
3196
+ if field. vis . is_accessible_from ( sub_def_scope, self . tcx ) {
3197
+ self . tcx . check_stability ( field. did , Some ( expr. hir_id ) , expr. span , None ) ;
3198
+ } else {
3199
+ self . private_field_err ( ident, container_def. did ( ) ) . emit ( ) ;
3190
3200
}
3201
+
3202
+ // Save the index of all fields regardless of their visibility in case
3203
+ // of error recovery.
3204
+ field_indices. push ( ( index, subindex) ) ;
3205
+ current_container = field_ty;
3206
+
3207
+ continue ;
3191
3208
}
3192
3209
ty:: Adt ( container_def, args) => {
3193
3210
let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
@@ -3212,7 +3229,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3212
3229
3213
3230
// Save the index of all fields regardless of their visibility in case
3214
3231
// of error recovery.
3215
- field_indices. push ( Field ( index) ) ;
3232
+ field_indices. push ( ( FIRST_VARIANT , index) ) ;
3216
3233
current_container = field_ty;
3217
3234
3218
3235
continue ;
@@ -3226,7 +3243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3226
3243
self . require_type_is_sized ( ty, expr. span , traits:: MiscObligation ) ;
3227
3244
}
3228
3245
if let Some ( & field_ty) = tys. get ( index) {
3229
- field_indices. push ( Field ( index. into ( ) ) ) ;
3246
+ field_indices. push ( ( FIRST_VARIANT , index. into ( ) ) ) ;
3230
3247
current_container = field_ty;
3231
3248
3232
3249
continue ;
0 commit comments