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