@@ -21,6 +21,7 @@ pub mod generics;
2121
2222use std:: slice;
2323
24+ use rustc_abi:: FIRST_VARIANT ;
2425use rustc_ast:: LitKind ;
2526use rustc_data_structures:: assert_matches;
2627use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
@@ -39,7 +40,7 @@ use rustc_middle::middle::stability::AllowUnstable;
3940use rustc_middle:: mir:: interpret:: LitToConstInput ;
4041use rustc_middle:: ty:: print:: PrintPolyTraitRefExt as _;
4142use rustc_middle:: ty:: {
42- self , Const , GenericArgKind , GenericArgsRef , GenericParamDefKind , Ty , TyCtxt ,
43+ self , Const , FieldId , GenericArgKind , GenericArgsRef , GenericParamDefKind , Ty , TyCtxt ,
4344 TypeSuperFoldable , TypeVisitableExt , TypingMode , Upcast , fold_regions,
4445} ;
4546use rustc_middle:: { bug, span_bug} ;
@@ -52,11 +53,11 @@ use rustc_trait_selection::traits::{self, FulfillmentError};
5253use tracing:: { debug, instrument} ;
5354
5455use crate :: check:: check_abi;
55- use crate :: check_c_variadic_abi;
56- use crate :: errors:: { AmbiguousLifetimeBound , BadReturnTypeNotation } ;
56+ use crate :: errors:: { AmbiguousLifetimeBound , BadReturnTypeNotation , NoFieldOnType } ;
5757use crate :: hir_ty_lowering:: errors:: { GenericsArgsErrExtend , prohibit_assoc_item_constraint} ;
5858use crate :: hir_ty_lowering:: generics:: { check_generic_arg_count, lower_generic_args} ;
5959use crate :: middle:: resolve_bound_vars as rbv;
60+ use crate :: { NoVariantNamed , check_c_variadic_abi} ;
6061
6162/// The context in which an implied bound is being added to a item being lowered (i.e. a sizedness
6263/// trait or a default trait)
@@ -3004,8 +3005,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
30043005 self . record_ty ( pat. hir_id , ty, pat. span ) ;
30053006 pat_ty
30063007 }
3007- hir:: TyKind :: FieldOf ( ty, hir:: TyFieldPath { variant, field } ) => ty:: lower_field_of (
3008- self . tcx ( ) ,
3008+ hir:: TyKind :: FieldOf ( ty, hir:: TyFieldPath { variant, field } ) => self . lower_field_of (
30093009 self . lower_ty ( ty) ,
30103010 self . item_def_id ( ) ,
30113011 ty. span ,
@@ -3054,6 +3054,168 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
30543054 }
30553055 }
30563056
3057+ fn lower_field_of (
3058+ & self ,
3059+ ty : Ty < ' tcx > ,
3060+ item_def_id : LocalDefId ,
3061+ ty_span : Span ,
3062+ hir_id : HirId ,
3063+ variant : Option < Ident > ,
3064+ field : Ident ,
3065+ ) -> Ty < ' tcx > {
3066+ let dcx = self . dcx ( ) ;
3067+ let tcx = self . tcx ( ) ;
3068+ match ty. kind ( ) {
3069+ ty:: Adt ( def, _) => {
3070+ let base_did = def. did ( ) ;
3071+ let kind_name = tcx. def_descr ( base_did) ;
3072+ let ( variant_idx, variant) = if def. is_enum ( ) {
3073+ let Some ( variant) = variant else {
3074+ let err = dcx
3075+ . create_err ( NoVariantNamed { span : field. span , ident : field, ty } )
3076+ . with_span_help (
3077+ field. span . shrink_to_lo ( ) ,
3078+ "you might be missing a variant here: `Variant.`" ,
3079+ )
3080+ . emit ( ) ;
3081+ return Ty :: new_error ( tcx, err) ;
3082+ } ;
3083+
3084+ if let Some ( res) = def
3085+ . variants ( )
3086+ . iter_enumerated ( )
3087+ . find ( |( _, f) | f. ident ( tcx) . normalize_to_macros_2_0 ( ) == variant)
3088+ {
3089+ res
3090+ } else {
3091+ let err = dcx
3092+ . create_err ( NoVariantNamed { span : variant. span , ident : variant, ty } )
3093+ . emit ( ) ;
3094+ return Ty :: new_error ( tcx, err) ;
3095+ }
3096+ } else {
3097+ if let Some ( variant) = variant {
3098+ let adt_path = tcx. def_path_str ( base_did) ;
3099+ struct_span_code_err ! (
3100+ dcx,
3101+ variant. span,
3102+ E0609 ,
3103+ "{kind_name} `{adt_path}` does not have any variants" ,
3104+ )
3105+ . with_span_label ( variant. span , "variant unknown" )
3106+ . emit ( ) ;
3107+ }
3108+ ( FIRST_VARIANT , def. non_enum_variant ( ) )
3109+ } ;
3110+ let block = tcx. local_def_id_to_hir_id ( item_def_id) ;
3111+ let ( ident, def_scope) = tcx. adjust_ident_and_get_scope ( field, def. did ( ) , block) ;
3112+ if let Some ( ( field_idx, field) ) = variant
3113+ . fields
3114+ . iter_enumerated ( )
3115+ . find ( |( _, f) | f. ident ( tcx) . normalize_to_macros_2_0 ( ) == ident)
3116+ {
3117+ if field. vis . is_accessible_from ( def_scope, tcx) {
3118+ tcx. check_stability ( field. did , Some ( hir_id) , ident. span , None ) ;
3119+ } else {
3120+ let adt_path = tcx. def_path_str ( base_did) ;
3121+ struct_span_code_err ! (
3122+ dcx,
3123+ ident. span,
3124+ E0616 ,
3125+ "field `{ident}` of {kind_name} `{adt_path}` is private" ,
3126+ )
3127+ . with_span_label ( ident. span , "private field" )
3128+ . emit ( ) ;
3129+ }
3130+ Ty :: new_field_representing_type (
3131+ tcx,
3132+ ty,
3133+ FieldId { variant : variant_idx, field : field_idx } ,
3134+ )
3135+ } else {
3136+ let err =
3137+ dcx. create_err ( NoFieldOnType { span : ident. span , field : ident, ty } ) . emit ( ) ;
3138+ Ty :: new_error ( tcx, err)
3139+ }
3140+ }
3141+ ty:: Tuple ( tys) => {
3142+ let index = match field. as_str ( ) . parse :: < usize > ( ) {
3143+ Ok ( idx) => idx,
3144+ Err ( _) => {
3145+ let err =
3146+ dcx. create_err ( NoFieldOnType { span : field. span , field, ty } ) . emit ( ) ;
3147+ return Ty :: new_error ( tcx, err) ;
3148+ }
3149+ } ;
3150+ if field. name != sym:: integer ( index) {
3151+ bug ! ( "we parsed above, but now not equal?" ) ;
3152+ }
3153+ if tys. get ( index) . is_some ( ) {
3154+ Ty :: new_field_representing_type (
3155+ tcx,
3156+ ty,
3157+ FieldId { variant : FIRST_VARIANT , field : index. into ( ) } ,
3158+ )
3159+ } else {
3160+ let err = dcx. create_err ( NoFieldOnType { span : field. span , field, ty } ) . emit ( ) ;
3161+ Ty :: new_error ( tcx, err)
3162+ }
3163+ }
3164+ // FIXME(FRTs): support type aliases
3165+ /*
3166+ ty::Alias(AliasTyKind::Free, ty) => {
3167+ return self.lower_field_of(
3168+ ty,
3169+ item_def_id,
3170+ ty_span,
3171+ hir_id,
3172+ variant,
3173+ field,
3174+ );
3175+ }*/
3176+ ty:: Alias ( ..) => Ty :: new_error (
3177+ tcx,
3178+ dcx. span_err ( ty_span, format ! ( "could not resolve fields of `{ty}`" ) ) ,
3179+ ) ,
3180+ ty:: Error ( err) => Ty :: new_error ( tcx, * err) ,
3181+ ty:: Bool
3182+ | ty:: Char
3183+ | ty:: Int ( _)
3184+ | ty:: Uint ( _)
3185+ | ty:: Float ( _)
3186+ | ty:: Foreign ( _)
3187+ | ty:: Str
3188+ | ty:: FRT ( _, _)
3189+ | ty:: RawPtr ( _, _)
3190+ | ty:: Ref ( _, _, _)
3191+ | ty:: FnDef ( _, _)
3192+ | ty:: FnPtr ( _, _)
3193+ | ty:: UnsafeBinder ( _)
3194+ | ty:: Dynamic ( _, _)
3195+ | ty:: Closure ( _, _)
3196+ | ty:: CoroutineClosure ( _, _)
3197+ | ty:: Coroutine ( _, _)
3198+ | ty:: CoroutineWitness ( _, _)
3199+ | ty:: Never
3200+ | ty:: Param ( _)
3201+ | ty:: Bound ( _, _)
3202+ | ty:: Placeholder ( _)
3203+ | ty:: Slice ( ..) => Ty :: new_error (
3204+ tcx,
3205+ dcx. span_err ( ty_span, format ! ( "type `{ty}` doesn't have fields" ) ) ,
3206+ ) ,
3207+ ty:: Infer ( _) => Ty :: new_error (
3208+ tcx,
3209+ dcx. span_err ( ty_span, format ! ( "cannot use `{ty}` in this position" ) ) ,
3210+ ) ,
3211+ // FIXME(FRTs): support these types?
3212+ ty:: Array ( ..) | ty:: Pat ( ..) => Ty :: new_error (
3213+ tcx,
3214+ dcx. span_err ( ty_span, format ! ( "type `{ty}` is not yet supported in `field_of!`" ) ) ,
3215+ ) ,
3216+ }
3217+ }
3218+
30573219 /// Lower an opaque type (i.e., an existential impl-Trait type) from the HIR.
30583220 #[ instrument( level = "debug" , skip( self ) , ret) ]
30593221 fn lower_opaque_ty ( & self , def_id : LocalDefId , in_trait : Option < LocalDefId > ) -> Ty < ' tcx > {
0 commit comments