Skip to content

Commit 0111fb0

Browse files
committed
add TestReachabilityVisitor
1 parent 1080467 commit 0111fb0

File tree

7 files changed

+246
-2
lines changed

7 files changed

+246
-2
lines changed

compiler/rustc_error_messages/locales/en-US/privacy.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interfac
1111
.label = can't leak {$vis_descr} {$kind}
1212
.visibility_label = `{$descr}` declared as {$vis_descr}
1313
14+
privacy_report_access_level = {$descr}
15+
1416
privacy_from_private_dep_in_public_interface =
1517
{$kind} `{$descr}` from private dependency '{$krate}' in public interface
1618

compiler/rustc_feature/src/builtin_attrs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
758758
// Internal attributes, Testing:
759759
// ==========================================================================
760760

761+
rustc_attr!(TEST, rustc_access_level, Normal, template!(Word), WarnFollowing),
761762
rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing),
762763
rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing),
763764
rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing),

compiler/rustc_privacy/src/errors.rs

+8
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ pub struct InPublicInterface<'a> {
7575
pub vis_span: Span,
7676
}
7777

78+
#[derive(SessionDiagnostic)]
79+
#[diag(privacy::report_access_level)]
80+
pub struct ReportAccessLevel {
81+
#[primary_span]
82+
pub span: Span,
83+
pub descr: String,
84+
}
85+
7886
#[derive(LintDiagnostic)]
7987
#[diag(privacy::from_private_dep_in_public_interface)]
8088
pub struct FromPrivateDependencyInPublicInterface<'a> {

compiler/rustc_privacy/src/lib.rs

+60-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind};
3030
use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
3131
use rustc_session::lint;
3232
use rustc_span::hygiene::Transparency;
33-
use rustc_span::symbol::{kw, Ident};
33+
use rustc_span::symbol::{kw, sym, Ident};
3434
use rustc_span::Span;
3535

3636
use std::marker::PhantomData;
@@ -39,7 +39,8 @@ use std::{cmp, fmt, mem};
3939

4040
use errors::{
4141
FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
42-
InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, UnnamedItemIsPrivate,
42+
InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportAccessLevel,
43+
UnnamedItemIsPrivate,
4344
};
4445

4546
////////////////////////////////////////////////////////////////////////////////
@@ -904,6 +905,60 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
904905
}
905906
}
906907

908+
////////////////////////////////////////////////////////////////////////////////
909+
/// Visitor, used for AccessLevels table checking
910+
////////////////////////////////////////////////////////////////////////////////
911+
pub struct TestReachabilityVisitor<'tcx, 'a> {
912+
tcx: TyCtxt<'tcx>,
913+
access_levels: &'a AccessLevels,
914+
}
915+
916+
impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> {
917+
fn access_level_diagnostic(&mut self, def_id: LocalDefId) {
918+
if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_access_level) {
919+
let access_level = format!("{:?}", self.access_levels.map.get(&def_id));
920+
let span = self.tcx.def_span(def_id.to_def_id());
921+
self.tcx.sess.emit_err(ReportAccessLevel { span, descr: access_level });
922+
}
923+
}
924+
}
925+
926+
impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> {
927+
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
928+
self.access_level_diagnostic(item.def_id);
929+
930+
match item.kind {
931+
hir::ItemKind::Enum(ref def, _) => {
932+
for variant in def.variants.iter() {
933+
let variant_id = self.tcx.hir().local_def_id(variant.id);
934+
self.access_level_diagnostic(variant_id);
935+
for field in variant.data.fields() {
936+
let def_id = self.tcx.hir().local_def_id(field.hir_id);
937+
self.access_level_diagnostic(def_id);
938+
}
939+
}
940+
}
941+
hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
942+
for field in def.fields() {
943+
let def_id = self.tcx.hir().local_def_id(field.hir_id);
944+
self.access_level_diagnostic(def_id);
945+
}
946+
}
947+
_ => {}
948+
}
949+
}
950+
951+
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) {
952+
self.access_level_diagnostic(item.def_id);
953+
}
954+
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) {
955+
self.access_level_diagnostic(item.def_id);
956+
}
957+
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
958+
self.access_level_diagnostic(item.def_id);
959+
}
960+
}
961+
907962
//////////////////////////////////////////////////////////////////////////////////////
908963
/// Name privacy visitor, checks privacy and reports violations.
909964
/// Most of name privacy checks are performed during the main resolution phase,
@@ -2042,6 +2097,9 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
20422097
}
20432098
}
20442099

