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,97 +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
- 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.
439
432
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 ) {
441
434
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) )
443
436
. span_label ( span, & format ! ( "field `{}` is private" , field. name) )
444
437
. emit ( ) ;
445
438
}
446
439
}
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
- }
461
440
}
462
441
463
- impl < ' a , ' tcx > Visitor < ' tcx > for PrivacyVisitor < ' a , ' tcx > {
442
+ impl < ' a , ' tcx > Visitor < ' tcx > for NamePrivacyVisitor < ' a , ' tcx > {
464
443
/// We want to visit items in the context of their containing
465
444
/// module and so forth, so supply a crate for doing a deep walk.
466
445
fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
467
446
NestedVisitorMap :: All ( & self . tcx . hir )
468
447
}
469
448
470
449
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) ) ;
473
451
let body = self . tcx . hir . body ( body) ;
474
452
self . visit_body ( body) ;
475
- self . tables = old_tables ;
453
+ self . tables = orig_tables ;
476
454
}
477
455
478
456
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 ) ) ;
480
458
intravisit:: walk_item ( self , item) ;
481
- self . curitem = orig_curitem ;
459
+ self . current_item = orig_current_item ;
482
460
}
483
461
484
462
fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr ) {
485
463
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) => {
492
465
let def = self . tables . qpath_def ( qpath, expr. id ) ;
493
466
let adt = self . tables . expr_ty ( expr) . ty_adt_def ( ) . unwrap ( ) ;
494
467
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 ) ;
503
476
}
504
477
} 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 ) ) ;
509
480
}
510
481
}
511
482
}
@@ -515,47 +486,20 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> {
515
486
intravisit:: walk_expr ( self , expr) ;
516
487
}
517
488
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 {
526
491
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 ( ) ;
529
494
let variant = adt. variant_of_def ( def) ;
530
495
for field in fields {
531
496
self . check_field ( field. span , adt, variant. field_named ( field. node . name ) ) ;
532
497
}
533
498
}
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
- }
549
499
_ => { }
550
500
}
551
501
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) ;
559
503
}
560
504
}
561
505
@@ -1233,17 +1177,14 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1233
1177
1234
1178
let krate = tcx. hir . krate ( ) ;
1235
1179
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 {
1240
1182
tcx : tcx,
1241
1183
tables : & ty:: TypeckTables :: empty ( ) ,
1184
+ current_item : DefId :: local ( CRATE_DEF_INDEX ) ,
1242
1185
} ;
1243
1186
intravisit:: walk_crate ( & mut visitor, krate) ;
1244
1187
1245
- tcx. sess . abort_if_errors ( ) ;
1246
-
1247
1188
// Build up a set of all exported items in the AST. This is a set of all
1248
1189
// items which are reachable from external crates based on visibility.
1249
1190
let mut visitor = EmbargoVisitor {
0 commit comments