22#![ feature( in_band_lifetimes) ]
33#![ feature( nll) ]
44#![ feature( or_patterns) ]
5+ #![ cfg_attr( bootstrap, feature( track_caller) ) ]
56#![ recursion_limit = "256" ]
67
78use rustc_attr as attr;
@@ -345,17 +346,6 @@ fn def_id_visibility<'tcx>(
345346 }
346347}
347348
348- // Set the correct `TypeckTables` for the given `item_id` (or an empty table if
349- // there is no `TypeckTables` for the item).
350- fn item_tables < ' a , ' tcx > (
351- tcx : TyCtxt < ' tcx > ,
352- hir_id : hir:: HirId ,
353- empty_tables : & ' a ty:: TypeckTables < ' tcx > ,
354- ) -> & ' a ty:: TypeckTables < ' tcx > {
355- let def_id = tcx. hir ( ) . local_def_id ( hir_id) ;
356- if tcx. has_typeck_tables ( def_id) { tcx. typeck_tables_of ( def_id) } else { empty_tables }
357- }
358-
359349fn min ( vis1 : ty:: Visibility , vis2 : ty:: Visibility , tcx : TyCtxt < ' _ > ) -> ty:: Visibility {
360350 if vis1. is_at_least ( vis2, tcx) { vis2 } else { vis1 }
361351}
@@ -1029,14 +1019,21 @@ impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
10291019/// This pass performs remaining checks for fields in struct expressions and patterns.
10301020//////////////////////////////////////////////////////////////////////////////////////
10311021
1032- struct NamePrivacyVisitor < ' a , ' tcx > {
1022+ struct NamePrivacyVisitor < ' tcx > {
10331023 tcx : TyCtxt < ' tcx > ,
1034- tables : & ' a ty:: TypeckTables < ' tcx > ,
1024+ maybe_typeck_tables : Option < & ' tcx ty:: TypeckTables < ' tcx > > ,
10351025 current_item : Option < hir:: HirId > ,
1036- empty_tables : & ' a ty:: TypeckTables < ' tcx > ,
10371026}
10381027
1039- impl < ' a , ' tcx > NamePrivacyVisitor < ' a , ' tcx > {
1028+ impl < ' tcx > NamePrivacyVisitor < ' tcx > {
1029+ /// Gets the type-checking side-tables for the current body.
1030+ /// As this will ICE if called outside bodies, only call when working with
1031+ /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
1032+ #[ track_caller]
1033+ fn tables ( & self ) -> & ' tcx ty:: TypeckTables < ' tcx > {
1034+ self . maybe_typeck_tables . expect ( "`NamePrivacyVisitor::tables` called outside of body" )
1035+ }
1036+
10401037 // Checks that a field in a struct constructor (expression or pattern) is accessible.
10411038 fn check_field (
10421039 & mut self ,
@@ -1072,7 +1069,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
10721069 }
10731070}
10741071
1075- impl < ' a , ' tcx > Visitor < ' tcx > for NamePrivacyVisitor < ' a , ' tcx > {
1072+ impl < ' tcx > Visitor < ' tcx > for NamePrivacyVisitor < ' tcx > {
10761073 type Map = Map < ' tcx > ;
10771074
10781075 /// We want to visit items in the context of their containing
@@ -1087,39 +1084,22 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
10871084 }
10881085
10891086 fn visit_nested_body ( & mut self , body : hir:: BodyId ) {
1090- let orig_tables = mem :: replace ( & mut self . tables , self . tcx . body_tables ( body) ) ;
1087+ let old_maybe_typeck_tables = self . maybe_typeck_tables . replace ( self . tcx . body_tables ( body) ) ;
10911088 let body = self . tcx . hir ( ) . body ( body) ;
10921089 self . visit_body ( body) ;
1093- self . tables = orig_tables ;
1090+ self . maybe_typeck_tables = old_maybe_typeck_tables ;
10941091 }
10951092
10961093 fn visit_item ( & mut self , item : & ' tcx hir:: Item < ' tcx > ) {
1097- let orig_current_item = mem:: replace ( & mut self . current_item , Some ( item. hir_id ) ) ;
1098- let orig_tables =
1099- mem:: replace ( & mut self . tables , item_tables ( self . tcx , item. hir_id , self . empty_tables ) ) ;
1094+ let orig_current_item = self . current_item . replace ( item. hir_id ) ;
11001095 intravisit:: walk_item ( self , item) ;
11011096 self . current_item = orig_current_item;
1102- self . tables = orig_tables;
1103- }
1104-
1105- fn visit_trait_item ( & mut self , ti : & ' tcx hir:: TraitItem < ' tcx > ) {
1106- let orig_tables =
1107- mem:: replace ( & mut self . tables , item_tables ( self . tcx , ti. hir_id , self . empty_tables ) ) ;
1108- intravisit:: walk_trait_item ( self , ti) ;
1109- self . tables = orig_tables;
1110- }
1111-
1112- fn visit_impl_item ( & mut self , ii : & ' tcx hir:: ImplItem < ' tcx > ) {
1113- let orig_tables =
1114- mem:: replace ( & mut self . tables , item_tables ( self . tcx , ii. hir_id , self . empty_tables ) ) ;
1115- intravisit:: walk_impl_item ( self , ii) ;
1116- self . tables = orig_tables;
11171097 }
11181098
11191099 fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) {
11201100 if let hir:: ExprKind :: Struct ( ref qpath, fields, ref base) = expr. kind {
1121- let res = self . tables . qpath_res ( qpath, expr. hir_id ) ;
1122- let adt = self . tables . expr_ty ( expr) . ty_adt_def ( ) . unwrap ( ) ;
1101+ let res = self . tables ( ) . qpath_res ( qpath, expr. hir_id ) ;
1102+ let adt = self . tables ( ) . expr_ty ( expr) . ty_adt_def ( ) . unwrap ( ) ;
11231103 let variant = adt. variant_of_res ( res) ;
11241104 if let Some ( ref base) = * base {
11251105 // If the expression uses FRU we need to make sure all the unmentioned fields
@@ -1128,7 +1108,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
11281108 for ( vf_index, variant_field) in variant. fields . iter ( ) . enumerate ( ) {
11291109 let field = fields
11301110 . iter ( )
1131- . find ( |f| self . tcx . field_index ( f. hir_id , self . tables ) == vf_index) ;
1111+ . find ( |f| self . tcx . field_index ( f. hir_id , self . tables ( ) ) == vf_index) ;
11321112 let ( use_ctxt, span) = match field {
11331113 Some ( field) => ( field. ident . span , field. span ) ,
11341114 None => ( base. span , base. span ) ,
@@ -1138,7 +1118,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
11381118 } else {
11391119 for field in fields {
11401120 let use_ctxt = field. ident . span ;
1141- let index = self . tcx . field_index ( field. hir_id , self . tables ) ;
1121+ let index = self . tcx . field_index ( field. hir_id , self . tables ( ) ) ;
11421122 self . check_field ( use_ctxt, field. span , adt, & variant. fields [ index] , false ) ;
11431123 }
11441124 }
@@ -1149,12 +1129,12 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
11491129
11501130 fn visit_pat ( & mut self , pat : & ' tcx hir:: Pat < ' tcx > ) {
11511131 if let PatKind :: Struct ( ref qpath, fields, _) = pat. kind {
1152- let res = self . tables . qpath_res ( qpath, pat. hir_id ) ;
1153- let adt = self . tables . pat_ty ( pat) . ty_adt_def ( ) . unwrap ( ) ;
1132+ let res = self . tables ( ) . qpath_res ( qpath, pat. hir_id ) ;
1133+ let adt = self . tables ( ) . pat_ty ( pat) . ty_adt_def ( ) . unwrap ( ) ;
11541134 let variant = adt. variant_of_res ( res) ;
11551135 for field in fields {
11561136 let use_ctxt = field. ident . span ;
1157- let index = self . tcx . field_index ( field. hir_id , self . tables ) ;
1137+ let index = self . tcx . field_index ( field. hir_id , self . tables ( ) ) ;
11581138 self . check_field ( use_ctxt, field. span , adt, & variant. fields [ index] , false ) ;
11591139 }
11601140 }
@@ -1169,16 +1149,22 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
11691149/// Checks are performed on "semantic" types regardless of names and their hygiene.
11701150////////////////////////////////////////////////////////////////////////////////////////////
11711151
1172- struct TypePrivacyVisitor < ' a , ' tcx > {
1152+ struct TypePrivacyVisitor < ' tcx > {
11731153 tcx : TyCtxt < ' tcx > ,
1174- tables : & ' a ty:: TypeckTables < ' tcx > ,
1154+ maybe_typeck_tables : Option < & ' tcx ty:: TypeckTables < ' tcx > > ,
11751155 current_item : LocalDefId ,
1176- in_body : bool ,
11771156 span : Span ,
1178- empty_tables : & ' a ty:: TypeckTables < ' tcx > ,
11791157}
11801158
1181- impl < ' a , ' tcx > TypePrivacyVisitor < ' a , ' tcx > {
1159+ impl < ' tcx > TypePrivacyVisitor < ' tcx > {
1160+ /// Gets the type-checking side-tables for the current body.
1161+ /// As this will ICE if called outside bodies, only call when working with
1162+ /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
1163+ #[ track_caller]
1164+ fn tables ( & self ) -> & ' tcx ty:: TypeckTables < ' tcx > {
1165+ self . maybe_typeck_tables . expect ( "`TypePrivacyVisitor::tables` called outside of body" )
1166+ }
1167+
11821168 fn item_is_accessible ( & self , did : DefId ) -> bool {
11831169 def_id_visibility ( self . tcx , did)
11841170 . 0
@@ -1188,10 +1174,11 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
11881174 // Take node-id of an expression or pattern and check its type for privacy.
11891175 fn check_expr_pat_type ( & mut self , id : hir:: HirId , span : Span ) -> bool {
11901176 self . span = span;
1191- if self . visit ( self . tables . node_type ( id) ) || self . visit ( self . tables . node_substs ( id) ) {
1177+ let tables = self . tables ( ) ;
1178+ if self . visit ( tables. node_type ( id) ) || self . visit ( tables. node_substs ( id) ) {
11921179 return true ;
11931180 }
1194- if let Some ( adjustments) = self . tables . adjustments ( ) . get ( id) {
1181+ if let Some ( adjustments) = tables. adjustments ( ) . get ( id) {
11951182 for adjustment in adjustments {
11961183 if self . visit ( adjustment. target ) {
11971184 return true ;
@@ -1214,7 +1201,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
12141201 }
12151202}
12161203
1217- impl < ' a , ' tcx > Visitor < ' tcx > for TypePrivacyVisitor < ' a , ' tcx > {
1204+ impl < ' tcx > Visitor < ' tcx > for TypePrivacyVisitor < ' tcx > {
12181205 type Map = Map < ' tcx > ;
12191206
12201207 /// We want to visit items in the context of their containing
@@ -1229,19 +1216,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
12291216 }
12301217
12311218 fn visit_nested_body ( & mut self , body : hir:: BodyId ) {
1232- let orig_tables = mem:: replace ( & mut self . tables , self . tcx . body_tables ( body) ) ;
1233- let orig_in_body = mem:: replace ( & mut self . in_body , true ) ;
1219+ let old_maybe_typeck_tables = self . maybe_typeck_tables . replace ( self . tcx . body_tables ( body) ) ;
12341220 let body = self . tcx . hir ( ) . body ( body) ;
12351221 self . visit_body ( body) ;
1236- self . tables = orig_tables;
1237- self . in_body = orig_in_body;
1222+ self . maybe_typeck_tables = old_maybe_typeck_tables;
12381223 }
12391224
12401225 fn visit_ty ( & mut self , hir_ty : & ' tcx hir:: Ty < ' tcx > ) {
12411226 self . span = hir_ty. span ;
1242- if self . in_body {
1227+ if let Some ( tables ) = self . maybe_typeck_tables {
12431228 // Types in bodies.
1244- if self . visit ( self . tables . node_type ( hir_ty. hir_id ) ) {
1229+ if self . visit ( tables. node_type ( hir_ty. hir_id ) ) {
12451230 return ;
12461231 }
12471232 } else {
@@ -1258,7 +1243,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
12581243
12591244 fn visit_trait_ref ( & mut self , trait_ref : & ' tcx hir:: TraitRef < ' tcx > ) {
12601245 self . span = trait_ref. path . span ;
1261- if ! self . in_body {
1246+ if self . maybe_typeck_tables . is_none ( ) {
12621247 // Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
12631248 // The traits' privacy in bodies is already checked as a part of trait object types.
12641249 let bounds = rustc_typeck:: hir_trait_to_predicates (
@@ -1304,7 +1289,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
13041289 hir:: ExprKind :: MethodCall ( _, span, _, _) => {
13051290 // Method calls have to be checked specially.
13061291 self . span = span;
1307- if let Some ( def_id) = self . tables . type_dependent_def_id ( expr. hir_id ) {
1292+ if let Some ( def_id) = self . tables ( ) . type_dependent_def_id ( expr. hir_id ) {
13081293 if self . visit ( self . tcx . type_of ( def_id) ) {
13091294 return ;
13101295 }
@@ -1327,9 +1312,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
13271312 // more code internal visibility at link time. (Access to private functions
13281313 // is already prohibited by type privacy for function types.)
13291314 fn visit_qpath ( & mut self , qpath : & ' tcx hir:: QPath < ' tcx > , id : hir:: HirId , span : Span ) {
1330- let def = match self . tables . qpath_res ( qpath, id) {
1331- Res :: Def ( kind, def_id) => Some ( ( kind, def_id) ) ,
1332- _ => None ,
1315+ let def = match qpath {
1316+ hir:: QPath :: Resolved ( _, path) => match path. res {
1317+ Res :: Def ( kind, def_id) => Some ( ( kind, def_id) ) ,
1318+ _ => None ,
1319+ } ,
1320+ hir:: QPath :: TypeRelative ( ..) => {
1321+ self . maybe_typeck_tables . and_then ( |tables| tables. type_dependent_def ( id) )
1322+ }
13331323 } ;
13341324 let def = def. filter ( |( kind, _) | match kind {
13351325 DefKind :: AssocFn | DefKind :: AssocConst | DefKind :: AssocTy | DefKind :: Static => true ,
@@ -1385,31 +1375,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
13851375 fn visit_item ( & mut self , item : & ' tcx hir:: Item < ' tcx > ) {
13861376 let orig_current_item =
13871377 mem:: replace ( & mut self . current_item , self . tcx . hir ( ) . local_def_id ( item. hir_id ) ) ;
1388- let orig_in_body = mem:: replace ( & mut self . in_body , false ) ;
1389- let orig_tables =
1390- mem:: replace ( & mut self . tables , item_tables ( self . tcx , item. hir_id , self . empty_tables ) ) ;
1378+ let old_maybe_typeck_tables = self . maybe_typeck_tables . take ( ) ;
13911379 intravisit:: walk_item ( self , item) ;
1392- self . tables = orig_tables;
1393- self . in_body = orig_in_body;
1380+ self . maybe_typeck_tables = old_maybe_typeck_tables;
13941381 self . current_item = orig_current_item;
13951382 }
1396-
1397- fn visit_trait_item ( & mut self , ti : & ' tcx hir:: TraitItem < ' tcx > ) {
1398- let orig_tables =
1399- mem:: replace ( & mut self . tables , item_tables ( self . tcx , ti. hir_id , self . empty_tables ) ) ;
1400- intravisit:: walk_trait_item ( self , ti) ;
1401- self . tables = orig_tables;
1402- }
1403-
1404- fn visit_impl_item ( & mut self , ii : & ' tcx hir:: ImplItem < ' tcx > ) {
1405- let orig_tables =
1406- mem:: replace ( & mut self . tables , item_tables ( self . tcx , ii. hir_id , self . empty_tables ) ) ;
1407- intravisit:: walk_impl_item ( self , ii) ;
1408- self . tables = orig_tables;
1409- }
14101383}
14111384
1412- impl DefIdVisitor < ' tcx > for TypePrivacyVisitor < ' a , ' tcx > {
1385+ impl DefIdVisitor < ' tcx > for TypePrivacyVisitor < ' tcx > {
14131386 fn tcx ( & self ) -> TyCtxt < ' tcx > {
14141387 self . tcx
14151388 }
@@ -2066,29 +2039,16 @@ pub fn provide(providers: &mut Providers<'_>) {
20662039}
20672040
20682041fn check_mod_privacy ( tcx : TyCtxt < ' _ > , module_def_id : LocalDefId ) {
2069- let empty_tables = ty:: TypeckTables :: empty ( None ) ;
2070-
20712042 // Check privacy of names not checked in previous compilation stages.
2072- let mut visitor = NamePrivacyVisitor {
2073- tcx,
2074- tables : & empty_tables,
2075- current_item : None ,
2076- empty_tables : & empty_tables,
2077- } ;
2043+ let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_tables : None , current_item : None } ;
20782044 let ( module, span, hir_id) = tcx. hir ( ) . get_module ( module_def_id) ;
20792045
20802046 intravisit:: walk_mod ( & mut visitor, module, hir_id) ;
20812047
20822048 // Check privacy of explicitly written types and traits as well as
20832049 // inferred types of expressions and patterns.
2084- let mut visitor = TypePrivacyVisitor {
2085- tcx,
2086- tables : & empty_tables,
2087- current_item : module_def_id,
2088- in_body : false ,
2089- span,
2090- empty_tables : & empty_tables,
2091- } ;
2050+ let mut visitor =
2051+ TypePrivacyVisitor { tcx, maybe_typeck_tables : None , current_item : module_def_id, span } ;
20922052 intravisit:: walk_mod ( & mut visitor, module, hir_id) ;
20932053}
20942054
0 commit comments