@@ -19,12 +19,13 @@ use std::cell::Cell;
1919use std:: iter;
2020use std:: ops:: Bound ;
2121
22- use rustc_abi:: ExternAbi ;
22+ use rustc_abi:: { ExternAbi , FIRST_VARIANT } ;
2323use rustc_ast:: Recovered ;
2424use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
2525use rustc_data_structures:: unord:: UnordMap ;
2626use rustc_errors:: {
27- Applicability , Diag , DiagCtxtHandle , E0228 , ErrorGuaranteed , StashKey , struct_span_code_err,
27+ Applicability , Diag , DiagCtxtHandle , E0228 , E0616 , ErrorGuaranteed , StashKey ,
28+ struct_span_code_err,
2829} ;
2930use rustc_hir:: attrs:: AttributeKind ;
3031use rustc_hir:: def:: DefKind ;
@@ -36,7 +37,8 @@ use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
3637use rustc_middle:: query:: Providers ;
3738use rustc_middle:: ty:: util:: { Discr , IntTypeExt } ;
3839use rustc_middle:: ty:: {
39- self , AdtKind , Const , IsSuggestable , Ty , TyCtxt , TypeVisitableExt , TypingMode , fold_regions,
40+ self , AdtKind , Const , FieldPath , FieldPathKind , IsSuggestable , Ty , TyCtxt , TypeVisitableExt ,
41+ TypingMode , fold_regions,
4042} ;
4143use rustc_middle:: { bug, span_bug} ;
4244use rustc_span:: { DUMMY_SP , Ident , Span , Symbol , kw, sym} ;
@@ -47,7 +49,7 @@ use rustc_trait_selection::traits::{
4749} ;
4850use tracing:: { debug, instrument} ;
4951
50- use crate :: errors;
52+ use crate :: errors:: { self , NoFieldOnType } ;
5153use crate :: hir_ty_lowering:: {
5254 FeedConstTy , HirTyLowerer , InherentAssocCandidate , RegionInferReason ,
5355} ;
@@ -346,6 +348,84 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
346348 ty:: Const :: new_error_with_message ( self . tcx ( ) , span, "bad placeholder constant" )
347349 }
348350
351+ fn lower_field_path (
352+ & self ,
353+ container : & rustc_hir:: Ty < ' tcx > ,
354+ fields : & [ Ident ] ,
355+ span : Span ,
356+ hir_id : HirId ,
357+ field_path_kind : FieldPathKind ,
358+ ) -> Result < ( Ty < ' tcx > , FieldPath < ' tcx > ) , ErrorGuaranteed > {
359+ assert_eq ! ( field_path_kind, FieldPathKind :: FieldOf ) ;
360+ let container = self . lower_ty ( container) ;
361+
362+ let mut field_indices = Vec :: with_capacity ( fields. len ( ) ) ;
363+ let mut current_container = container;
364+ let mut fields = fields. into_iter ( ) ;
365+ let mut infcx = None ;
366+ let infcx = self . infcx ( ) . unwrap_or_else ( || {
367+ assert ! ( !container. has_infer( ) ) ;
368+ infcx = Some ( self . tcx ( ) . infer_ctxt ( ) . build ( ty:: TypingMode :: non_body_analysis ( ) ) ) ;
369+ infcx. as_ref ( ) . unwrap ( )
370+ } ) ;
371+
372+ while let Some ( & field) = fields. next ( ) {
373+ let container = infcx. shallow_resolve ( current_container) ;
374+ match container. kind ( ) {
375+ ty:: Adt ( def, args) if !def. is_enum ( ) => {
376+ let block = self . tcx . local_def_id_to_hir_id ( self . item_def_id ) ;
377+ let ( ident, def_scope) =
378+ self . tcx . adjust_ident_and_get_scope ( field, def. did ( ) , block) ;
379+
380+ let fields = & def. non_enum_variant ( ) . fields ;
381+ if let Some ( ( index, field) ) = fields
382+ . iter_enumerated ( )
383+ . find ( |( _, f) | f. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == ident)
384+ {
385+ let field_ty = field. ty ( self . tcx , args) ;
386+
387+ if field. vis . is_accessible_from ( def_scope, self . tcx ) {
388+ self . tcx . check_stability ( field. did , Some ( hir_id) , span, None ) ;
389+ } else {
390+ let base_did = def. did ( ) ;
391+ let struct_path = self . tcx ( ) . def_path_str ( base_did) ;
392+ let kind_name = self . tcx ( ) . def_descr ( base_did) ;
393+ struct_span_code_err ! (
394+ self . dcx( ) ,
395+ ident. span,
396+ E0616 ,
397+ "field `{ident}` of {kind_name} `{struct_path}` is private" ,
398+ )
399+ . with_span_label ( ident. span , "private field" )
400+ . emit ( ) ;
401+ }
402+
403+ field_indices. push ( ( FIRST_VARIANT , index) ) ;
404+ current_container = field_ty;
405+
406+ continue ;
407+ }
408+ }
409+ ty:: Tuple ( tys) => {
410+ if let Ok ( index) = field. as_str ( ) . parse :: < usize > ( )
411+ && field. name == sym:: integer ( index)
412+ && let Some ( & field_ty) = tys. get ( index)
413+ {
414+ field_indices. push ( ( FIRST_VARIANT , index. into ( ) ) ) ;
415+ current_container = field_ty;
416+ continue ;
417+ }
418+ }
419+ _ => { }
420+ }
421+ return Err ( self
422+ . dcx ( )
423+ . create_err ( NoFieldOnType { span : field. span , ty : container, field } )
424+ . emit ( ) ) ;
425+ }
426+ Ok ( ( container, self . tcx . mk_field_path_from_iter ( field_indices. into_iter ( ) ) ) )
427+ }
428+
349429 fn register_trait_ascription_bounds (
350430 & self ,
351431 _: Vec < ( ty:: Clause < ' tcx > , Span ) > ,
0 commit comments