diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 8a00622486d..9b5e94e87a1 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1292,48 +1292,38 @@ impl LintPass for UnsafeCode { } fn check_item(&mut self, cx: &Context, it: &ast::Item) { - use syntax::ast::Unsafety::Unsafe; - - fn check_method(cx: &Context, meth: &P) { - 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(ast::Unsafety::Unsafe, _, _, _) => + cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait"), - 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); - } - } - }, + ast::ItemImpl(ast::Unsafety::Unsafe, _, _, _, _, _) => + cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait"), _ => return, } } + + fn check_fn(&mut self, cx: &Context, fk: visit::FnKind, _: &ast::FnDecl, + _: &ast::Block, span: Span, _: ast::NodeId) { + match fk { + visit::FkItemFn(_, _, ast::Unsafety::Unsafe, _) => + cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function"), + + visit::FkMethod(_, _, m) => { + if let ast::Method_::MethDecl(_, _, _, _, ast::Unsafety::Unsafe, _, _, _) = m.node { + cx.span_lint(UNSAFE_CODE, m.span, "implementation of an `unsafe` method") + } + }, + + _ => (), + } + } + + fn check_ty_method(&mut self, cx: &Context, ty_method: &ast::TypeMethod) { + if let ast::TypeMethod { unsafety: ast::Unsafety::Unsafe, span, ..} = *ty_method { + cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` method") + } + } } declare_lint! { diff --git a/src/test/compile-fail/lint-unsafe-code.rs b/src/test/compile-fail/lint-unsafe-code.rs index 7b17d887757..8440cf3a88e 100644 --- a/src/test/compile-fail/lint-unsafe-code.rs +++ b/src/test/compile-fail/lint-unsafe-code.rs @@ -15,6 +15,8 @@ use std::marker::PhantomFn; struct Bar; +struct Bar2; +struct Bar3; #[allow(unsafe_code)] mod allowed_unsafe { @@ -46,6 +48,53 @@ impl Baz for Bar { unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method } + +#[allow(unsafe_code)] +trait A { + unsafe fn allowed_unsafe(&self); + unsafe fn allowed_unsafe_provided(&self) {} +} + +#[allow(unsafe_code)] +impl Baz for Bar2 { + unsafe fn baz(&self) {} + unsafe fn provided_override(&self) {} +} + +impl Baz for Bar3 { + #[allow(unsafe_code)] + unsafe fn baz(&self) {} + unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +#[allow(unsafe_code)] +unsafe trait B { + fn dummy(&self) {} +} + +trait C { + #[allow(unsafe_code)] + unsafe fn baz(&self); + unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +impl C for Bar { + #[allow(unsafe_code)] + unsafe fn baz(&self) {} + unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +impl C for Bar2 { + unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +trait D { + #[allow(unsafe_code)] + unsafe fn unsafe_provided(&self) {} +} + +impl D for Bar {} + fn main() { unsafe {} //~ ERROR: usage of an `unsafe` block