Skip to content

Commit

Permalink
add TestReachabilityVisitor
Browse files Browse the repository at this point in the history
  • Loading branch information
Bryanskiy committed Aug 31, 2022
1 parent 1080467 commit 0111fb0
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 2 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/privacy.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interfac
.label = can't leak {$vis_descr} {$kind}
.visibility_label = `{$descr}` declared as {$vis_descr}
privacy_report_access_level = {$descr}
privacy_from_private_dep_in_public_interface =
{$kind} `{$descr}` from private dependency '{$krate}' in public interface
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// Internal attributes, Testing:
// ==========================================================================

rustc_attr!(TEST, rustc_access_level, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing),
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_privacy/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ pub struct InPublicInterface<'a> {
pub vis_span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(privacy::report_access_level)]
pub struct ReportAccessLevel {
#[primary_span]
pub span: Span,
pub descr: String,
}

#[derive(LintDiagnostic)]
#[diag(privacy::from_private_dep_in_public_interface)]
pub struct FromPrivateDependencyInPublicInterface<'a> {
Expand Down
62 changes: 60 additions & 2 deletions compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind};
use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_session::lint;
use rustc_span::hygiene::Transparency;
use rustc_span::symbol::{kw, Ident};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;

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

use errors::{
FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, UnnamedItemIsPrivate,
InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportAccessLevel,
UnnamedItemIsPrivate,
};

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -904,6 +905,60 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
}
}

////////////////////////////////////////////////////////////////////////////////
/// Visitor, used for AccessLevels table checking
////////////////////////////////////////////////////////////////////////////////
pub struct TestReachabilityVisitor<'tcx, 'a> {
tcx: TyCtxt<'tcx>,
access_levels: &'a AccessLevels,
}

impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> {
fn access_level_diagnostic(&mut self, def_id: LocalDefId) {
if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_access_level) {
let access_level = format!("{:?}", self.access_levels.map.get(&def_id));
let span = self.tcx.def_span(def_id.to_def_id());
self.tcx.sess.emit_err(ReportAccessLevel { span, descr: access_level });
}
}
}

impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> {
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
self.access_level_diagnostic(item.def_id);

match item.kind {
hir::ItemKind::Enum(ref def, _) => {
for variant in def.variants.iter() {
let variant_id = self.tcx.hir().local_def_id(variant.id);
self.access_level_diagnostic(variant_id);
for field in variant.data.fields() {
let def_id = self.tcx.hir().local_def_id(field.hir_id);
self.access_level_diagnostic(def_id);
}
}
}
hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
for field in def.fields() {
let def_id = self.tcx.hir().local_def_id(field.hir_id);
self.access_level_diagnostic(def_id);
}
}
_ => {}
}
}

fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) {
self.access_level_diagnostic(item.def_id);
}
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) {
self.access_level_diagnostic(item.def_id);
}
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
self.access_level_diagnostic(item.def_id);
}
}

//////////////////////////////////////////////////////////////////////////////////////
/// Name privacy visitor, checks privacy and reports violations.
/// Most of name privacy checks are performed during the main resolution phase,
Expand Down Expand Up @@ -2042,6 +2097,9 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
}
}

let mut check_visitor = TestReachabilityVisitor { tcx, access_levels: &visitor.access_levels };
tcx.hir().visit_all_item_likes_in_crate(&mut check_visitor);

