@@ -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 ;
@@ -3098,8 +3098,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3098
3098
fields : & [ Ident ] ,
3099
3099
expr : & ' tcx hir:: Expr < ' tcx > ,
3100
3100
) -> Ty < ' tcx > {
3101
- use rustc_target:: abi:: OffsetOfIdx :: * ;
3102
-
3103
3101
let container = self . to_ty ( container) . normalized ;
3104
3102
3105
3103
let mut field_indices = Vec :: with_capacity ( fields. len ( ) ) ;
@@ -3115,49 +3113,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3115
3113
let ( ident, _def_scope) =
3116
3114
self . tcx . adjust_ident_and_get_scope ( field, container_def. did ( ) , block) ;
3117
3115
3118
- if let Some ( ( index, variant) ) = container_def. variants ( )
3116
+ let Some ( ( index, variant) ) = container_def. variants ( )
3119
3117
. 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) ;
3142
3144
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
+ } ;
3145
3160
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) ;
3151
3162
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 ) ;
3157
3165
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 ( ) ;
3160
3170
}
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 ;
3161
3178
}
3162
3179
ty:: Adt ( container_def, args) => {
3163
3180
let block = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . body_id ) ;
@@ -3182,7 +3199,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3182
3199
3183
3200
// Save the index of all fields regardless of their visibility in case
3184
3201
// of error recovery.
3185
- field_indices. push ( Field ( index) ) ;
3202
+ field_indices. push ( ( FIRST_VARIANT , index) ) ;
3186
3203
current_container = field_ty;
3187
3204
3188
3205
continue ;
@@ -3196,7 +3213,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3196
3213
self . require_type_is_sized ( ty, expr. span , traits:: MiscObligation ) ;
3197
3214
}
3198
3215
if let Some ( & field_ty) = tys. get ( index) {
3199
- field_indices. push ( Field ( index. into ( ) ) ) ;
3216
+ field_indices. push ( ( FIRST_VARIANT , index. into ( ) ) ) ;
3200
3217
current_container = field_ty;
3201
3218
3202
3219
continue ;
0 commit comments