13
13
#![ crate_type = "dylib" ]
14
14
#![ crate_type = "rlib" ]
15
15
#![ 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/" ) ]
18
18
#![ deny( warnings) ]
19
19
20
20
#![ feature( rustc_diagnostic_macros) ]
@@ -30,7 +30,6 @@ use rustc::hir::def::Def;
30
30
use rustc:: hir:: def_id:: { CRATE_DEF_INDEX , LOCAL_CRATE , CrateNum , DefId } ;
31
31
use rustc:: hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
32
32
use rustc:: hir:: itemlikevisit:: DeepVisitor ;
33
- use rustc:: hir:: pat_util:: EnumerateAndAdjustIterator ;
34
33
use rustc:: lint;
35
34
use rustc:: middle:: privacy:: { AccessLevel , AccessLevels } ;
36
35
use rustc:: ty:: { self , TyCtxt , Ty , TypeFoldable } ;
@@ -415,70 +414,69 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b
415
414
}
416
415
}
417
416
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
+ //////////////////////////////////////////////////////////////////////////////////////
421
423
422
- struct PrivacyVisitor < ' a , ' tcx : ' a > {
424
+ struct NamePrivacyVisitor < ' a , ' tcx : ' a > {
423
425
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
424
- curitem : DefId ,
425
- in_foreign : bool ,
426
426
tables : & ' a ty:: TypeckTables < ' tcx > ,
427
+ current_item : DefId ,
427
428
}
428
429
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 .
431
432
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 ) {
433
434
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) )
435
436
. span_label ( span, & format ! ( "field `{}` is private" , field. name) )
436
437
. emit ( ) ;
437
438
}
438
439
}
439
440
}
440
441
441
- impl < ' a , ' tcx > Visitor < ' tcx > for PrivacyVisitor < ' a , ' tcx > {
442
+ impl < ' a , ' tcx > Visitor < ' tcx > for NamePrivacyVisitor < ' a , ' tcx > {
442
443
/// We want to visit items in the context of their containing
443
444
/// module and so forth, so supply a crate for doing a deep walk.
444
445
fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
445
446
NestedVisitorMap :: All ( & self . tcx . hir )
446
447
}
447
448
448
449
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) ) ;
451
451
let body = self . tcx . hir . body ( body) ;
452
452
self . visit_body ( body) ;
453
- self . tables = old_tables ;
453
+ self . tables = orig_tables ;
454
454
}
455
455
456
456
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 ) ) ;
458
458
intravisit:: walk_item ( self , item) ;
459
- self . curitem = orig_curitem ;
459
+ self . current_item = orig_current_item ;
460
460
}
461
461
462
462
fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr ) {
463
463
match expr. node {
464
- hir:: ExprStruct ( ref qpath, ref expr_fields , _ ) => {
464
+ hir:: ExprStruct ( ref qpath, ref fields , ref base ) => {
465
465
let def = self . tables . qpath_def ( qpath, expr. id ) ;
466
466
let adt = self . tables . expr_ty ( expr) . ty_adt_def ( ) . unwrap ( ) ;
467
467
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 ) ;
476
476
}
477
477
} 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 ) ) ;
482
480
}
483
481
}
484
482
}
@@ -488,47 +486,20 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> {
488
486
intravisit:: walk_expr ( self , expr) ;
489
487
}
490
488
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 {
499
491
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 ( ) ;
502
494
let variant = adt. variant_of_def ( def) ;
503
495
for field in fields {
504
496
self . check_field ( field. span , adt, variant. field_named ( field. node . name ) ) ;
505
497
}
506
498
}
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
- }
522
499
_ => { }
523
500
}
524
501
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) ;
532
503
}
533
504
}
534
505
@@ -1206,17 +1177,14 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1206
1177
1207
1178
let krate = tcx. hir . krate ( ) ;
1208
1179
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 {
1213
1182
tcx : tcx,
1214
1183
tables : & ty:: TypeckTables :: empty ( ) ,
1184
+ current_item : DefId :: local ( CRATE_DEF_INDEX ) ,
1215
1185
} ;
1216
1186
intravisit:: walk_crate ( & mut visitor, krate) ;
1217
1187
1218
- tcx. sess . abort_if_errors ( ) ;
1219
-
1220
1188
// Build up a set of all exported items in the AST. This is a set of all
1221
1189
// items which are reachable from external crates based on visibility.
1222
1190
let mut visitor = EmbargoVisitor {
0 commit comments