@@ -614,6 +614,7 @@ struct TypePrivacyVisitor<'a, 'tcx: 'a> {
614
614
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
615
615
tables : & ' a ty:: TypeckTables < ' tcx > ,
616
616
current_item : DefId ,
617
+ in_body : bool ,
617
618
span : Span ,
618
619
empty_tables : & ' a ty:: TypeckTables < ' tcx > ,
619
620
}
@@ -671,10 +672,8 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
671
672
// Take node ID of an expression or pattern and check its type for privacy.
672
673
fn check_expr_pat_type ( & mut self , id : hir:: HirId , span : Span ) -> bool {
673
674
self . span = span;
674
- if let Some ( ty) = self . tables . node_id_to_type_opt ( id) {
675
- if ty. visit_with ( self ) {
676
- return true ;
677
- }
675
+ if self . tables . node_id_to_type ( id) . visit_with ( self ) {
676
+ return true ;
678
677
}
679
678
if self . tables . node_substs ( id) . visit_with ( self ) {
680
679
return true ;
@@ -688,6 +687,16 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
688
687
}
689
688
false
690
689
}
690
+
691
+ fn check_trait_ref ( & mut self , trait_ref : ty:: TraitRef < ' tcx > ) -> bool {
692
+ if !self . item_is_accessible ( trait_ref. def_id ) {
693
+ let msg = format ! ( "trait `{}` is private" , trait_ref) ;
694
+ self . tcx . sess . span_err ( self . span , & msg) ;
695
+ return true ;
696
+ }
697
+
698
+ trait_ref. super_visit_with ( self )
699
+ }
691
700
}
692
701
693
702
impl < ' a , ' tcx > Visitor < ' tcx > for TypePrivacyVisitor < ' a , ' tcx > {
@@ -699,16 +708,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
699
708
700
709
fn visit_nested_body ( & mut self , body : hir:: BodyId ) {
701
710
let orig_tables = replace ( & mut self . tables , self . tcx . body_tables ( body) ) ;
711
+ let orig_in_body = replace ( & mut self . in_body , true ) ;
702
712
let body = self . tcx . hir . body ( body) ;
703
713
self . visit_body ( body) ;
704
714
self . tables = orig_tables;
715
+ self . in_body = orig_in_body;
705
716
}
706
717
707
718
fn visit_ty ( & mut self , hir_ty : & ' tcx hir:: Ty ) {
708
719
self . span = hir_ty. span ;
709
- if let Some ( ty ) = self . tables . node_id_to_type_opt ( hir_ty . hir_id ) {
720
+ if self . in_body {
710
721
// Types in bodies.
711
- if ty . visit_with ( self ) {
722
+ if self . tables . node_id_to_type ( hir_ty . hir_id ) . visit_with ( self ) {
712
723
return ;
713
724
}
714
725
} else {
@@ -724,10 +735,21 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
724
735
}
725
736
726
737
fn visit_trait_ref ( & mut self , trait_ref : & ' tcx hir:: TraitRef ) {
727
- if !self . item_is_accessible ( trait_ref. path . def . def_id ( ) ) {
728
- let msg = format ! ( "trait `{:?}` is private" , trait_ref. path) ;
729
- self . tcx . sess . span_err ( self . span , & msg) ;
730
- return ;
738
+ self . span = trait_ref. path . span ;
739
+ if !self . in_body {
740
+ // Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
741
+ // The traits' privacy in bodies is already checked as a part of trait object types.
742
+ let ( principal, projections) =
743
+ rustc_typeck:: hir_trait_to_predicates ( self . tcx , trait_ref) ;
744
+ if self . check_trait_ref ( * principal. skip_binder ( ) ) {
745
+ return ;
746
+ }
747
+ for poly_predicate in projections {
748
+ let tcx = self . tcx ;
749
+ if self . check_trait_ref ( poly_predicate. skip_binder ( ) . projection_ty . trait_ref ( tcx) ) {
750
+ return ;
751
+ }
752
+ }
731
753
}
732
754
733
755
intravisit:: walk_trait_ref ( self , trait_ref) ;
@@ -760,19 +782,29 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
760
782
intravisit:: walk_expr ( self , expr) ;
761
783
}
762
784
785
+ // Prohibit access to associated items with insufficient nominal visibility.
763
786
fn visit_qpath ( & mut self , qpath : & ' tcx hir:: QPath , id : ast:: NodeId , span : Span ) {
764
- // Inherent associated constants don't have self type in substs,
765
- // we have to check it additionally.
766
- if let hir:: QPath :: TypeRelative ( ..) = * qpath {
767
- let hir_id = self . tcx . hir . node_to_hir_id ( id) ;
768
- if let Some ( def) = self . tables . type_dependent_defs ( ) . get ( hir_id) . cloned ( ) {
769
- if let Some ( assoc_item) = self . tcx . opt_associated_item ( def. def_id ( ) ) {
770
- if let ty:: ImplContainer ( impl_def_id) = assoc_item. container {
771
- if self . tcx . type_of ( impl_def_id) . visit_with ( self ) {
772
- return ;
773
- }
774
- }
775
- }
787
+ let def = match * qpath {
788
+ hir:: QPath :: Resolved ( _, ref path) => match path. def {
789
+ Def :: Method ( ..) | Def :: AssociatedConst ( ..) |
790
+ Def :: AssociatedTy ( ..) => Some ( path. def ) ,
791
+ _ => None ,
792
+ }
793
+ hir:: QPath :: TypeRelative ( ..) => {
794
+ let hir_id = self . tcx . hir . node_to_hir_id ( id) ;
795
+ self . tables . type_dependent_defs ( ) . get ( hir_id) . cloned ( )
796
+ }
797
+ } ;
798
+ if let Some ( def) = def {
799
+ let def_id = def. def_id ( ) ;
800
+ if !self . item_is_accessible ( def_id) {
801
+ let name = match * qpath {
802
+ hir:: QPath :: Resolved ( _, ref path) => format ! ( "{}" , path) ,
803
+ hir:: QPath :: TypeRelative ( _, ref segment) => segment. name . to_string ( ) ,
804
+ } ;
805
+ let msg = format ! ( "{} `{}` is private" , def. kind_name( ) , name) ;
806
+ self . tcx . sess . span_err ( span, & msg) ;
807
+ return ;
776
808
}
777
809
}
778
810
@@ -807,9 +839,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
807
839
item. id ,
808
840
& mut self . tables ,
809
841
self . empty_tables ) ;
842
+ let orig_in_body = replace ( & mut self . in_body , false ) ;
810
843
self . current_item = self . tcx . hir . local_def_id ( item. id ) ;
811
844
intravisit:: walk_item ( self , item) ;
812
845
self . tables = orig_tables;
846
+ self . in_body = orig_in_body;
813
847
self . current_item = orig_current_item;
814
848
}
815
849
@@ -869,13 +903,8 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
869
903
}
870
904
}
871
905
ty:: TyProjection ( ref proj) => {
872
- let trait_ref = proj. trait_ref ( self . tcx ) ;
873
- if !self . item_is_accessible ( trait_ref. def_id ) {
874
- let msg = format ! ( "trait `{}` is private" , trait_ref) ;
875
- self . tcx . sess . span_err ( self . span , & msg) ;
876
- return true ;
877
- }
878
- if trait_ref. super_visit_with ( self ) {
906
+ let tcx = self . tcx ;
907
+ if self . check_trait_ref ( proj. trait_ref ( tcx) ) {
879
908
return true ;
880
909
}
881
910
}
@@ -1629,6 +1658,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1629
1658
tcx,
1630
1659
tables : & empty_tables,
1631
1660
current_item : DefId :: local ( CRATE_DEF_INDEX ) ,
1661
+ in_body : false ,
1632
1662
span : krate. span ,
1633
1663
empty_tables : & empty_tables,
1634
1664
} ;
0 commit comments