Skip to content

Commit fee8f00

Browse files
authored
Rollup merge of #120284 - petrochenkov:typrivisit2, r=oli-obk
privacy: Refactor top-level visiting in `TypePrivacyVisitor` Full hierarchical visiting (`nested_filter::All`) is not necessary, visiting all item-likes in isolation is enough. Tracking current item is not necessary, just keeping the current `mod` item is enough. `visit_generic_arg` should behave like its default version, including checking types of const arguments. Some comments, including FIXMEs, are also added. Noticed while reading code to review #113671. r? ``@oli-obk``
2 parents 8290589 + ba75970 commit fee8f00

File tree

3 files changed

+43
-66
lines changed

3 files changed

+43
-66
lines changed

compiler/rustc_privacy/src/lib.rs

+27-63
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ use rustc_hir::def::{DefKind, Res};
2424
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID};
2525
use rustc_hir::intravisit::{self, Visitor};
2626
use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, PatKind};
27-
use rustc_middle::bug;
2827
use rustc_middle::hir::nested_filter;
2928
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
3029
use rustc_middle::query::Providers;
3130
use rustc_middle::ty::GenericArgs;
3231
use rustc_middle::ty::{self, Const, GenericParamDefKind};
3332
use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
33+
use rustc_middle::{bug, span_bug};
3434
use rustc_session::lint;
3535
use rustc_span::hygiene::Transparency;
3636
use rustc_span::symbol::{kw, sym, Ident};
@@ -1064,29 +1064,22 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
10641064

10651065
struct TypePrivacyVisitor<'tcx> {
10661066
tcx: TyCtxt<'tcx>,
1067+
module_def_id: LocalModDefId,
10671068
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
1068-
current_item: LocalDefId,
10691069
span: Span,
10701070
}
10711071

10721072
impl<'tcx> TypePrivacyVisitor<'tcx> {
1073-
/// Gets the type-checking results for the current body.
1074-
/// As this will ICE if called outside bodies, only call when working with
1075-
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
1076-
#[track_caller]
1077-
fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
1078-
self.maybe_typeck_results
1079-
.expect("`TypePrivacyVisitor::typeck_results` called outside of body")
1080-
}
1081-
10821073
fn item_is_accessible(&self, did: DefId) -> bool {
1083-
self.tcx.visibility(did).is_accessible_from(self.current_item, self.tcx)
1074+
self.tcx.visibility(did).is_accessible_from(self.module_def_id, self.tcx)
10841075
}
10851076

10861077
// Take node-id of an expression or pattern and check its type for privacy.
10871078
fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
10881079
self.span = span;
1089-
let typeck_results = self.typeck_results();
1080+
let typeck_results = self
1081+
.maybe_typeck_results
1082+
.unwrap_or_else(|| span_bug!(span, "`hir::Expr` or `hir::Pat` outside of a body"));
10901083
let result: ControlFlow<()> = try {
10911084
self.visit(typeck_results.node_type(id))?;
10921085
self.visit(typeck_results.node_args(id))?;
@@ -1107,35 +1100,13 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
11071100
}
11081101

11091102
impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
1110-
type NestedFilter = nested_filter::All;
1111-
1112-
/// We want to visit items in the context of their containing
1113-
/// module and so forth, so supply a crate for doing a deep walk.
1114-
fn nested_visit_map(&mut self) -> Self::Map {
1115-
self.tcx.hir()
1116-
}
1117-
1118-
fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
1119-
// Don't visit nested modules, since we run a separate visitor walk
1120-
// for each module in `effective_visibilities`
1121-
}
1122-
1123-
fn visit_nested_body(&mut self, body: hir::BodyId) {
1103+
fn visit_nested_body(&mut self, body_id: hir::BodyId) {
11241104
let old_maybe_typeck_results =
1125-
self.maybe_typeck_results.replace(self.tcx.typeck_body(body));
1126-
let body = self.tcx.hir().body(body);
1127-
self.visit_body(body);
1105+
self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id));
1106+
self.visit_body(self.tcx.hir().body(body_id));
11281107
self.maybe_typeck_results = old_maybe_typeck_results;
11291108
}
11301109

1131-
fn visit_generic_arg(&mut self, generic_arg: &'tcx hir::GenericArg<'tcx>) {
1132-
match generic_arg {
1133-
hir::GenericArg::Type(t) => self.visit_ty(t),
1134-
hir::GenericArg::Infer(inf) => self.visit_infer(inf),
1135-
hir::GenericArg::Lifetime(_) | hir::GenericArg::Const(_) => {}
1136-
}
1137-
}
1138-
11391110
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) {
11401111
self.span = hir_ty.span;
11411112
if let Some(typeck_results) = self.maybe_typeck_results {
@@ -1163,19 +1134,19 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
11631134
return;
11641135
}
11651136
} else {
1166-
// We don't do anything for const infers here.
1137+
// FIXME: check types of const infers here.
11671138
}
11681139
} else {
1169-
bug!("visit_infer without typeck_results");
1140+
span_bug!(self.span, "`hir::InferArg` outside of a body");
11701141
}
11711142
intravisit::walk_inf(self, inf);
11721143
}
11731144

