Skip to content

Commit 659382f

Browse files
authored
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)] | ~~~~~~~~~~~~ ```
2 parents e3ded4f + 6d05e2a commit 659382f

File tree

7 files changed

+281
-41
lines changed

7 files changed

+281
-41
lines changed

compiler/rustc_builtin_macros/src/test.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_ast as ast;
66
use rustc_ast::attr;
77
use rustc_ast::ptr::P;
88
use rustc_ast_pretty::pprust;
9+
use rustc_errors::Applicability;
910
use rustc_expand::base::*;
1011
use rustc_session::Session;
1112
use rustc_span::symbol::{sym, Ident, Symbol};
@@ -102,11 +103,20 @@ pub fn expand_test_or_bench(
102103
}
103104
};
104105

105-
if let ast::ItemKind::MacCall(_) = item.kind {
106-
cx.sess.parse_sess.span_diagnostic.span_warn(
107-
item.span,
108-
"`#[test]` attribute should not be used on macros. Use `#[cfg(test)]` instead.",
109-
);
106+
// Note: non-associated fn items are already handled by `expand_test_or_bench`
107+
if !matches!(item.kind, ast::ItemKind::Fn(_)) {
108+
cx.sess
109+
.parse_sess
110+
.span_diagnostic
111+
.struct_span_err(
112+
attr_sp,
113+
"the `#[test]` attribute may only be used on a non-associated function",
114+
)
115+
.note("the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions")
116+
.span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr()))
117+
.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)
118+
.emit();
119+
110120
return vec![Annotatable::Item(item)];
111121
}
112122

@@ -466,7 +476,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
466476
(false, _) => true,
467477
}
468478
} else {
469-
sd.span_err(i.span, "only functions may be used as tests");
479+
// should be unreachable because `is_test_fn_item` should catch all non-fn items
470480
false
471481
}
472482
}

src/test/ui/issues/issue-14772.rs

-6
This file was deleted.

src/test/ui/issues/issue-14772.stderr

-8
This file was deleted.

src/test/ui/test-attrs/test-on-macro.rs

-13
This file was deleted.

src/test/ui/test-attrs/test-on-macro.stderr

