Skip to content

Implement check_attribute to forbid #[allow_internal_unsafe] #57467

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 10 commits into from
Jan 15, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
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
42 changes: 24 additions & 18 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ use syntax_pos::{BytePos, Span, SyntaxContext};
use syntax::symbol::keywords;
use syntax::errors::{Applicability, DiagnosticBuilder};
use syntax::print::pprust::expr_to_string;
use syntax::visit::FnKind;

use rustc::hir::{self, GenericParamKind, PatKind};
use rustc::hir::intravisit::FnKind;

use nonstandard_style::{MethodLateContext, method_context};

Expand Down Expand Up @@ -216,7 +216,7 @@ impl LintPass for UnsafeCode {
}

impl UnsafeCode {
fn report_unsafe(&self, cx: &LateContext, span: Span, desc: &'static str) {
fn report_unsafe(&self, cx: &EarlyContext, span: Span, desc: &'static str) {
// This comes from a macro that has #[allow_internal_unsafe].
if span.allows_unsafe() {
return;
Expand All @@ -226,23 +226,30 @@ impl UnsafeCode {
}
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
if let hir::ExprKind::Block(ref blk, _) = e.node {
impl EarlyLintPass for UnsafeCode {
fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
if attr.check_name("allow_internal_unsafe") {
self.report_unsafe(cx, attr.span, "cannot use `allow_internal_unsafe` \
with `forbid(unsafe_code)`");
}
}

fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) {
if let ast::ExprKind::Block(ref blk, _) = e.node {
// Don't warn about generated blocks, that'll just pollute the output.
if blk.rules == hir::UnsafeBlock(hir::UserProvided) {
if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
self.report_unsafe(cx, blk.span, "usage of an `unsafe` block");
}
}
}

fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
match it.node {
hir::ItemKind::Trait(_, hir::Unsafety::Unsafe, ..) => {
ast::ItemKind::Trait(_, ast::Unsafety::Unsafe, ..) => {
self.report_unsafe(cx, it.span, "declaration of an `unsafe` trait")
}

hir::ItemKind::Impl(hir::Unsafety::Unsafe, ..) => {
ast::ItemKind::Impl(ast::Unsafety::Unsafe, ..) => {
self.report_unsafe(cx, it.span, "implementation of an `unsafe` trait")
}

Expand All @@ -251,19 +258,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
}

fn check_fn(&mut self,
cx: &LateContext,
fk: FnKind<'tcx>,
_: &hir::FnDecl,
_: &hir::Body,
cx: &EarlyContext,
fk: FnKind,
_: &ast::FnDecl,
span: Span,
_: ast::NodeId) {
match fk {
FnKind::ItemFn(_, _, hir::FnHeader { unsafety: hir::Unsafety::Unsafe, .. }, ..) => {
FnKind::ItemFn(_, ast::FnHeader { unsafety: ast::Unsafety::Unsafe, .. }, ..) => {
self.report_unsafe(cx, span, "declaration of an `unsafe` function")
}

FnKind::Method(_, sig, ..) => {
if sig.header.unsafety == hir::Unsafety::Unsafe {
if sig.header.unsafety == ast::Unsafety::Unsafe {
self.report_unsafe(cx, span, "implementation of an `unsafe` method")
}
}
Expand All @@ -272,9 +278,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
}
}

fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
if let hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(_)) = item.node {
if sig.header.unsafety == hir::Unsafety::Unsafe {
fn check_trait_item(&mut self, cx: &EarlyContext, item: &ast::TraitItem) {
if let ast::TraitItemKind::Method(ref sig, _) = item.node {
if sig.header.unsafety == ast::Unsafety::Unsafe {
self.report_unsafe(cx, item.span, "declaration of an `unsafe` method")
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
add_early_builtin!(sess,
UnusedParens,
UnusedImportBraces,
UnsafeCode,
AnonymousParameters,
UnusedDocComment,
BadRepr,
Expand All @@ -134,7 +135,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
NonSnakeCase: NonSnakeCase,
NonUpperCaseGlobals: NonUpperCaseGlobals,
NonShorthandFieldPatterns: NonShorthandFieldPatterns,
UnsafeCode: UnsafeCode,
UnusedAllocation: UnusedAllocation,
MissingCopyImplementations: MissingCopyImplementations,
UnstableFeatures: UnstableFeatures,
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -853,13 +853,13 @@ pub struct Field {

pub type SpannedIdent = Spanned<Ident>;

#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
pub enum BlockCheckMode {
Default,
Unsafe(UnsafeSource),
}

#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
pub enum UnsafeSource {
CompilerGenerated,
UserProvided,
Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/lint/lint-forbid-internal-unsafe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![forbid(unsafe_code)]
#![feature(allow_internal_unsafe)]

#[allow_internal_unsafe]
//~^ ERROR: cannot use `allow_internal_unsafe` with `forbid(unsafe_code)`
macro_rules! evil {
($e:expr) => {
unsafe {
$e
}
}
}

fn main() {
println!("{}", evil!(*(0 as *const u8)));
}
14 changes: 14 additions & 0 deletions src/test/ui/lint/lint-forbid-internal-unsafe.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: cannot use `allow_internal_unsafe` with `forbid(unsafe_code)`
--> $DIR/lint-forbid-internal-unsafe.rs:4:1
|
LL | #[allow_internal_unsafe]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/lint-forbid-internal-unsafe.rs:1:11
|
LL | #![forbid(unsafe_code)]
| ^^^^^^^^^^^

error: aborting due to previous error

3 changes: 3 additions & 0 deletions src/test/ui/lint/lint-unsafe-code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ unsafe impl Foo for Bar {} //~ ERROR: implementation of an `unsafe` trait
trait Baz {
unsafe fn baz(&self); //~ ERROR: declaration of an `unsafe` method
unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
//~^ ERROR: declaration of an `unsafe` method
unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
//~^ ERROR: declaration of an `unsafe` method
}

impl Baz for Bar {
Expand Down Expand Up @@ -63,6 +65,7 @@ trait C {
#[allow(unsafe_code)]
unsafe fn baz(&self);
unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
//~^ ERROR: declaration of an `unsafe` method
}

impl C for Bar {
Expand Down
36 changes: 27 additions & 9 deletions src/test/ui/lint/lint-unsafe-code.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -28,56 +28,74 @@ error: declaration of an `unsafe` method
LL | unsafe fn baz(&self); //~ ERROR: declaration of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^

error: declaration of an `unsafe` method
--> $DIR/lint-unsafe-code.rs:29:5
|
LL | unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: implementation of an `unsafe` method
--> $DIR/lint-unsafe-code.rs:29:5
|
LL | unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: declaration of an `unsafe` method
--> $DIR/lint-unsafe-code.rs:31:5
|
LL | unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: implementation of an `unsafe` method
--> $DIR/lint-unsafe-code.rs:30:5
--> $DIR/lint-unsafe-code.rs:31:5
|
LL | unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: implementation of an `unsafe` method
--> $DIR/lint-unsafe-code.rs:34:5
--> $DIR/lint-unsafe-code.rs:36:5
|
LL | unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^^^

error: implementation of an `unsafe` method
--> $DIR/lint-unsafe-code.rs:35:5
--> $DIR/lint-unsafe-code.rs:37:5
|
LL | unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: implementation of an `unsafe` method
--> $DIR/lint-unsafe-code.rs:54:5
--> $DIR/lint-unsafe-code.rs:56:5
|
LL | unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: declaration of an `unsafe` method
--> $DIR/lint-unsafe-code.rs:67:5
|
LL | unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: implementation of an `unsafe` method
--> $DIR/lint-unsafe-code.rs:65:5
--> $DIR/lint-unsafe-code.rs:67:5
|
LL | unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: implementation of an `unsafe` method
--> $DIR/lint-unsafe-code.rs:71:5
--> $DIR/lint-unsafe-code.rs:74:5
|
LL | unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: implementation of an `unsafe` method
--> $DIR/lint-unsafe-code.rs:75:5
--> $DIR/lint-unsafe-code.rs:78:5
|
LL | unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method
| ^^^^^^^^^^^^^^^^^^^^^^^

error: usage of an `unsafe` block
--> $DIR/lint-unsafe-code.rs:86:5
--> $DIR/lint-unsafe-code.rs:89:5
|
LL | unsafe {} //~ ERROR: usage of an `unsafe` block
| ^^^^^^^^^
Expand All @@ -91,5 +109,5 @@ LL | unsafe {} //~ ERROR: usage of an `unsafe` block
LL | unsafe_in_macro!()
| ------------------ in this macro invocation

error: aborting due to 14 previous errors
error: aborting due to 17 previous errors