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