14
14
15
15
use std:: mem:: replace;
16
16
17
+ use metadata:: csearch;
17
18
use middle:: lint;
18
19
use middle:: resolve;
19
20
use middle:: ty;
@@ -358,6 +359,12 @@ enum PrivacyResult {
358
359
DisallowedBy ( ast:: NodeId ) ,
359
360
}
360
361
362
+ enum FieldName {
363
+ UnnamedField ( uint ) , // index
364
+ // FIXME #6993: change type (and name) from Ident to Name
365
+ NamedField ( ast:: Ident ) ,
366
+ }
367
+
361
368
impl < ' a > PrivacyVisitor < ' a > {
362
369
// used when debugging
363
370
fn nodestr ( & self , id : ast:: NodeId ) -> ~str {
@@ -560,18 +567,23 @@ impl<'a> PrivacyVisitor<'a> {
560
567
}
561
568
562
569
// Checks that a field is in scope.
563
- // FIXME #6993: change type (and name) from Ident to Name
564
- fn check_field ( & mut self , span : Span , id : ast:: DefId , ident : ast:: Ident ) {
565
- for field in ty:: lookup_struct_fields ( self . tcx , id) . iter ( ) {
566
- if field. name != ident. name { continue ; }
567
- if field. vis == ast:: Public { break }
568
- if !is_local ( field. id ) ||
569
- !self . private_accessible ( field. id . node ) {
570
- self . tcx . sess . span_err ( span,
571
- format ! ( "field `{}` is private" ,
572
- token:: get_ident( ident) ) )
570
+ fn check_field ( & mut self , span : Span , id : ast:: DefId ,
571
+ name : FieldName ) {
572
+ let fields = ty:: lookup_struct_fields ( self . tcx , id) ;
573
+ let field = match name {
574
+ NamedField ( ident) => {
575
+ fields. iter ( ) . find ( |f| f. name == ident. name ) . unwrap ( )
573
576
}
574
- break ;
577
+ UnnamedField ( idx) => fields. get ( idx)
578
+ } ;
579
+ if field. vis == ast:: Public { return }
580
+ if !is_local ( field. id ) || !self . private_accessible ( field. id . node ) {
581
+ let msg = match name {
582
+ NamedField ( name) => format ! ( "field `{}` is private" ,
583
+ token:: get_ident( name) ) ,
584
+ UnnamedField ( idx) => format ! ( "field \\ #{} is private" , idx + 1 ) ,
585
+ } ;
586
+ self . tcx . sess . span_err ( span, msg) ;
575
587
}
576
588
}
577
589
@@ -634,10 +646,11 @@ impl<'a> PrivacyVisitor<'a> {
634
646
_ => { } ,
635
647
}
636
648
}
637
- // If an import is not used in either namespace, we still want to check
638
- // that it could be legal. Therefore we check in both namespaces and only
639
- // report an error if both would be illegal. We only report one error,
640
- // even if it is illegal to import from both namespaces.
649
+ // If an import is not used in either namespace, we still
650
+ // want to check that it could be legal. Therefore we check
651
+ // in both namespaces and only report an error if both would
652
+ // be illegal. We only report one error, even if it is
653
+ // illegal to import from both namespaces.
641
654
match ( value_priv, check_value, type_priv, check_type) {
642
655
( Some ( p) , resolve:: Unused , None , _) |
643
656
( None , _, Some ( p) , resolve:: Unused ) => {
@@ -701,7 +714,8 @@ impl<'a> PrivacyVisitor<'a> {
701
714
// is whether the trait itself is accessible or not.
702
715
MethodParam ( MethodParam { trait_id : trait_id, .. } ) |
703
716
MethodObject ( MethodObject { trait_id : trait_id, .. } ) => {
704
- self . report_error ( self . ensure_public ( span, trait_id, None , "source trait" ) ) ;
717
+ self . report_error ( self . ensure_public ( span, trait_id, None ,
718
+ "source trait" ) ) ;
705
719
}
706
720
}
707
721
}
@@ -726,7 +740,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
726
740
match ty:: get ( ty:: expr_ty_adjusted ( self . tcx , base,
727
741
& * self . method_map . borrow ( ) ) ) . sty {
728
742
ty:: ty_struct( id, _) => {
729
- self . check_field ( expr. span , id, ident) ;
743
+ self . check_field ( expr. span , id, NamedField ( ident) ) ;
730
744
}
731
745
_ => { }
732
746
}
@@ -749,15 +763,16 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
749
763
match ty:: get ( ty:: expr_ty ( self . tcx , expr) ) . sty {
750
764
ty:: ty_struct( id, _) => {
751
765
for field in ( * fields) . iter ( ) {
752
- self . check_field ( expr. span , id, field. ident . node ) ;
766
+ self . check_field ( expr. span , id,
767
+ NamedField ( field. ident . node ) ) ;
753
768
}
754
769
}
755
770
ty:: ty_enum( _, _) => {
756
771
match self . tcx . def_map . borrow ( ) . get_copy ( & expr. id ) {
757
772
ast:: DefVariant ( _, variant_id, _) => {
758
773
for field in fields. iter ( ) {
759
774
self . check_field ( expr. span , variant_id,
760
- field. ident . node ) ;
775
+ NamedField ( field. ident . node ) ) ;
761
776
}
762
777
}
763
778
_ => self . tcx . sess . span_bug ( expr. span ,
@@ -772,6 +787,46 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
772
787
struct type?!") ,
773
788
}
774
789
}
790
+ ast:: ExprPath ( ..) => {
791
+ let guard = |did : ast:: DefId | {
792
+ let fields = ty:: lookup_struct_fields ( self . tcx , did) ;
793
+ let any_priv = fields. iter ( ) . any ( |f| {
794
+ f. vis != ast:: Public && (
795
+ !is_local ( f. id ) ||
796
+ !self . private_accessible ( f. id . node ) )
797
+ } ) ;
798
+ if any_priv {
799
+ self . tcx . sess . span_err ( expr. span ,
800
+ "cannot invoke tuple struct constructor \
801
+ with private fields") ;
802
+ }
803
+ } ;
804
+ match self . tcx . def_map . borrow ( ) . find ( & expr. id ) {
805
+ Some ( & ast:: DefStruct ( did) ) => {
806
+ guard ( if is_local ( did) {
807
+ local_def ( self . tcx . map . get_parent ( did. node ) )
808
+ } else {
809
+ // "tuple structs" with zero fields (such as
810
+ // `pub struct Foo;`) don't have a ctor_id, hence
811
+ // the unwrap_or to the same struct id.
812
+ let maybe_did =
813
+ csearch:: get_tuple_struct_definition_if_ctor (
814
+ & self . tcx . sess . cstore , did) ;
815
+ maybe_did. unwrap_or ( did)
816
+ } )
817
+ }
818
+ // Tuple struct constructors across crates are identified as
819
+ // DefFn types, so we explicitly handle that case here.
820
+ Some ( & ast:: DefFn ( did, _) ) if !is_local ( did) => {
821
+ match csearch:: get_tuple_struct_definition_if_ctor (
822
+ & self . tcx . sess . cstore , did) {
823
+ Some ( did) => guard ( did) ,
824
+ None => { }
825
+ }
826
+ }
827
+ _ => { }
828
+ }
829
+ }
775
830
_ => { }
776
831
}
777
832
@@ -821,15 +876,16 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
821
876
match ty:: get ( ty:: pat_ty ( self . tcx , pattern) ) . sty {
822
877
ty:: ty_struct( id, _) => {
823
878
for field in fields. iter ( ) {
824
- self . check_field ( pattern. span , id, field. ident ) ;
879
+ self . check_field ( pattern. span , id,
880
+ NamedField ( field. ident ) ) ;
825
881
}
826
882
}
827
883
ty:: ty_enum( _, _) => {
828
884
match self . tcx . def_map . borrow ( ) . find ( & pattern. id ) {
829
885
Some ( & ast:: DefVariant ( _, variant_id, _) ) => {
830
886
for field in fields. iter ( ) {
831
887
self . check_field ( pattern. span , variant_id,
832
- field. ident ) ;
888
+ NamedField ( field. ident ) ) ;
833
889
}
834
890
}
835
891
_ => self . tcx . sess . span_bug ( pattern. span ,
@@ -844,6 +900,27 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
844
900
struct type?!") ,
845
901
}
846
902
}
903
+
904
+ // Patterns which bind no fields are allowable (the path is check
905
+ // elsewhere).
906
+ ast:: PatEnum ( _, Some ( ref fields) ) => {
907
+ match ty:: get ( ty:: pat_ty ( self . tcx , pattern) ) . sty {
908
+ ty:: ty_struct( id, _) => {
909
+ for ( i, field) in fields. iter ( ) . enumerate ( ) {
910
+ match field. node {
911
+ ast:: PatWild ( ..) => continue ,
912
+ _ => { }
913
+ }
914
+ self . check_field ( field. span , id, UnnamedField ( i) ) ;
915
+ }
916
+ }
917
+ ty:: ty_enum( ..) => {
918
+ // enum fields have no privacy at this time
919
+ }
920
+ _ => { }
921
+ }
922
+
923
+ }
847
924
_ => { }
848
925
}
849
926
0 commit comments