1313#![ crate_type = "dylib" ]  
1414#![ crate_type = "rlib" ]  
1515#![ doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png" ,  
16-       html_favicon_url = "https://doc.rust-lang.org/favicon.ico" ,  
17-       html_root_url = "https://doc.rust-lang.org/nightly/" ) ]  
16+         html_favicon_url = "https://doc.rust-lang.org/favicon.ico" ,  
17+         html_root_url = "https://doc.rust-lang.org/nightly/" ) ]  
1818#![ deny( warnings) ]  
1919
2020#![ feature( rustc_diagnostic_macros) ]  
@@ -30,7 +30,6 @@ use rustc::hir::def::Def;
3030use  rustc:: hir:: def_id:: { CRATE_DEF_INDEX ,  LOCAL_CRATE ,  CrateNum ,  DefId } ; 
3131use  rustc:: hir:: intravisit:: { self ,  Visitor ,  NestedVisitorMap } ; 
3232use  rustc:: hir:: itemlikevisit:: DeepVisitor ; 
33- use  rustc:: hir:: pat_util:: EnumerateAndAdjustIterator ; 
3433use  rustc:: lint; 
3534use  rustc:: middle:: privacy:: { AccessLevel ,  AccessLevels } ; 
3635use  rustc:: ty:: { self ,  TyCtxt ,  Ty ,  TypeFoldable } ; 
@@ -415,97 +414,69 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b
415414    } 
416415} 
417416
418- //////////////////////////////////////////////////////////////////////////////// 
419- /// The privacy visitor, where privacy checks take place (violations reported) 
420- //////////////////////////////////////////////////////////////////////////////// 
417+ ////////////////////////////////////////////////////////////////////////////////////// 
418+ /// Name privacy visitor, checks privacy and reports violations. 
419+ /// Most of name privacy checks are performed during the main resolution phase, 
420+ /// or later in type checking when field accesses and associated items are resolved. 
421+ /// This pass performs remaining checks for fields in struct expressions and patterns. 
422+ ////////////////////////////////////////////////////////////////////////////////////// 
421423
422- struct  PrivacyVisitor < ' a ,  ' tcx :  ' a >  { 
424+ struct  NamePrivacyVisitor < ' a ,  ' tcx :  ' a >  { 
423425    tcx :  TyCtxt < ' a ,  ' tcx ,  ' tcx > , 
424-     curitem :  DefId , 
425-     in_foreign :  bool , 
426426    tables :  & ' a  ty:: TypeckTables < ' tcx > , 
427+     current_item :  DefId , 
427428} 
428429
429- impl < ' a ,  ' tcx >  PrivacyVisitor < ' a ,  ' tcx >  { 
430-     fn  item_is_accessible ( & self ,  did :  DefId )  -> bool  { 
431-         match  self . tcx . hir . as_local_node_id ( did)  { 
432-             Some ( node_id)  =>
433-                 ty:: Visibility :: from_hir ( & self . tcx . hir . expect_item ( node_id) . vis ,  node_id,  self . tcx ) , 
434-             None  => self . tcx . sess . cstore . visibility ( did) , 
435-         } . is_accessible_from ( self . curitem ,  self . tcx ) 
436-     } 
437- 
438-     // Checks that a field is in scope. 
430+ impl < ' a ,  ' tcx >  NamePrivacyVisitor < ' a ,  ' tcx >  { 
431+     // Checks that a field is accessible. 
439432    fn  check_field ( & mut  self ,  span :  Span ,  def :  & ' tcx  ty:: AdtDef ,  field :  & ' tcx  ty:: FieldDef )  { 
440-         if  !def. is_enum ( )  && !field. vis . is_accessible_from ( self . curitem ,  self . tcx )  { 
433+         if  !def. is_enum ( )  && !field. vis . is_accessible_from ( self . current_item ,  self . tcx )  { 
441434            struct_span_err ! ( self . tcx. sess,  span,  E0451 ,  "field `{}` of {} `{}` is private" , 
442-                       field. name,  def. variant_descr( ) ,  self . tcx. item_path_str( def. did) ) 
435+                               field. name,  def. variant_descr( ) ,  self . tcx. item_path_str( def. did) ) 
443436                . span_label ( span,  & format ! ( "field `{}` is private" ,  field. name) ) 
444437                . emit ( ) ; 
445438        } 
446439    } 
447- 
448-     // Checks that a method is in scope. 
449-     fn  check_method ( & mut  self ,  span :  Span ,  method_def_id :  DefId )  { 
450-         match  self . tcx . associated_item ( method_def_id) . container  { 
451-             // Trait methods are always all public. The only controlling factor 
452-             // is whether the trait itself is accessible or not. 
453-             ty:: TraitContainer ( trait_def_id)  if  !self . item_is_accessible ( trait_def_id)  => { 
454-                 let  msg = format ! ( "source trait `{}` is private" , 
455-                                   self . tcx. item_path_str( trait_def_id) ) ; 
456-                 self . tcx . sess . span_err ( span,  & msg) ; 
457-             } 
458-             _ => { } 
459-         } 
460-     } 
461440} 
462441
463- impl < ' a ,  ' tcx >  Visitor < ' tcx >  for  PrivacyVisitor < ' a ,  ' tcx >  { 
442+ impl < ' a ,  ' tcx >  Visitor < ' tcx >  for  NamePrivacyVisitor < ' a ,  ' tcx >  { 
464443    /// We want to visit items in the context of their containing 
465444     /// module and so forth, so supply a crate for doing a deep walk. 
466445     fn  nested_visit_map < ' this > ( & ' this  mut  self )  -> NestedVisitorMap < ' this ,  ' tcx >  { 
467446        NestedVisitorMap :: All ( & self . tcx . hir ) 
468447    } 
469448
470449    fn  visit_nested_body ( & mut  self ,  body :  hir:: BodyId )  { 
471-         let  old_tables = self . tables ; 
472-         self . tables  = self . tcx . body_tables ( body) ; 
450+         let  orig_tables = replace ( & mut  self . tables ,  self . tcx . body_tables ( body) ) ; 
473451        let  body = self . tcx . hir . body ( body) ; 
474452        self . visit_body ( body) ; 
475-         self . tables  = old_tables ; 
453+         self . tables  = orig_tables ; 
476454    } 
477455
478456    fn  visit_item ( & mut  self ,  item :  & ' tcx  hir:: Item )  { 
479-         let  orig_curitem  = replace ( & mut  self . curitem ,  self . tcx . hir . local_def_id ( item. id ) ) ; 
457+         let  orig_current_item  = replace ( & mut  self . current_item ,  self . tcx . hir . local_def_id ( item. id ) ) ; 
480458        intravisit:: walk_item ( self ,  item) ; 
481-         self . curitem  = orig_curitem ; 
459+         self . current_item  = orig_current_item ; 
482460    } 
483461
484462    fn  visit_expr ( & mut  self ,  expr :  & ' tcx  hir:: Expr )  { 
485463        match  expr. node  { 
486-             hir:: ExprMethodCall ( ..)  => { 
487-                 let  method_call = ty:: MethodCall :: expr ( expr. id ) ; 
488-                 let  method = self . tables . method_map [ & method_call] ; 
489-                 self . check_method ( expr. span ,  method. def_id ) ; 
490-             } 
491-             hir:: ExprStruct ( ref  qpath,  ref  expr_fields,  _)  => { 
464+             hir:: ExprStruct ( ref  qpath,  ref  fields,  ref  base)  => { 
492465                let  def = self . tables . qpath_def ( qpath,  expr. id ) ; 
493466                let  adt = self . tables . expr_ty ( expr) . ty_adt_def ( ) . unwrap ( ) ; 
494467                let  variant = adt. variant_of_def ( def) ; 
495-                 // RFC 736: ensure all unmentioned fields are visible. 
496-                 // Rather than computing the set of  unmentioned fields 
497-                 // (i.e. `all_fields - fields`), just check them all,  
498-                 // unless the ADT is a union, then unmentioned fields 
499-                 // are not checked. 
500-                 if  adt . is_union ( )   { 
501-                     for  expr_field  in  expr_fields  { 
502-                         self . check_field ( expr . span ,  adt,  variant . field_named ( expr_field . name . node ) ) ; 
468+                 if   let   Some ( ref  base )  =  * base  { 
469+                      // If the expression uses FRU we need to make sure all the  unmentioned fields 
470+                      // are checked for privacy (RFC 736). Rather than computing the set of  
471+                      // unmentioned fields, just check them all. 
472+                      for  variant_field  in   & variant . fields   { 
473+                          let  field = fields . iter ( ) . find ( |f| f . name . node  == variant_field . name ) ; 
474+                          let  span =  if   let   Some ( f )  = field  {  f . span   }   else   {  base . span   } ; 
475+                         self . check_field ( span,  adt,  variant_field ) ; 
503476                    } 
504477                }  else  { 
505-                     for  field in  & variant. fields  { 
506-                         let  expr_field = expr_fields. iter ( ) . find ( |f| f. name . node  == field. name ) ; 
507-                         let  span = if  let  Some ( f)  = expr_field {  f. span  }  else  {  expr. span  } ; 
508-                         self . check_field ( span,  adt,  field) ; 
478+                     for  field in  fields { 
479+                         self . check_field ( field. span ,  adt,  variant. field_named ( field. name . node ) ) ; 
509480                    } 
510481                } 
511482            } 
@@ -515,47 +486,20 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> {
515486        intravisit:: walk_expr ( self ,  expr) ; 
516487    } 
517488
518-     fn  visit_pat ( & mut  self ,  pattern :  & ' tcx  hir:: Pat )  { 
519-         // Foreign functions do not have their patterns mapped in the def_map, 
520-         // and there's nothing really relevant there anyway, so don't bother 
521-         // checking privacy. If you can name the type then you can pass it to an 
522-         // external C function anyway. 
523-         if  self . in_foreign  {  return  } 
524- 
525-         match  pattern. node  { 
489+     fn  visit_pat ( & mut  self ,  pat :  & ' tcx  hir:: Pat )  { 
490+         match  pat. node  { 
526491            PatKind :: Struct ( ref  qpath,  ref  fields,  _)  => { 
527-                 let  def = self . tables . qpath_def ( qpath,  pattern . id ) ; 
528-                 let  adt = self . tables . pat_ty ( pattern ) . ty_adt_def ( ) . unwrap ( ) ; 
492+                 let  def = self . tables . qpath_def ( qpath,  pat . id ) ; 
493+                 let  adt = self . tables . pat_ty ( pat ) . ty_adt_def ( ) . unwrap ( ) ; 
529494                let  variant = adt. variant_of_def ( def) ; 
530495                for  field in  fields { 
531496                    self . check_field ( field. span ,  adt,  variant. field_named ( field. node . name ) ) ; 
532497                } 
533498            } 
534-             PatKind :: TupleStruct ( _,  ref  fields,  ddpos)  => { 
535-                 match  self . tables . pat_ty ( pattern) . sty  { 
536-                     // enum fields have no privacy at this time 
537-                     ty:: TyAdt ( def,  _)  if  !def. is_enum ( )  => { 
538-                         let  expected_len = def. struct_variant ( ) . fields . len ( ) ; 
539-                         for  ( i,  field)  in  fields. iter ( ) . enumerate_and_adjust ( expected_len,  ddpos)  { 
540-                             if  let  PatKind :: Wild  = field. node  { 
541-                                 continue 
542-                             } 
543-                             self . check_field ( field. span ,  def,  & def. struct_variant ( ) . fields [ i] ) ; 
544-                         } 
545-                     } 
546-                     _ => { } 
547-                 } 
548-             } 
549499            _ => { } 
550500        } 
551501
552-         intravisit:: walk_pat ( self ,  pattern) ; 
553-     } 
554- 
555-     fn  visit_foreign_item ( & mut  self ,  fi :  & ' tcx  hir:: ForeignItem )  { 
556-         self . in_foreign  = true ; 
557-         intravisit:: walk_foreign_item ( self ,  fi) ; 
558-         self . in_foreign  = false ; 
502+         intravisit:: walk_pat ( self ,  pat) ; 
559503    } 
560504} 
561505
@@ -1233,17 +1177,14 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12331177
12341178    let  krate = tcx. hir . krate ( ) ; 
12351179
1236-     // Use the parent map to check the privacy of everything 
1237-     let  mut  visitor = PrivacyVisitor  { 
1238-         curitem :  DefId :: local ( CRATE_DEF_INDEX ) , 
1239-         in_foreign :  false , 
1180+     // Check privacy of names not checked in previous compilation stages. 
1181+     let  mut  visitor = NamePrivacyVisitor  { 
12401182        tcx :  tcx, 
12411183        tables :  & ty:: TypeckTables :: empty ( ) , 
1184+         current_item :  DefId :: local ( CRATE_DEF_INDEX ) , 
12421185    } ; 
12431186    intravisit:: walk_crate ( & mut  visitor,  krate) ; 
12441187
1245-     tcx. sess . abort_if_errors ( ) ; 
1246- 
12471188    // Build up a set of all exported items in the AST. This is a set of all 
12481189    // items which are reachable from external crates based on visibility. 
12491190    let  mut  visitor = EmbargoVisitor  { 
0 commit comments