tcx.arena.alloc(visitor.access_levels)
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,7 @@ symbols! {
rust_eh_unregister_frames,
rust_oom,
rustc,
rustc_access_level,
rustc_allocator,
rustc_allocator_nounwind,
rustc_allocator_zeroed,
Expand Down
49 changes: 49 additions & 0 deletions src/test/ui/privacy/access_levels.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#![feature(rustc_attrs)]

#[rustc_access_level] mod outer { //~ ERROR None
#[rustc_access_level] pub mod inner { //~ ERROR Some(Exported)
#[rustc_access_level]
extern "C" { //~ ERROR Some(Exported)
#[rustc_access_level] static a: u8; //~ ERROR None
#[rustc_access_level] pub fn b(); //~ ERROR Some(Exported)
}
#[rustc_access_level]
pub trait Trait { //~ ERROR Some(Exported)
#[rustc_access_level] const A: i32; //~ ERROR Some(Exported)
#[rustc_access_level] type B; //~ ERROR Some(Exported)
}

#[rustc_access_level]
pub struct Struct { //~ ERROR Some(Exported)
#[rustc_access_level] a: u8, //~ ERROR None
#[rustc_access_level] pub b: u8, //~ ERROR Some(Exported)
}

#[rustc_access_level]
pub union Union { //~ ERROR Some(Exported)
#[rustc_access_level] a: u8, //~ ERROR None
#[rustc_access_level] pub b: u8, //~ ERROR Some(Exported)
}

#[rustc_access_level]
pub enum Enum { //~ ERROR Some(Exported)
#[rustc_access_level] A( //~ ERROR Some(Exported)
#[rustc_access_level] Struct, //~ ERROR Some(Exported)
#[rustc_access_level] Union, //~ ERROR Some(Exported)
),
}
}

#[rustc_access_level] macro_rules! none_macro { //~ ERROR None
() => {};
}

#[macro_export]
#[rustc_access_level] macro_rules! public_macro { //~ ERROR Some(Public)
() => {};
}
}

pub use outer::inner;

fn main() {}
125 changes: 125 additions & 0 deletions src/test/ui/privacy/access_levels.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
error: None
--> $DIR/access_levels.rs:3:23
|
LL | #[rustc_access_level] mod outer {
| ^^^^^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:4:27
|
LL | #[rustc_access_level] pub mod inner {
| ^^^^^^^^^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:6:9
|
LL | / extern "C" {
LL | | #[rustc_access_level] static a: u8;
LL | | #[rustc_access_level] pub fn b();
LL | | }
| |_________^

error: Some(Exported)
--> $DIR/access_levels.rs:11:9
|
LL | pub trait Trait {
| ^^^^^^^^^^^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:17:9
|
LL | pub struct Struct {
| ^^^^^^^^^^^^^^^^^

error: None
--> $DIR/access_levels.rs:18:35
|
LL | #[rustc_access_level] a: u8,
| ^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:19:35
|
LL | #[rustc_access_level] pub b: u8,
| ^^^^^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:23:9
|
LL | pub union Union {
| ^^^^^^^^^^^^^^^

error: None
--> $DIR/access_levels.rs:24:35
|
LL | #[rustc_access_level] a: u8,
| ^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:25:35
|
LL | #[rustc_access_level] pub b: u8,
| ^^^^^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:29:9
|
LL | pub enum Enum {
| ^^^^^^^^^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:30:35
|
LL | #[rustc_access_level] A(
| ^

error: Some(Exported)
--> $DIR/access_levels.rs:31:39
|
LL | #[rustc_access_level] Struct,
| ^^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:32:39
|
LL | #[rustc_access_level] Union,
| ^^^^^

error: None
--> $DIR/access_levels.rs:37:27
|
LL | #[rustc_access_level] macro_rules! none_macro {
| ^^^^^^^^^^^^^^^^^^^^^^^

error: Some(Public)
--> $DIR/access_levels.rs:42:27
|
LL | #[rustc_access_level] macro_rules! public_macro {
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:12:35
|
LL | #[rustc_access_level] const A: i32;
| ^^^^^^^^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:13:35
|
LL | #[rustc_access_level] type B;
| ^^^^^^

error: None
--> $DIR/access_levels.rs:7:35
|
LL | #[rustc_access_level] static a: u8;
| ^^^^^^^^^^^^

error: Some(Exported)
--> $DIR/access_levels.rs:8:35
|
LL | #[rustc_access_level] pub fn b();
| ^^^^^^^^^^

error: aborting due to 20 previous errors

0 comments on commit 0111fb0

Please sign in to comment.