Skip to content

optimization of access level table construction #100147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 2, 2022
Merged
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
add TestReachabilityVisitor
  • Loading branch information
Bryanskiy committed Aug 31, 2022
commit 0111fb00dac90d67f8d770ca2a25923cfd24e25d
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