-8
This file was deleted.
+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// compile-flags: --test
2+
3+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
4+
mod test {}
5+
6+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
7+
mod loooooooooooooong_teeeeeeeeeest {
8+
/*
9+
this is a comment
10+
this comment goes on for a very long time
11+
this is to pad out the span for this module for a long time
12+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
13+
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
14+
laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
15+
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
16+
non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
17+
*/
18+
}
19+
20+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
21+
extern "C" {}
22+
23+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
24+
trait Foo {}
25+
26+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
27+
impl Foo for i32 {}
28+
29+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
30+
const FOO: i32 = -1_i32;
31+
32+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
33+
static BAR: u64 = 10_000_u64;
34+
35+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
36+
enum MyUnit {
37+
Unit,
38+
}
39+
40+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
41+
struct NewI32(i32);
42+
43+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
44+
union Spooky {
45+
x: i32,
46+
y: u32,
47+
}
48+
49+
#[repr(C, align(64))]
50+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
51+
#[derive(Copy, Clone, Debug)]
52+
struct MoreAttrs {
53+
a: i32,
54+
b: u64,
55+
}
56+
57+
macro_rules! foo {
58+
() => {};
59+
}
60+
61+
#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
62+
foo!();
63+
64+
// make sure it doesn't erroneously trigger on a real test
65+
#[test]
66+
fn real_test() {
67+
assert_eq!(42_i32, 42_i32);
68+
}
69+
70+
// make sure it works with cfg test
71+
#[cfg(test)]
72+
mod real_tests {
73+
#[cfg(test)]
74+
fn foo() {}
75+
76+
#[test]
77+
fn bar() {
78+
foo();
79+
}
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
error: the `#[test]` attribute may only be used on a non-associated function
2+
--> $DIR/test-on-not-fn.rs:3:1
3+
|
4+
LL | #[test]
5+
| ^^^^^^^
6+
LL | mod test {}
7+
| ----------- expected a non-associated function, found a module
8+
|
9+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
10+
help: replace with conditional compilation to make the item only exist when tests are being run
11+
|
12+
LL | #[cfg(test)]
13+
| ~~~~~~~~~~~~
14+
15+
error: the `#[test]` attribute may only be used on a non-associated function
16+
--> $DIR/test-on-not-fn.rs:6:1
17+
|
18+
LL | #[test]
19+
| ^^^^^^^
20+
LL | / mod loooooooooooooong_teeeeeeeeeest {
21+
LL | | /*
22+
LL | | this is a comment
23+
LL | | this comment goes on for a very long time
24+
... |
25+
LL | | */
26+
LL | | }
27+
| |_- expected a non-associated function, found a module
28+
|
29+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
30+
help: replace with conditional compilation to make the item only exist when tests are being run
31+
|
32+
LL | #[cfg(test)]
33+
| ~~~~~~~~~~~~
34+
35+
error: the `#[test]` attribute may only be used on a non-associated function
36+
--> $DIR/test-on-not-fn.rs:20:1
37+
|
38+
LL | #[test]
39+
| ^^^^^^^
40+
LL | extern "C" {}
41+
| ------------- expected a non-associated function, found an extern block
42+
|
43+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
44+
help: replace with conditional compilation to make the item only exist when tests are being run
45+
|
46+
LL | #[cfg(test)]
47+
| ~~~~~~~~~~~~
48+
49+
error: the `#[test]` attribute may only be used on a non-associated function
50+
--> $DIR/test-on-not-fn.rs:23:1
51+
|
52+
LL | #[test]
53+
| ^^^^^^^
54+
LL | trait Foo {}
55+
| ------------ expected a non-associated function, found a trait
56+
|
57+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
58+
help: replace with conditional compilation to make the item only exist when tests are being run
59+
|
60+
LL | #[cfg(test)]
61+
| ~~~~~~~~~~~~
62+
63+
error: the `#[test]` attribute may only be used on a non-associated function
64+
--> $DIR/test-on-not-fn.rs:26:1
65+
|
66+
LL | #[test]
67+
| ^^^^^^^
68+
LL | impl Foo for i32 {}
69+
| ------------------- expected a non-associated function, found an implementation
70+
|
71+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
72+
help: replace with conditional compilation to make the item only exist when tests are being run
73+
|
74+
LL | #[cfg(test)]
75+
| ~~~~~~~~~~~~
76+
77+
error: the `#[test]` attribute may only be used on a non-associated function
78+
--> $DIR/test-on-not-fn.rs:29:1
79+
|
80+
LL | #[test]
81+
| ^^^^^^^
82+
LL | const FOO: i32 = -1_i32;
83+
| ------------------------ expected a non-associated function, found a constant item
84+
|
85+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
86+
help: replace with conditional compilation to make the item only exist when tests are being run
87+
|
88+
LL | #[cfg(test)]
89+
| ~~~~~~~~~~~~
90+
91+
error: the `#[test]` attribute may only be used on a non-associated function
92+
--> $DIR/test-on-not-fn.rs:32:1
93+
|
94+
LL | #[test]
95+
| ^^^^^^^
96+
LL | static BAR: u64 = 10_000_u64;
97+
| ----------------------------- expected a non-associated function, found a static item
98+
|
99+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
100+
help: replace with conditional compilation to make the item only exist when tests are being run
101+
|
102+
LL | #[cfg(test)]
103+
| ~~~~~~~~~~~~
104+
105+
error: the `#[test]` attribute may only be used on a non-associated function
106+
--> $DIR/test-on-not-fn.rs:35:1
107+
|
108+
LL | #[test]
109+
| ^^^^^^^
110+
LL | / enum MyUnit {
111+
LL | | Unit,
112+
LL | | }
113+
| |_- expected a non-associated function, found an enum
114+
|
115+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
116+
help: replace with conditional compilation to make the item only exist when tests are being run
117+
|
118+
LL | #[cfg(test)]
119+
| ~~~~~~~~~~~~
120+
121+
error: the `#[test]` attribute may only be used on a non-associated function
122+
--> $DIR/test-on-not-fn.rs:40:1
123+
|
124+
LL | #[test]
125+
| ^^^^^^^
126+
LL | struct NewI32(i32);
127+
| ------------------- expected a non-associated function, found a struct
128+
|
129+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
130+
help: replace with conditional compilation to make the item only exist when tests are being run
131+
|
132+
LL | #[cfg(test)]
133+
| ~~~~~~~~~~~~
134+
135+
error: the `#[test]` attribute may only be used on a non-associated function
136+
--> $DIR/test-on-not-fn.rs:43:1
137+
|
138+
LL | #[test]
139+
| ^^^^^^^
140+
LL | / union Spooky {
141+
LL | | x: i32,
142+
LL | | y: u32,
143+
LL | | }
144+
| |_- expected a non-associated function, found a union
145+
|
146+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
147+
help: replace with conditional compilation to make the item only exist when tests are being run
148+
|
149+
LL | #[cfg(test)]
150+
| ~~~~~~~~~~~~
151+
152+
error: the `#[test]` attribute may only be used on a non-associated function
153+
--> $DIR/test-on-not-fn.rs:50:1
154+
|
155+
LL | #[test]
156+
| ^^^^^^^
157+
LL | #[derive(Copy, Clone, Debug)]
158+
LL | / struct MoreAttrs {
159+
LL | | a: i32,
160+
LL | | b: u64,
161+
LL | | }
162+
| |_- expected a non-associated function, found a struct
163+
|
164+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
165+
help: replace with conditional compilation to make the item only exist when tests are being run
166+
|
167+
LL | #[cfg(test)]
168+
| ~~~~~~~~~~~~
169+
170+
error: the `#[test]` attribute may only be used on a non-associated function
171+
--> $DIR/test-on-not-fn.rs:61:1
172+
|
173+
LL | #[test]
174+
| ^^^^^^^
175+
LL | foo!();
176+
| ------- expected a non-associated function, found an item macro invocation
177+
|
178+
= note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
179+
help: replace with conditional compilation to make the item only exist when tests are being run
180+
|
181+
LL | #[cfg(test)]
182+
| ~~~~~~~~~~~~
183+
184+
error: aborting due to 12 previous errors
185+

0 commit comments

Comments
 (0)