@@ -351,6 +351,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
351
351
// Do not check privacy inside items with the resolve_unexported
352
352
// attribute. This is used for the test runner.
353
353
if !attr:: contains_name ( item. attrs , "!resolve_unexported" ) {
354
+ check_sane_privacy ( tcx, item) ;
354
355
oldvisit:: visit_item ( item, ( method_map, visitor) ) ;
355
356
}
356
357
} ,
@@ -540,3 +541,81 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
540
541
} ) ;
541
542
oldvisit:: visit_crate ( crate , ( method_map, visitor) ) ;
542
543
}
544
+
545
+ /// Validates all of the visibility qualifers placed on the item given. This
546
+ /// ensures that there are no extraneous qualifiers that don't actually do
547
+ /// anything. In theory these qualifiers wouldn't parse, but that may happen
548
+ /// later on down the road...
549
+ fn check_sane_privacy ( tcx : ty:: ctxt , item : @ast:: item ) {
550
+ match item. node {
551
+ // implementations of traits don't need visibility qualifiers because
552
+ // that's controlled by having the trait in scope.
553
+ ast:: item_impl( _, Some ( * ) , _, ref methods) => {
554
+ for m in methods. iter ( ) {
555
+ match m. vis {
556
+ ast:: private | ast:: public => {
557
+ tcx. sess . span_err ( m. span , "unnecessary visibility" )
558
+ }
559
+ ast:: inherited => { }
560
+ }
561
+ }
562
+ }
563
+
564
+ ast:: item_enum( ref def, _) => {
565
+ for v in def. variants . iter ( ) {
566
+ match v. node . vis {
567
+ ast:: public => {
568
+ if item. vis == ast:: public {
569
+ tcx. sess . span_err ( v. span , "unnecessary `pub` \
570
+ visibility") ;
571
+ }
572
+ }
573
+ ast:: private => {
574
+ if item. vis != ast:: public {
575
+ tcx. sess . span_err ( v. span , "unnecessary `priv` \
576
+ visibility") ;
577
+ }
578
+ }
579
+ ast:: inherited => { }
580
+ }
581
+ }
582
+ }
583
+
584
+ ast:: item_struct( ref def, _) => {
585
+ for f in def. fields . iter ( ) {
586
+ match f. node . kind {
587
+ ast:: named_field( _, ast:: public) => {
588
+ tcx. sess . span_err ( f. span , "unnecessary `pub` \
589
+ visibility") ;
590
+ }
591
+ ast:: named_field( _, ast:: private) => {
592
+ // Fields should really be private by default...
593
+ }
594
+ ast:: named_field( * ) | ast:: unnamed_field => { }
595
+ }
596
+ }
597
+ }
598
+
599
+ ast:: item_trait( _, _, ref methods) => {
600
+ for m in methods. iter ( ) {
601
+ match * m {
602
+ ast:: provided( ref m) => {
603
+ match m. vis {
604
+ ast:: private | ast:: public => {
605
+ tcx. sess . span_err ( m. span , "unnecessary \
606
+ visibility") ;
607
+ }
608
+ ast:: inherited => { }
609
+ }
610
+ }
611
+ // this is warned about in the parser
612
+ ast:: required( * ) => { }
613
+ }
614
+ }
615
+ }
616
+
617
+ ast:: item_impl( * ) | ast:: item_static( * ) | ast:: item_foreign_mod( * ) |
618
+ ast:: item_fn( * ) | ast:: item_mod( * ) | ast:: item_ty( * ) |
619
+ ast:: item_mac( * ) => { }
620
+ }
621
+ }
0 commit comments