diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index f1f5e3ef6e1..c5f3b45950e 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1709,7 +1709,6 @@ impl LintPass for SoftLints { } } - declare_lint! { pub ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, Allow, @@ -1744,3 +1743,44 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { } } } + +declare_lint! { + UNNAMEABLE_TEST_FUNCTIONS, + Warn, + "detects an function that cannot be named being marked as #[test]" +} + +pub struct UnnameableTestFunctions; + +impl LintPass for UnnameableTestFunctions { + fn get_lints(&self) -> LintArray { + lint_array!(UNNAMEABLE_TEST_FUNCTIONS) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestFunctions { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { + match it.node { + hir::ItemFn(..) => { + for attr in &it.attrs { + if attr.name() == "test" { + let parent = cx.tcx.hir.get_parent(it.id); + match cx.tcx.hir.find(parent) { + Some(hir_map::NodeItem(hir::Item {node: hir::ItemMod(_), ..})) | + None => {} + _ => { + cx.struct_span_lint( + UNNAMEABLE_TEST_FUNCTIONS, + attr.span, + "cannot test inner function", + ).emit(); + } + } + break; + } + } + } + _ => return, + }; + } +} diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 13e97a9d3e5..adc700506ff 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -130,6 +130,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { MutableTransmutes: MutableTransmutes, UnionsWithDropFields: UnionsWithDropFields, UnreachablePub: UnreachablePub, + UnnameableTestFunctions: UnnameableTestFunctions, TypeAliasBounds: TypeAliasBounds, UnusedBrokenConst: UnusedBrokenConst, TrivialConstraints: TrivialConstraints, diff --git a/src/test/ui/lint/test-inner-fn.rs b/src/test/ui/lint/test-inner-fn.rs new file mode 100644 index 00000000000..4304c96197f --- /dev/null +++ b/src/test/ui/lint/test-inner-fn.rs @@ -0,0 +1,29 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: --test -D unnameable_test_functions + +#[test] +fn foo() { + #[test] //~ ERROR cannot test inner function [unnameable_test_functions] + fn bar() {} + bar(); +} + +mod x { + #[test] + fn foo() { + #[test] //~ ERROR cannot test inner function [unnameable_test_functions] + fn bar() {} + bar(); + } +} + +fn main() {} diff --git a/src/test/ui/lint/test-inner-fn.stderr b/src/test/ui/lint/test-inner-fn.stderr new file mode 100644 index 00000000000..37f0c161036 --- /dev/null +++ b/src/test/ui/lint/test-inner-fn.stderr @@ -0,0 +1,16 @@ +error: cannot test inner function + --> $DIR/test-inner-fn.rs:15:5 + | +LL | #[test] //~ ERROR cannot test inner function [unnameable_test_functions] + | ^^^^^^^ + | + = note: requested on the command line with `-D unnameable-test-functions` + +error: cannot test inner function + --> $DIR/test-inner-fn.rs:23:9 + | +LL | #[test] //~ ERROR cannot test inner function [unnameable_test_functions] + | ^^^^^^^ + +error: aborting due to 2 previous errors +