diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2020-06-25 22:23:41 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2020-07-02 16:49:41 +0300 |
| commit | 780d6cb1408717f968a21d627cc34c8ffa7f6fe8 (patch) | |
| tree | 7fb840e65368edb4e2ccc7856d786068b96a31e5 /src | |
| parent | 883ece499fef22b4703f5b04133bb2beff08c794 (diff) | |
| download | rust-780d6cb1408717f968a21d627cc34c8ffa7f6fe8.tar.gz rust-780d6cb1408717f968a21d627cc34c8ffa7f6fe8.zip | |
rustc_privacy: avoid using TypeckTables::empty for {Name,Type}PrivacyVisitor.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_privacy/lib.rs | 156 |
1 files changed, 58 insertions, 98 deletions
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 20f09ef52f0..de21365c536 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -2,6 +2,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(track_caller))] #![recursion_limit = "256"] use rustc_attr as attr; @@ -345,17 +346,6 @@ fn def_id_visibility<'tcx>( } } -// Set the correct `TypeckTables` for the given `item_id` (or an empty table if -// there is no `TypeckTables` for the item). -fn item_tables<'a, 'tcx>( - tcx: TyCtxt<'tcx>, - hir_id: hir::HirId, - empty_tables: &'a ty::TypeckTables<'tcx>, -) -> &'a ty::TypeckTables<'tcx> { - let def_id = tcx.hir().local_def_id(hir_id); - if tcx.has_typeck_tables(def_id) { tcx.typeck_tables_of(def_id) } else { empty_tables } -} - fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility { if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 } } @@ -1029,14 +1019,21 @@ impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { /// This pass performs remaining checks for fields in struct expressions and patterns. ////////////////////////////////////////////////////////////////////////////////////// -struct NamePrivacyVisitor<'a, 'tcx> { +struct NamePrivacyVisitor<'tcx> { tcx: TyCtxt<'tcx>, - tables: &'a ty::TypeckTables<'tcx>, + maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>, current_item: Option<hir::HirId>, - empty_tables: &'a ty::TypeckTables<'tcx>, } -impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { +impl<'tcx> NamePrivacyVisitor<'tcx> { + /// Gets the type-checking side-tables for the current body. + /// As this will ICE if called outside bodies, only call when working with + /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). + #[track_caller] + fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> { + self.maybe_typeck_tables.expect("`NamePrivacyVisitor::tables` called outside of body") + } + // Checks that a field in a struct constructor (expression or pattern) is accessible. fn check_field( &mut self, @@ -1072,7 +1069,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { type Map = Map<'tcx>; /// We want to visit items in the context of their containing @@ -1087,39 +1084,22 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body)); + let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.tcx.body_tables(body)); let body = self.tcx.hir().body(body); self.visit_body(body); - self.tables = orig_tables; + self.maybe_typeck_tables = old_maybe_typeck_tables; } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, Some(item.hir_id)); - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables)); + let orig_current_item = self.current_item.replace(item.hir_id); intravisit::walk_item(self, item); self.current_item = orig_current_item; - self.tables = orig_tables; - } - - fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) { - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables)); - intravisit::walk_trait_item(self, ti); - self.tables = orig_tables; - } - - fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables)); - intravisit::walk_impl_item(self, ii); - self.tables = orig_tables; } fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { if let hir::ExprKind::Struct(ref qpath, fields, ref base) = expr.kind { - let res = self.tables.qpath_res(qpath, expr.hir_id); - let adt = self.tables.expr_ty(expr).ty_adt_def().unwrap(); + let res = self.tables().qpath_res(qpath, expr.hir_id); + let adt = self.tables().expr_ty(expr).ty_adt_def().unwrap(); let variant = adt.variant_of_res(res); if let Some(ref base) = *base { // 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> { for (vf_index, variant_field) in variant.fields.iter().enumerate() { let field = fields .iter() - .find(|f| self.tcx.field_index(f.hir_id, self.tables) == vf_index); + .find(|f| self.tcx.field_index(f.hir_id, self.tables()) == vf_index); let (use_ctxt, span) = match field { Some(field) => (field.ident.span, field.span), None => (base.span, base.span), @@ -1138,7 +1118,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { } else { for field in fields { let use_ctxt = field.ident.span; - let index = self.tcx.field_index(field.hir_id, self.tables); + let index = self.tcx.field_index(field.hir_id, self.tables()); self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false); } } @@ -1149,12 +1129,12 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) { if let PatKind::Struct(ref qpath, fields, _) = pat.kind { - let res = self.tables.qpath_res(qpath, pat.hir_id); - let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap(); + let res = self.tables().qpath_res(qpath, pat.hir_id); + let adt = self.tables().pat_ty(pat).ty_adt_def().unwrap(); let variant = adt.variant_of_res(res); for field in fields { let use_ctxt = field.ident.span; - let index = self.tcx.field_index(field.hir_id, self.tables); + let index = self.tcx.field_index(field.hir_id, self.tables()); self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false); } } @@ -1169,16 +1149,22 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { /// Checks are performed on "semantic" types regardless of names and their hygiene. //////////////////////////////////////////////////////////////////////////////////////////// -struct TypePrivacyVisitor<'a, 'tcx> { +struct TypePrivacyVisitor<'tcx> { tcx: TyCtxt<'tcx>, - tables: &'a ty::TypeckTables<'tcx>, + maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>, current_item: LocalDefId, - in_body: bool, span: Span, - empty_tables: &'a ty::TypeckTables<'tcx>, } -impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { +impl<'tcx> TypePrivacyVisitor<'tcx> { + /// Gets the type-checking side-tables for the current body. + /// As this will ICE if called outside bodies, only call when working with + /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). + #[track_caller] + fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> { + self.maybe_typeck_tables.expect("`TypePrivacyVisitor::tables` called outside of body") + } + fn item_is_accessible(&self, did: DefId) -> bool { def_id_visibility(self.tcx, did) .0 @@ -1188,10 +1174,11 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { // Take node-id of an expression or pattern and check its type for privacy. fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool { self.span = span; - if self.visit(self.tables.node_type(id)) || self.visit(self.tables.node_substs(id)) { + let tables = self.tables(); + if self.visit(tables.node_type(id)) || self.visit(tables.node_substs(id)) { return true; } - if let Some(adjustments) = self.tables.adjustments().get(id) { + if let Some(adjustments) = tables.adjustments().get(id) { for adjustment in adjustments { if self.visit(adjustment.target) { return true; @@ -1214,7 +1201,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { type Map = Map<'tcx>; /// We want to visit items in the context of their containing @@ -1229,19 +1216,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body)); - let orig_in_body = mem::replace(&mut self.in_body, true); + let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.tcx.body_tables(body)); let body = self.tcx.hir().body(body); self.visit_body(body); - self.tables = orig_tables; - self.in_body = orig_in_body; + self.maybe_typeck_tables = old_maybe_typeck_tables; } fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) { self.span = hir_ty.span; - if self.in_body { + if let Some(tables) = self.maybe_typeck_tables { // Types in bodies. - if self.visit(self.tables.node_type(hir_ty.hir_id)) { + if self.visit(tables.node_type(hir_ty.hir_id)) { return; } } else { @@ -1258,7 +1243,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) { self.span = trait_ref.path.span; - if !self.in_body { + if self.maybe_typeck_tables.is_none() { // Avoid calling `hir_trait_to_predicates` in bodies, it will ICE. // The traits' privacy in bodies is already checked as a part of trait object types. let bounds = rustc_typeck::hir_trait_to_predicates( @@ -1304,7 +1289,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { hir::ExprKind::MethodCall(_, span, _, _) => { // Method calls have to be checked specially. self.span = span; - if let Some(def_id) = self.tables.type_dependent_def_id(expr.hir_id) { + if let Some(def_id) = self.tables().type_dependent_def_id(expr.hir_id) { if self.visit(self.tcx.type_of(def_id)) { return; } @@ -1327,9 +1312,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // more code internal visibility at link time. (Access to private functions // is already prohibited by type privacy for function types.) fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: Span) { - let def = match self.tables.qpath_res(qpath, id) { - Res::Def(kind, def_id) => Some((kind, def_id)), - _ => None, + let def = match qpath { + hir::QPath::Resolved(_, path) => match path.res { + Res::Def(kind, def_id) => Some((kind, def_id)), + _ => None, + }, + hir::QPath::TypeRelative(..) => { + self.maybe_typeck_tables.and_then(|tables| tables.type_dependent_def(id)) + } }; let def = def.filter(|(kind, _)| match kind { DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static => true, @@ -1385,31 +1375,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { let orig_current_item = mem::replace(&mut self.current_item, self.tcx.hir().local_def_id(item.hir_id)); - let orig_in_body = mem::replace(&mut self.in_body, false); - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables)); + let old_maybe_typeck_tables = self.maybe_typeck_tables.take(); intravisit::walk_item(self, item); - self.tables = orig_tables; - self.in_body = orig_in_body; + self.maybe_typeck_tables = old_maybe_typeck_tables; self.current_item = orig_current_item; } - - fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) { - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables)); - intravisit::walk_trait_item(self, ti); - self.tables = orig_tables; - } - - fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables)); - intravisit::walk_impl_item(self, ii); - self.tables = orig_tables; - } } -impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { +impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -2066,29 +2039,16 @@ pub fn provide(providers: &mut Providers<'_>) { } fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { - let empty_tables = ty::TypeckTables::empty(None); - // Check privacy of names not checked in previous compilation stages. - let mut visitor = NamePrivacyVisitor { - tcx, - tables: &empty_tables, - current_item: None, - empty_tables: &empty_tables, - }; + let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_tables: None, current_item: None }; let (module, span, hir_id) = tcx.hir().get_module(module_def_id); intravisit::walk_mod(&mut visitor, module, hir_id); // Check privacy of explicitly written types and traits as well as // inferred types of expressions and patterns. - let mut visitor = TypePrivacyVisitor { - tcx, - tables: &empty_tables, - current_item: module_def_id, - in_body: false, - span, - empty_tables: &empty_tables, - }; + let mut visitor = + TypePrivacyVisitor { tcx, maybe_typeck_tables: None, current_item: module_def_id, span }; intravisit::walk_mod(&mut visitor, module, hir_id); } |
