2
2
#![ feature( in_band_lifetimes) ]
3
3
#![ feature( nll) ]
4
4
#![ feature( or_patterns) ]
5
+ #![ cfg_attr( bootstrap, feature( track_caller) ) ]
5
6
#![ recursion_limit = "256" ]
6
7
7
8
use rustc_attr as attr;
@@ -345,17 +346,6 @@ fn def_id_visibility<'tcx>(
345
346
}
346
347
}
347
348
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
-
359
349
fn min ( vis1 : ty:: Visibility , vis2 : ty:: Visibility , tcx : TyCtxt < ' _ > ) -> ty:: Visibility {
360
350
if vis1. is_at_least ( vis2, tcx) { vis2 } else { vis1 }
361
351
}
@@ -1029,14 +1019,21 @@ impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
1029
1019
/// This pass performs remaining checks for fields in struct expressions and patterns.
1030
1020
//////////////////////////////////////////////////////////////////////////////////////
1031
1021
1032
- struct NamePrivacyVisitor < ' a , ' tcx > {
1022
+ struct NamePrivacyVisitor < ' tcx > {
1033
1023
tcx : TyCtxt < ' tcx > ,
1034
- tables : & ' a ty:: TypeckTables < ' tcx > ,
1024
+ maybe_typeck_tables : Option < & ' tcx ty:: TypeckTables < ' tcx > > ,
1035
1025
current_item : Option < hir:: HirId > ,
1036
- empty_tables : & ' a ty:: TypeckTables < ' tcx > ,
1037
1026
}
1038
1027
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
+
1040
1037
// Checks that a field in a struct constructor (expression or pattern) is accessible.
1041
1038
fn check_field (
1042
1039
& mut self ,
@@ -1072,7 +1069,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
1072
1069
}
1073
1070
}
1074
1071
1075
- impl < ' a , ' tcx > Visitor < ' tcx > for NamePrivacyVisitor < ' a , ' tcx > {
1072
+ impl < ' tcx > Visitor < ' tcx > for NamePrivacyVisitor < ' tcx > {
1076
1073
type Map = Map < ' tcx > ;
1077
1074
1078
1075
/// We want to visit items in the context of their containing
@@ -1087,39 +1084,22 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
1087
1084
}
1088
1085
1089
1086
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) ) ;
1091
1088
let body = self . tcx . hir ( ) . body ( body) ;
1092
1089
self . visit_body ( body) ;
1093
- self . tables = orig_tables ;
1090
+ self . maybe_typeck_tables = old_maybe_typeck_tables ;
1094
1091
}
1095
1092
1096
1093
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 ) ;
1100
1095
intravisit:: walk_item ( self , item) ;
1101
1096
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;
1117
1097
}
1118
1098
1119
1099
fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) {
1120
1100
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 ( ) ;
1123
1103
let variant = adt. variant_of_res ( res) ;
1124
1104
if let Some ( ref base) = * base {
1125
1105
// 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> {
1128
1108
for ( vf_index, variant_field) in variant. fields . iter ( ) . enumerate ( ) {
1129
1109
let field = fields
1130
1110
. 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) ;
1132
1112
let ( use_ctxt, span) = match field {
1133
1113
Some ( field) => ( field. ident . span , field. span ) ,
1134
1114
None => ( base. span , base. span ) ,
@@ -1138,7 +1118,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
1138
1118
} else {
1139
1119
for field in fields {
1140
1120
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 ( ) ) ;
1142
1122
self . check_field ( use_ctxt, field. span , adt, & variant. fields [ index] , false ) ;
1143
1123
}
1144
1124
}
@@ -1149,12 +1129,12 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
1149
1129
1150
1130
fn visit_pat ( & mut self , pat : & ' tcx hir:: Pat < ' tcx > ) {
1151
1131
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 ( ) ;
1154
1134
let variant = adt. variant_of_res ( res) ;
1155
1135
for field in fields {
1156
1136
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 ( ) ) ;
1158
1138
self . check_field ( use_ctxt, field. span , adt, & variant. fields [ index] , false ) ;
1159
1139
}
1160
1140
}
@@ -1169,16 +1149,22 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
1169
1149
/// Checks are performed on "semantic" types regardless of names and their hygiene.
1170
1150
////////////////////////////////////////////////////////////////////////////////////////////
1171
1151
1172
- struct TypePrivacyVisitor < ' a , ' tcx > {
1152
+ struct TypePrivacyVisitor < ' tcx > {
1173
1153
tcx : TyCtxt < ' tcx > ,
1174
- tables : & ' a ty:: TypeckTables < ' tcx > ,
1154
+ maybe_typeck_tables : Option < & ' tcx ty:: TypeckTables < ' tcx > > ,
1175
1155
current_item : LocalDefId ,
1176
- in_body : bool ,
1177
1156
span : Span ,
1178
- empty_tables : & ' a ty:: TypeckTables < ' tcx > ,
1179
1157
}
1180
1158
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
+
1182
1168
fn item_is_accessible ( & self , did : DefId ) -> bool {
1183
1169
def_id_visibility ( self . tcx , did)
1184
1170
. 0
@@ -1188,10 +1174,11 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
1188
1174
// Take node-id of an expression or pattern and check its type for privacy.
1189
1175
fn check_expr_pat_type ( & mut self , id : hir:: HirId , span : Span ) -> bool {
1190
1176
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) ) {
1192
1179
return true ;
1193
1180
}
1194
- if let Some ( adjustments) = self . tables . adjustments ( ) . get ( id) {
1181
+ if let Some ( adjustments) = tables. adjustments ( ) . get ( id) {
1195
1182
for adjustment in adjustments {
1196
1183
if self . visit ( adjustment. target ) {
1197
1184
return true ;
@@ -1214,7 +1201,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
1214
1201
}
1215
1202
}
1216
1203
1217
- impl < ' a , ' tcx > Visitor < ' tcx > for TypePrivacyVisitor < ' a , ' tcx > {
1204
+ impl < ' tcx > Visitor < ' tcx > for TypePrivacyVisitor < ' tcx > {
1218
1205
type Map = Map < ' tcx > ;
1219
1206
1220
1207
/// We want to visit items in the context of their containing
@@ -1229,19 +1216,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
1229
1216
}
1230
1217
1231
1218
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) ) ;
1234
1220
let body = self . tcx . hir ( ) . body ( body) ;
1235
1221
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;
1238
1223
}
1239
1224
1240
1225
fn visit_ty ( & mut self , hir_ty : & ' tcx hir:: Ty < ' tcx > ) {
1241
1226
self . span = hir_ty. span ;
1242
- if self . in_body {
1227
+ if let Some ( tables ) = self . maybe_typeck_tables {
1243
1228
// 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 ) ) {
1245
1230
return ;
1246
1231
}
1247
1232
} else {
@@ -1258,7 +1243,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
1258
1243
1259
1244
fn visit_trait_ref ( & mut self , trait_ref : & ' tcx hir:: TraitRef < ' tcx > ) {
1260
1245
self . span = trait_ref. path . span ;
1261
- if ! self . in_body {
1246
+ if self . maybe_typeck_tables . is_none ( ) {
1262
1247
// Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
1263
1248
// The traits' privacy in bodies is already checked as a part of trait object types.
1264
1249
let bounds = rustc_typeck:: hir_trait_to_predicates (
@@ -1304,7 +1289,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
1304
1289
hir:: ExprKind :: MethodCall ( _, span, _, _) => {
1305
1290
// Method calls have to be checked specially.
1306
1291
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 ) {
1308
1293
if self . visit ( self . tcx . type_of ( def_id) ) {
1309
1294
return ;
1310
1295
}
@@ -1327,9 +1312,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
1327
1312
// more code internal visibility at link time. (Access to private functions
1328
1313
// is already prohibited by type privacy for function types.)
1329
1314
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
+ }
1333
1323
} ;
1334
1324
let def = def. filter ( |( kind, _) | match kind {
1335
1325
DefKind :: AssocFn | DefKind :: AssocConst | DefKind :: AssocTy | DefKind :: Static => true ,
@@ -1385,31 +1375,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
1385
1375
fn visit_item ( & mut self , item : & ' tcx hir:: Item < ' tcx > ) {
1386
1376
let orig_current_item =
1387
1377
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 ( ) ;
1391
1379
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;
1394
1381
self . current_item = orig_current_item;
1395
1382
}
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
- }
1410
1383
}
1411
1384
1412
- impl DefIdVisitor < ' tcx > for TypePrivacyVisitor < ' a , ' tcx > {
1385
+ impl DefIdVisitor < ' tcx > for TypePrivacyVisitor < ' tcx > {
1413
1386
fn tcx ( & self ) -> TyCtxt < ' tcx > {
1414
1387
self . tcx
1415
1388
}
@@ -2066,29 +2039,16 @@ pub fn provide(providers: &mut Providers<'_>) {
2066
2039
}
2067
2040
2068
2041
fn check_mod_privacy ( tcx : TyCtxt < ' _ > , module_def_id : LocalDefId ) {
2069
- let empty_tables = ty:: TypeckTables :: empty ( None ) ;
2070
-
2071
2042
// 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 } ;
2078
2044
let ( module, span, hir_id) = tcx. hir ( ) . get_module ( module_def_id) ;
2079
2045
2080
2046
intravisit:: walk_mod ( & mut visitor, module, hir_id) ;
2081
2047
2082
2048
// Check privacy of explicitly written types and traits as well as
2083
2049
// 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 } ;
2092
2052
intravisit:: walk_mod ( & mut visitor, module, hir_id) ;
2093
2053
}
2094
2054
0 commit comments