Rollup merge of #92959 - asquared31415:test-non-fn-help, r=estebank
Add more info and suggestions to use of #[test] on invalid items This pr changes the diagnostics for using `#[test]` on an item that can't be used as a test to explain that the attribute has no meaningful effect on non-functions and suggests the use of `#[cfg(test)]` for conditional compilation instead. Example change: ```rs #[test] mod test {} ``` previously output ``` error: only functions may be used as tests --> src/lib.rs:2:1 | 2 | mod test {} | ^^^^^^^^^^^ ``` now outputs ``` error: the `#[test]` attribute may only be used on a non-associated function --> $DIR/test-on-not-fn.rs:3:1 | LL | #[test] | ^^^^^^^ LL | mod test {} | ----------- expected a non-associated function, found a module | = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions help: replace with conditional compilation to make the item only exist when tests are being run | LL | #[cfg(test)] | ~~~~~~~~~~~~ ```
This commit is contained in:
commit
659382fa47
7 changed files with 281 additions and 41 deletions
|
@ -6,6 +6,7 @@ use rustc_ast as ast;
|
||||||
use rustc_ast::attr;
|
use rustc_ast::attr;
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
|
use rustc_errors::Applicability;
|
||||||
use rustc_expand::base::*;
|
use rustc_expand::base::*;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||||
|
@ -102,11 +103,20 @@ pub fn expand_test_or_bench(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let ast::ItemKind::MacCall(_) = item.kind {
|
// Note: non-associated fn items are already handled by `expand_test_or_bench`
|
||||||
cx.sess.parse_sess.span_diagnostic.span_warn(
|
if !matches!(item.kind, ast::ItemKind::Fn(_)) {
|
||||||
item.span,
|
cx.sess
|
||||||
"`#[test]` attribute should not be used on macros. Use `#[cfg(test)]` instead.",
|
.parse_sess
|
||||||
);
|
.span_diagnostic
|
||||||
|
.struct_span_err(
|
||||||
|
attr_sp,
|
||||||
|
"the `#[test]` attribute may only be used on a non-associated function",
|
||||||
|
)
|
||||||
|
.note("the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions")
|
||||||
|
.span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr()))
|
||||||
|
.span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", String::from("#[cfg(test)]"), Applicability::MaybeIncorrect)
|
||||||
|
.emit();
|
||||||
|
|
||||||
return vec![Annotatable::Item(item)];
|
return vec![Annotatable::Item(item)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,7 +476,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
|
||||||
(false, _) => true,
|
(false, _) => true,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sd.span_err(i.span, "only functions may be used as tests");
|
// should be unreachable because `is_test_fn_item` should catch all non-fn items
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
// compile-flags: --test
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
mod foo {} //~ ERROR only functions may be used as tests
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,8 +0,0 @@
|
||||||
error: only functions may be used as tests
|
|
||||||
--> $DIR/issue-14772.rs:4:1
|
|
||||||
|
|
|
||||||
LL | mod foo {}
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
// check-pass
|
|
||||||
// compile-flags:--test
|
|
||||||
|
|
||||||
#![deny(warnings)]
|
|
||||||
|
|
||||||
macro_rules! foo {
|
|
||||||
() => (fn foo(){})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
foo!(); //~ WARNING `#[test]` attribute should not be used on macros
|
|
||||||
|
|
||||||
fn main(){}
|
|
|
@ -1,8 +0,0 @@
|
||||||
warning: `#[test]` attribute should not be used on macros. Use `#[cfg(test)]` instead.
|
|
||||||
--> $DIR/test-on-macro.rs:11:1
|
|
||||||
|
|
|
||||||
LL | foo!();
|
|
||||||
| ^^^^^^^
|
|
||||||
|
|
||||||
warning: 1 warning emitted
|
|
||||||
|
|
80
src/test/ui/test-attrs/test-on-not-fn.rs
Normal file
80
src/test/ui/test-attrs/test-on-not-fn.rs
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
// compile-flags: --test
|
||||||
|
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
mod test {}
|
||||||
|
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
mod loooooooooooooong_teeeeeeeeeest {
|
||||||
|
/*
|
||||||
|
this is a comment
|
||||||
|
this comment goes on for a very long time
|
||||||
|
this is to pad out the span for this module for a long time
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
|
||||||
|
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
|
||||||
|
laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
|
||||||
|
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
|
||||||
|
non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
extern "C" {}
|
||||||
|
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
trait Foo {}
|
||||||
|
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
impl Foo for i32 {}
|
||||||
|
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
const FOO: i32 = -1_i32;
|
||||||
|
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
static BAR: u64 = 10_000_u64;
|
||||||
|
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
enum MyUnit {
|
||||||
|
Unit,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
struct NewI32(i32);
|
||||||
|
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
union Spooky {
|
||||||
|
x: i32,
|
||||||
|
y: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, align(64))]
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
struct MoreAttrs {
|
||||||
|
a: i32,
|
||||||
|
b: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo {
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
foo!();
|
||||||
|
|
||||||
|
// make sure it doesn't erroneously trigger on a real test
|
||||||
|
#[test]
|
||||||
|
fn real_test() {
|
||||||
|
assert_eq!(42_i32, 42_i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure it works with cfg test
|
||||||
|
#[cfg(test)]
|
||||||
|
mod real_tests {
|
||||||
|
#[cfg(test)]
|
||||||
|
fn foo() {}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bar() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
}
|
185
src/test/ui/test-attrs/test-on-not-fn.stderr
Normal file
185
src/test/ui/test-attrs/test-on-not-fn.stderr
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:3:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | mod test {}
|
||||||
|
| ----------- expected a non-associated function, found a module
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:6:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | / mod loooooooooooooong_teeeeeeeeeest {
|
||||||
|
LL | | /*
|
||||||
|
LL | | this is a comment
|
||||||
|
LL | | this comment goes on for a very long time
|
||||||
|
... |
|
||||||
|
LL | | */
|
||||||
|
LL | | }
|
||||||
|
| |_- expected a non-associated function, found a module
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:20:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | extern "C" {}
|
||||||
|
| ------------- expected a non-associated function, found an extern block
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:23:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | trait Foo {}
|
||||||
|
| ------------ expected a non-associated function, found a trait
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:26:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | impl Foo for i32 {}
|
||||||
|
| ------------------- expected a non-associated function, found an implementation
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:29:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | const FOO: i32 = -1_i32;
|
||||||
|
| ------------------------ expected a non-associated function, found a constant item
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:32:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | static BAR: u64 = 10_000_u64;
|
||||||
|
| ----------------------------- expected a non-associated function, found a static item
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:35:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | / enum MyUnit {
|
||||||
|
LL | | Unit,
|
||||||
|
LL | | }
|
||||||
|
| |_- expected a non-associated function, found an enum
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:40:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | struct NewI32(i32);
|
||||||
|
| ------------------- expected a non-associated function, found a struct
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:43:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | / union Spooky {
|
||||||
|
LL | | x: i32,
|
||||||
|
LL | | y: u32,
|
||||||
|
LL | | }
|
||||||
|
| |_- expected a non-associated function, found a union
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:50:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | #[derive(Copy, Clone, Debug)]
|
||||||
|
LL | / struct MoreAttrs {
|
||||||
|
LL | | a: i32,
|
||||||
|
LL | | b: u64,
|
||||||
|
LL | | }
|
||||||
|
| |_- expected a non-associated function, found a struct
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: the `#[test]` attribute may only be used on a non-associated function
|
||||||
|
--> $DIR/test-on-not-fn.rs:61:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
LL | foo!();
|
||||||
|
| ------- expected a non-associated function, found an item macro invocation
|
||||||
|
|
|
||||||
|
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
|
||||||
|
help: replace with conditional compilation to make the item only exist when tests are being run
|
||||||
|
|
|
||||||
|
LL | #[cfg(test)]
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 12 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue