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,70 +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- // Checks that a field is in scope .
430+ impl < ' a , ' tcx > NamePrivacyVisitor < ' a , ' tcx > {
431+ // Checks that a field is accessible .
431432 fn check_field ( & mut self , span : Span , def : & ' tcx ty:: AdtDef , field : & ' tcx ty:: FieldDef ) {
432- 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 ) {
433434 struct_span_err ! ( self . tcx. sess, span, E0451 , "field `{}` of {} `{}` is private" ,
434- 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) )
435436 . span_label ( span, & format ! ( "field `{}` is private" , field. name) )
436437 . emit ( ) ;
437438 }
438439 }
439440}
440441
441- impl < ' a , ' tcx > Visitor < ' tcx > for PrivacyVisitor < ' a , ' tcx > {
442+ impl < ' a , ' tcx > Visitor < ' tcx > for NamePrivacyVisitor < ' a , ' tcx > {
442443 /// We want to visit items in the context of their containing
443444 /// module and so forth, so supply a crate for doing a deep walk.
444445 fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
445446 NestedVisitorMap :: All ( & self . tcx . hir )
446447 }
447448
448449 fn visit_nested_body ( & mut self , body : hir:: BodyId ) {
449- let old_tables = self . tables ;
450- self . tables = self . tcx . body_tables ( body) ;
450+ let orig_tables = replace ( & mut self . tables , self . tcx . body_tables ( body) ) ;
451451 let body = self . tcx . hir . body ( body) ;
452452 self . visit_body ( body) ;
453- self . tables = old_tables ;
453+ self . tables = orig_tables ;
454454 }
455455
456456 fn visit_item ( & mut self , item : & ' tcx hir:: Item ) {
457- 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 ) ) ;
458458 intravisit:: walk_item ( self , item) ;
459- self . curitem = orig_curitem ;
459+ self . current_item = orig_current_item ;
460460 }
461461
462462 fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr ) {
463463 match expr. node {
464- hir:: ExprStruct ( ref qpath, ref expr_fields , _ ) => {
464+ hir:: ExprStruct ( ref qpath, ref fields , ref base ) => {
465465 let def = self . tables . qpath_def ( qpath, expr. id ) ;
466466 let adt = self . tables . expr_ty ( expr) . ty_adt_def ( ) . unwrap ( ) ;
467467 let variant = adt. variant_of_def ( def) ;
468- // RFC 736: ensure all unmentioned fields are visible.
469- // Rather than computing the set of unmentioned fields
470- // (i.e. `all_fields - fields`), just check them all,
471- // unless the ADT is a union, then unmentioned fields
472- // are not checked.
473- if adt . is_union ( ) {
474- for expr_field in expr_fields {
475- 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 ) ;
476476 }
477477 } else {
478- for field in & variant. fields {
479- let expr_field = expr_fields. iter ( ) . find ( |f| f. name . node == field. name ) ;
480- let span = if let Some ( f) = expr_field { f. span } else { expr. span } ;
481- self . check_field ( span, adt, field) ;
478+ for field in fields {
479+ self . check_field ( field. span , adt, variant. field_named ( field. name . node ) ) ;
482480 }
483481 }
484482 }
@@ -488,47 +486,20 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> {
488486 intravisit:: walk_expr ( self , expr) ;
489487 }
490488
491- fn visit_pat ( & mut self , pattern : & ' tcx hir:: Pat ) {
492- // Foreign functions do not have their patterns mapped in the def_map,
493- // and there's nothing really relevant there anyway, so don't bother
494- // checking privacy. If you can name the type then you can pass it to an
495- // external C function anyway.
496- if self . in_foreign { return }
497-
498- match pattern. node {
489+ fn visit_pat ( & mut self , pat : & ' tcx hir:: Pat ) {
490+ match pat. node {
499491 PatKind :: Struct ( ref qpath, ref fields, _) => {
500- let def = self . tables . qpath_def ( qpath, pattern . id ) ;
501- 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 ( ) ;
502494 let variant = adt. variant_of_def ( def) ;
503495 for field in fields {
504496 self . check_field ( field. span , adt, variant. field_named ( field. node . name ) ) ;
505497 }
506498 }
507- PatKind :: TupleStruct ( _, ref fields, ddpos) => {
508- match self . tables . pat_ty ( pattern) . sty {
509- // enum fields have no privacy at this time
510- ty:: TyAdt ( def, _) if !def. is_enum ( ) => {
511- let expected_len = def. struct_variant ( ) . fields . len ( ) ;
512- for ( i, field) in fields. iter ( ) . enumerate_and_adjust ( expected_len, ddpos) {
513- if let PatKind :: Wild = field. node {
514- continue
515- }
516- self . check_field ( field. span , def, & def. struct_variant ( ) . fields [ i] ) ;
517- }
518- }
519- _ => { }
520- }
521- }
522499 _ => { }
523500 }
524501
525- intravisit:: walk_pat ( self , pattern) ;
526- }
527-
528- fn visit_foreign_item ( & mut self , fi : & ' tcx hir:: ForeignItem ) {
529- self . in_foreign = true ;
530- intravisit:: walk_foreign_item ( self , fi) ;
531- self . in_foreign = false ;
502+ intravisit:: walk_pat ( self , pat) ;
532503 }
533504}
534505
@@ -1206,17 +1177,14 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12061177
12071178 let krate = tcx. hir . krate ( ) ;
12081179
1209- // Use the parent map to check the privacy of everything
1210- let mut visitor = PrivacyVisitor {
1211- curitem : DefId :: local ( CRATE_DEF_INDEX ) ,
1212- in_foreign : false ,
1180+ // Check privacy of names not checked in previous compilation stages.
1181+ let mut visitor = NamePrivacyVisitor {
12131182 tcx : tcx,
12141183 tables : & ty:: TypeckTables :: empty ( ) ,
1184+ current_item : DefId :: local ( CRATE_DEF_INDEX ) ,
12151185 } ;
12161186 intravisit:: walk_crate ( & mut visitor, krate) ;
12171187
1218- tcx. sess . abort_if_errors ( ) ;
1219-
12201188 // Build up a set of all exported items in the AST. This is a set of all
12211189 // items which are reachable from external crates based on visibility.
12221190 let mut visitor = EmbargoVisitor {
0 commit comments