Rollup merge of #22542 - ipetkov:unsafe-lint, r=huonw

This allows warning or forbidding all uses of unsafe code, whereas
previously only unsafe blocks were caught by the lint.

The lint has been renamed from `unsafe-blocks` to `unsafe-code` to
reflect its new purpose.

This is a minor [breaking-change]

Closes #22430
This commit is contained in:
Manish Goregaokar 2015-02-22 01:50:53 +05:30
commit 98ec45ee0b
4 changed files with 103 additions and 37 deletions

View File

@ -1,4 +1,4 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -1269,27 +1269,71 @@ impl LintPass for UnusedUnsafe {
}
declare_lint! {
UNSAFE_BLOCKS,
UNSAFE_CODE,
Allow,
"usage of an `unsafe` block"
"usage of `unsafe` code"
}
#[derive(Copy)]
pub struct UnsafeBlocks;
pub struct UnsafeCode;
impl LintPass for UnsafeBlocks {
impl LintPass for UnsafeCode {
fn get_lints(&self) -> LintArray {
lint_array!(UNSAFE_BLOCKS)
lint_array!(UNSAFE_CODE)
}
fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
if let ast::ExprBlock(ref blk) = e.node {
// Don't warn about generated blocks, that'll just pollute the output.
if blk.rules == ast::UnsafeBlock(ast::UserProvided) {
cx.span_lint(UNSAFE_BLOCKS, blk.span, "usage of an `unsafe` block");
cx.span_lint(UNSAFE_CODE, blk.span, "usage of an `unsafe` block");
}
}
}
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
use syntax::ast::Unsafety::Unsafe;
fn check_method(cx: &Context, meth: &P<ast::Method>) {
if let ast::Method_::MethDecl(_, _, _, _, Unsafe, _, _, _) = meth.node {
cx.span_lint(UNSAFE_CODE, meth.span, "implementation of an `unsafe` method");
}
}
match it.node {
ast::ItemFn(_, Unsafe, _, _, _) =>
cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` function"),
ast::ItemTrait(trait_safety, _, _, ref items) => {
if trait_safety == Unsafe {
cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait");
}
for it in items {
match *it {
ast::RequiredMethod(ast::TypeMethod { unsafety: Unsafe, span, ..}) =>
cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` method"),
ast::ProvidedMethod(ref meth) => check_method(cx, meth),
_ => (),
}
}
},
ast::ItemImpl(impl_safety, _, _, _, _, ref impls) => {
if impl_safety == Unsafe {
cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait");
}
for item in impls {
if let ast::ImplItem::MethodImplItem(ref meth) = *item {
check_method(cx, meth);
}
}
},
_ => return,
}
}
}
declare_lint! {

View File

@ -1,4 +1,4 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -206,7 +206,7 @@ impl LintStore {
UnusedImportBraces,
NonShorthandFieldPatterns,
UnusedUnsafe,
UnsafeBlocks,
UnsafeCode,
UnusedMut,
UnusedAllocation,
MissingCopyImplementations,

View File

@ -1,28 +0,0 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(unused_unsafe)]
#![allow(dead_code)]
#![deny(unsafe_blocks)]
unsafe fn allowed() {}
#[allow(unsafe_blocks)] fn also_allowed() { unsafe {} }
macro_rules! unsafe_in_macro {
() => {
unsafe {} //~ ERROR: usage of an `unsafe` block
}
}
fn main() {
unsafe {} //~ ERROR: usage of an `unsafe` block
unsafe_in_macro!()
}

View File

@ -0,0 +1,50 @@
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(unused_unsafe)]
#![allow(dead_code)]
#![deny(unsafe_code)]
struct Bar;
#[allow(unsafe_code)]
mod allowed_unsafe {
fn allowed() { unsafe {} }
unsafe fn also_allowed() {}
unsafe trait AllowedUnsafe {}
unsafe impl AllowedUnsafe for super::Bar {}
}
macro_rules! unsafe_in_macro {
() => {
unsafe {} //~ ERROR: usage of an `unsafe` block
}
}
unsafe fn baz() {} //~ ERROR: declaration of an `unsafe` function
unsafe trait Foo {} //~ ERROR: declaration of an `unsafe` trait
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
unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
}
impl Baz for Bar {
unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method
unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
}
fn main() {
unsafe {} //~ ERROR: usage of an `unsafe` block
unsafe_in_macro!()
}