Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add TestReachabilityVisitor
  • Loading branch information
Bryanskiy committed Aug 16, 2022
commit d0884c43f937aaeeda5d0f1c3da8b8ad0bb326aa
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_invalid_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 @@ -762,6 +762,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)]
#[error(privacy::invalid_access_level)]
pub struct ReportAccessLevel {
#[primary_span]
pub span: Span,
pub descr: String,
}

#[derive(LintDiagnostic)]
#[lint(privacy::from_private_dep_in_public_interface)]
pub struct FromPrivateDependencyInPublicInterface<'a> {
Expand Down
63 changes: 61 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> {
tcx: TyCtxt<'tcx>,
access_levels: &'tcx AccessLevels,
}

impl<'tcx> TestReachabilityVisitor<'tcx> {
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> Visitor<'tcx> for TestReachabilityVisitor<'tcx> {
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 @@ -2043,6 +2098,10 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
}
}

let mut check_visitor =
TestReachabilityVisitor { tcx, access_levels: &tcx.resolutions(()).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 @@ -1201,6 +1201,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