11741145
fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) {
11751146
self.span = trait_ref.path.span;
1176-
if self.maybe_typeck_results.is_none() {
1177-
// Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
1178-
// The traits' privacy in bodies is already checked as a part of trait object types.
1147+
if self.maybe_typeck_results.is_some() {
1148+
// Privacy of traits in bodies is checked as a part of trait object types.
1149+
} else {
11791150
let bounds = rustc_hir_analysis::hir_trait_to_predicates(
11801151
self.tcx,
11811152
trait_ref,
@@ -1223,7 +1194,10 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
12231194
hir::ExprKind::MethodCall(segment, ..) => {
12241195
// Method calls have to be checked specially.
12251196
self.span = segment.ident.span;
1226-
if let Some(def_id) = self.typeck_results().type_dependent_def_id(expr.hir_id) {
1197+
let typeck_results = self
1198+
.maybe_typeck_results
1199+
.unwrap_or_else(|| span_bug!(self.span, "`hir::Expr` outside of a body"));
1200+
if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
12271201
if self.visit(self.tcx.type_of(def_id).instantiate_identity()).is_break() {
12281202
return;
12291203
}
@@ -1251,9 +1225,13 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
12511225
Res::Def(kind, def_id) => Some((kind, def_id)),
12521226
_ => None,
12531227
},
1254-
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
1255-
.maybe_typeck_results
1256-
.and_then(|typeck_results| typeck_results.type_dependent_def(id)),
1228+
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => {
1229+
match self.maybe_typeck_results {
1230+
Some(typeck_results) => typeck_results.type_dependent_def(id),
1231+
// FIXME: Check type-relative associated types in signatures.
1232+
None => None,
1233+
}
1234+
}
12571235
};
12581236
let def = def.filter(|(kind, _)| {
12591237
matches!(
@@ -1307,15 +1285,6 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
13071285

13081286
intravisit::walk_local(self, local);
13091287
}
1310-
1311-
// Check types in item interfaces.
1312-
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
1313-
let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id);
1314-
let old_maybe_typeck_results = self.maybe_typeck_results.take();
1315-
intravisit::walk_item(self, item);
1316-
self.maybe_typeck_results = old_maybe_typeck_results;
1317-
self.current_item = orig_current_item;
1318-
}
13191288
}
13201289

13211290
impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
@@ -1785,13 +1754,8 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
17851754

17861755
// Check privacy of explicitly written types and traits as well as
17871756
// inferred types of expressions and patterns.
1788-
let mut visitor = TypePrivacyVisitor {
1789-
tcx,
1790-
maybe_typeck_results: None,
1791-
current_item: module_def_id.to_local_def_id(),
1792-
span,
1793-
};
1794-
intravisit::walk_mod(&mut visitor, module, hir_id);
1757+
let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span };
1758+
tcx.hir().visit_item_likes_in_module(module_def_id, &mut visitor);
17951759
}
17961760

17971761
fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {

tests/ui/privacy/private-type-in-interface.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type A = <m::Alias as m::Trait>::X; //~ ERROR type `Priv` is private
2626
trait Tr2<T> {}
2727
impl<T> Tr2<T> for u8 {}
2828
fn g() -> impl Tr2<m::Alias> { 0 } //~ ERROR type `Priv` is private
29+
//~| ERROR type `Priv` is private
2930
fn g_ext() -> impl Tr2<ext::Alias> { 0 } //~ ERROR type `ext::Priv` is private
30-
31+
//~| ERROR type `ext::Priv` is private
3132
fn main() {}

tests/ui/privacy/private-type-in-interface.stderr

+14-2
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,23 @@ error: type `Priv` is private
4646
LL | fn g() -> impl Tr2<m::Alias> { 0 }
4747
| ^^^^^^^^^^^^^^^^^^ private type
4848

49+
error: type `Priv` is private
50+
--> $DIR/private-type-in-interface.rs:28:16
51+
|
52+
LL | fn g() -> impl Tr2<m::Alias> { 0 }
53+
| ^^^^^^^^^^^^^ private type
54+
4955
error: type `ext::Priv` is private
50-
--> $DIR/private-type-in-interface.rs:29:15
56+
--> $DIR/private-type-in-interface.rs:30:15
5157
|
5258
LL | fn g_ext() -> impl Tr2<ext::Alias> { 0 }
5359
| ^^^^^^^^^^^^^^^^^^^^ private type
5460

55-
error: aborting due to 9 previous errors
61+
error: type `ext::Priv` is private
62+
--> $DIR/private-type-in-interface.rs:30:20
63+
|
64+
LL | fn g_ext() -> impl Tr2<ext::Alias> { 0 }
65+
| ^^^^^^^^^^^^^^^ private type
66+
67+
error: aborting due to 11 previous errors
5668

0 commit comments

Comments
 (0)