2100+
let mut check_visitor = TestReachabilityVisitor { tcx, access_levels: &visitor.access_levels };
2101+
tcx.hir().visit_all_item_likes_in_crate(&mut check_visitor);
2102+
20452103
tcx.arena.alloc(visitor.access_levels)
20462104
}
20472105

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,7 @@ symbols! {
12061206
rust_eh_unregister_frames,
12071207
rust_oom,
12081208
rustc,
1209+
rustc_access_level,
12091210
rustc_allocator,
12101211
rustc_allocator_nounwind,
12111212
rustc_allocator_zeroed,

src/test/ui/privacy/access_levels.rs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#![feature(rustc_attrs)]
2+
3+
#[rustc_access_level] mod outer { //~ ERROR None
4+
#[rustc_access_level] pub mod inner { //~ ERROR Some(Exported)
5+
#[rustc_access_level]
6+
extern "C" { //~ ERROR Some(Exported)
7+
#[rustc_access_level] static a: u8; //~ ERROR None
8+
#[rustc_access_level] pub fn b(); //~ ERROR Some(Exported)
9+
}
10+
#[rustc_access_level]
11+
pub trait Trait { //~ ERROR Some(Exported)
12+
#[rustc_access_level] const A: i32; //~ ERROR Some(Exported)
13+
#[rustc_access_level] type B; //~ ERROR Some(Exported)
14+
}
15+
16+
#[rustc_access_level]
17+
pub struct Struct { //~ ERROR Some(Exported)
18+
#[rustc_access_level] a: u8, //~ ERROR None
19+
#[rustc_access_level] pub b: u8, //~ ERROR Some(Exported)
20+
}
21+
22+
#[rustc_access_level]
23+
pub union Union { //~ ERROR Some(Exported)
24+
#[rustc_access_level] a: u8, //~ ERROR None
25+
#[rustc_access_level] pub b: u8, //~ ERROR Some(Exported)
26+
}
27+
28+
#[rustc_access_level]
29+
pub enum Enum { //~ ERROR Some(Exported)
30+
#[rustc_access_level] A( //~ ERROR Some(Exported)
31+
#[rustc_access_level] Struct, //~ ERROR Some(Exported)
32+
#[rustc_access_level] Union, //~ ERROR Some(Exported)
33+
),
34+
}
35+
}
36+
37+
#[rustc_access_level] macro_rules! none_macro { //~ ERROR None
38+
() => {};
39+
}
40+
41+
#[macro_export]
42+
#[rustc_access_level] macro_rules! public_macro { //~ ERROR Some(Public)
43+
() => {};
44+
}
45+
}
46+
47+
pub use outer::inner;
48+
49+
fn main() {}
+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
error: None
2+
--> $DIR/access_levels.rs:3:23
3+
|
4+
LL | #[rustc_access_level] mod outer {
5+
| ^^^^^^^^^
6+
7+
error: Some(Exported)
8+
--> $DIR/access_levels.rs:4:27
9+
|
10+
LL | #[rustc_access_level] pub mod inner {
11+
| ^^^^^^^^^^^^^
12+
13+
error: Some(Exported)
14+
--> $DIR/access_levels.rs:6:9
15+
|
16+
LL | / extern "C" {
17+
LL | | #[rustc_access_level] static a: u8;
18+
LL | | #[rustc_access_level] pub fn b();
19+
LL | | }
20+
| |_________^
21+
22+
error: Some(Exported)
23+
--> $DIR/access_levels.rs:11:9
24+
|
25+
LL | pub trait Trait {
26+
| ^^^^^^^^^^^^^^^
27+
28+
error: Some(Exported)
29+
--> $DIR/access_levels.rs:17:9
30+
|
31+
LL | pub struct Struct {
32+
| ^^^^^^^^^^^^^^^^^
33+
34+
error: None
35+
--> $DIR/access_levels.rs:18:35
36+
|
37+
LL | #[rustc_access_level] a: u8,
38+
| ^^^^^
39+
40+
error: Some(Exported)
41+
--> $DIR/access_levels.rs:19:35
42+
|
43+
LL | #[rustc_access_level] pub b: u8,
44+
| ^^^^^^^^^
45+
46+
error: Some(Exported)
47+
--> $DIR/access_levels.rs:23:9
48+
|
49+
LL | pub union Union {
50+
| ^^^^^^^^^^^^^^^
51+
52+
error: None
53+
--> $DIR/access_levels.rs:24:35
54+
|
55+
LL | #[rustc_access_level] a: u8,
56+
| ^^^^^
57+
58+
error: Some(Exported)
59+
--> $DIR/access_levels.rs:25:35
60+
|
61+
LL | #[rustc_access_level] pub b: u8,
62+
| ^^^^^^^^^
63+
64+
error: Some(Exported)
65+
--> $DIR/access_levels.rs:29:9
66+
|
67+
LL | pub enum Enum {
68+
| ^^^^^^^^^^^^^
69+
70+
error: Some(Exported)
71+
--> $DIR/access_levels.rs:30:35
72+
|
73+
LL | #[rustc_access_level] A(
74+
| ^
75+
76+
error: Some(Exported)
77+
--> $DIR/access_levels.rs:31:39
78+
|
79+
LL | #[rustc_access_level] Struct,
80+
| ^^^^^^
81+
82+
error: Some(Exported)
83+
--> $DIR/access_levels.rs:32:39
84+
|
85+
LL | #[rustc_access_level] Union,
86+
| ^^^^^
87+
88+
error: None
89+
--> $DIR/access_levels.rs:37:27
90+
|
91+
LL | #[rustc_access_level] macro_rules! none_macro {
92+
| ^^^^^^^^^^^^^^^^^^^^^^^
93+
94+
error: Some(Public)
95+
--> $DIR/access_levels.rs:42:27
96+
|
97+
LL | #[rustc_access_level] macro_rules! public_macro {
98+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
99+
100+
error: Some(Exported)
101+
--> $DIR/access_levels.rs:12:35
102+
|
103+
LL | #[rustc_access_level] const A: i32;
104+
| ^^^^^^^^^^^^
105+
106+
error: Some(Exported)
107+
--> $DIR/access_levels.rs:13:35
108+
|
109+
LL | #[rustc_access_level] type B;
110+
| ^^^^^^
111+
112+
error: None
113+
--> $DIR/access_levels.rs:7:35
114+
|
115+
LL | #[rustc_access_level] static a: u8;
116+
| ^^^^^^^^^^^^
117+
118+
error: Some(Exported)
119+
--> $DIR/access_levels.rs:8:35
120+
|
121+
LL | #[rustc_access_level] pub fn b();
122+
| ^^^^^^^^^^
123+
124+
error: aborting due to 20 previous errors
125+

0 commit comments

Comments
 (0)