Skip to content

Commit a9bf9ea

Browse files
committed
Add UI tests for the expect attribute (RFC-2383)
* Add UI tests with macros for the `expect` attribute (RFC-2383) * Addressed review comments - mostly UI test updates (RFC-2383) * Documented lint level attribute on macro not working bug (RFC-2383) See `rust#87391`
1 parent 33a5945 commit a9bf9ea

18 files changed

+424
-4
lines changed

compiler/rustc_lint/src/expect.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@ pub fn check_expectations(tcx: TyCtxt<'_>) {
1616
&tcx.lint_levels(()).lint_expectations;
1717

1818
for (id, expectation) in lint_expectations {
19-
if fulfilled_expectations.contains(id) {
20-
continue;
19+
if !fulfilled_expectations.contains(id) {
20+
emit_unfulfilled_expectation_lint(tcx, expectation);
2121
}
22-
23-
emit_unfulfilled_expectation_lint(tcx, expectation);
2422
}
2523
}
2624

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// check-pass
2+
3+
#![feature(lint_reasons)]
4+
5+
#![warn(unused)]
6+
7+
// This expect attribute should catch all lint triggers
8+
#[expect(unused_variables)]
9+
fn check_multiple_lints_1() {
10+
let value_i = 0xff00ff;
11+
let value_ii = 0xff00ff;
12+
let value_iii = 0xff00ff;
13+
let value_iiii = 0xff00ff;
14+
let value_iiiii = 0xff00ff;
15+
}
16+
17+
// This expect attribute should catch all lint triggers
18+
#[expect(unused_mut)]
19+
fn check_multiple_lints_2() {
20+
let mut a = 0xa;
21+
let mut b = 0xb;
22+
let mut c = 0xc;
23+
println!("The ABC goes as: {:#x} {:#x} {:#x}", a, b, c);
24+
}
25+
26+
// This expect attribute should catch all lint triggers
27+
#[expect(while_true)]
28+
fn check_multiple_lints_3() {
29+
// `while_true` is an early lint
30+
while true {}
31+
32+
while true {}
33+
34+
while true {}
35+
36+
while true {}
37+
38+
while true {}
39+
}
40+
41+
fn main() {
42+
check_multiple_lints_1();
43+
check_multiple_lints_2();
44+
check_multiple_lints_3();
45+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// check-pass
2+
3+
#![feature(lint_reasons)]
4+
5+
#![warn(unused)]
6+
7+
#![expect(unused_mut)]
8+
//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
9+
//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
10+
11+
#![expect(unused_variables)]
12+
13+
fn main() {
14+
let x = 0;
15+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
warning: this lint expectation is unfulfilled
2+
--> $DIR/crate_level_expect.rs:7:1
3+
|
4+
LL | #![expect(unused_mut)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(unfulfilled_lint_expectations)]` on by default
8+
9+
warning: 1 warning emitted
10+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// check-pass
2+
3+
#![feature(lint_reasons)]
4+
5+
#![warn(unused)]
6+
7+
macro_rules! expect_inside_macro {
8+
() => {
9+
#[expect(unused_variables)]
10+
let x = 0;
11+
};
12+
}
13+
14+
fn main() {
15+
expect_inside_macro!();
16+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// check-pass
2+
3+
#![feature(lint_reasons)]
4+
5+
#![warn(unused_variables)]
6+
7+
macro_rules! trigger_unused_variables_macro {
8+
() => {
9+
let x = 0;
10+
//~^ WARNING unused variable: `x` [unused_variables]
11+
//~| WARNING unused variable: `x` [unused_variables]
12+
};
13+
}
14+
15+
pub fn check_macro() {
16+
// This should trigger the `unused_variables` from inside the macro
17+
trigger_unused_variables_macro!();
18+
}
19+
20+
// This should be fulfilled by the macro
21+
#[expect(unused_variables)]
22+
pub fn check_expect_on_item() {
23+
trigger_unused_variables_macro!();
24+
}
25+
26+
pub fn check_expect_on_macro() {
27+
// This should be fulfilled by the macro
28+
#[expect(unused_variables)]
29+
trigger_unused_variables_macro!();
30+
31+
// FIXME: Lint attributes currently don't work directly on macros, and
32+
// therefore also doesn't work for the new `expect` attribute. This bug
33+
// is being tracked in rust#87391. The test will until then produce two
34+
// warnings about the unused variable x.
35+
//
36+
// The expectation is still marked as fulfilled. I'm not totally why but
37+
// my guess is that this will remain working when rust#87391 has been fixed.
38+
}
39+
40+
fn main() {
41+
42+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
warning: unused variable: `x`
2+
--> $DIR/expect_lint_from_macro.rs:9:13
3+
|
4+
LL | let x = 0;
5+
| ^ help: if this is intentional, prefix it with an underscore: `_x`
6+
...
7+
LL | trigger_unused_variables_macro!();
8+
| --------------------------------- in this macro invocation
9+
|
10+
note: the lint level is defined here
11+
--> $DIR/expect_lint_from_macro.rs:5:9
12+
|
13+
LL | #![warn(unused_variables)]
14+
| ^^^^^^^^^^^^^^^^
15+
= note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
16+
17+
warning: unused variable: `x`
18+
--> $DIR/expect_lint_from_macro.rs:9:13
19+
|
20+
LL | let x = 0;
21+
| ^ help: if this is intentional, prefix it with an underscore: `_x`
22+
...
23+
LL | trigger_unused_variables_macro!();
24+
| --------------------------------- in this macro invocation
25+
|
26+
= note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
27+
28+
warning: 2 warnings emitted
29+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// should error due to missing feature gate.
2+
3+
#![warn(unused)]
4+
5+
#[expect(unused)]
6+
//~^ ERROR: the `#[expect]` attribute is an experimental feature [E0658]
7+
fn main() {
8+
let x = 1;
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: the `#[expect]` attribute is an experimental feature
2+
--> $DIR/expect_missing_feature_gate.rs:5:1
3+
|
4+
LL | #[expect(unused)]
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #54503 <https://github.com/rust-lang/rust/issues/54503> for more information
8+
= help: add `#![feature(lint_reasons)]` to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// check-pass
2+
3+
#![feature(lint_reasons)]
4+
5+
#![warn(unused)]
6+
7+
#[expect(unused_variables, unused_mut, while_true)]
8+
fn check_multiple_lints_1() {
9+
// This only trigger `unused_variables`
10+
let who_am_i = 666;
11+
}
12+
13+
#[expect(unused_variables, unused_mut, while_true)]
14+
fn check_multiple_lints_2() {
15+
// This only triggers `unused_mut`
16+
let mut x = 0;
17+
println!("I use x: {}", x);
18+
}
19+
20+
21+
#[expect(unused_variables, unused_mut, while_true)]
22+
fn check_multiple_lints_3() {
23+
// This only triggers `while_true` which is also an early lint
24+
while true {}
25+
}
26+
27+
fn main() {
28+
check_multiple_lints_1();
29+
check_multiple_lints_2();
30+
check_multiple_lints_3();
31+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// check-pass
2+
// ignore-tidy-linelength
3+
4+
#![feature(lint_reasons)]
5+
#![warn(unused_mut)]
6+
7+
#[expect(
8+
unused_mut,
9+
reason = "this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered"
10+
)]
11+
//~^^^^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
12+
//~| NOTE this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered
13+
mod foo {
14+
fn bar() {
15+
#[allow(
16+
unused_mut,
17+
reason = "this overrides the previous `expect` lint level and allows the `unused_mut` lint here"
18+
)]
19+
let mut v = 0;
20+
}
21+
}
22+
23+
#[expect(
24+
unused_mut,
25+
reason = "this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered"
26+
)]
27+
//~^^^^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
28+
//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
29+
//~| NOTE this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered
30+
mod oof {
31+
#[warn(
32+
unused_mut,
33+
//~^ NOTE the lint level is defined here
34+
reason = "this overrides the previous `expect` lint level and warns about the `unused_mut` lint here"
35+
)]
36+
fn bar() {
37+
let mut v = 0;
38+
//~^ WARNING variable does not need to be mutable [unused_mut]
39+
//~| NOTE this overrides the previous `expect` lint level and warns about the `unused_mut` lint here
40+
}
41+
}
42+
43+
fn main() {}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
warning: variable does not need to be mutable
2+
--> $DIR/expect_nested_lint_levels.rs:37:13
3+
|
4+
LL | let mut v = 0;
5+
| ----^
6+
| |
7+
| help: remove this `mut`
8+
|
9+
= note: this overrides the previous `expect` lint level and warns about the `unused_mut` lint here
10+
note: the lint level is defined here
11+
--> $DIR/expect_nested_lint_levels.rs:32:9
12+
|
13+
LL | unused_mut,
14+
| ^^^^^^^^^^
15+
16+
warning: this lint expectation is unfulfilled
17+
--> $DIR/expect_nested_lint_levels.rs:23:1
18+
|
19+
LL | / #[expect(
20+
LL | | unused_mut,
21+
LL | | reason = "this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered"
22+
LL | | )]
23+
| |__^
24+
|
25+
= note: `#[warn(unfulfilled_lint_expectations)]` on by default
26+
= note: this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered
27+
28+
warning: this lint expectation is unfulfilled
29+
--> $DIR/expect_nested_lint_levels.rs:7:1
30+
|
31+
LL | / #[expect(
32+
LL | | unused_mut,
33+
LL | | reason = "this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered"
34+
LL | | )]
35+
| |__^
36+
|
37+
= note: this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered
38+
39+
warning: 3 warnings emitted
40+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// check-pass
2+
3+
#![feature(lint_reasons)]
4+
#![warn(unused)]
5+
6+
#![expect(unused_variables, reason = "<This should fail and display this reason>")]
7+
//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
8+
//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
9+
//~| NOTE <This should fail and display this reason>
10+
11+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: this lint expectation is unfulfilled
2+
--> $DIR/expect_with_reason.rs:6:1
3+
|
4+
LL | #![expect(unused_variables, reason = "<This should fail and display this reason>")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(unfulfilled_lint_expectations)]` on by default
8+
= note: <This should fail and display this reason>
9+
10+
warning: 1 warning emitted
11+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// check-pass
2+
3+
#![feature(lint_reasons)]
4+
5+
fn expect_early_pass_lints() {
6+
#[expect(while_true)]
7+
while true {
8+
println!("I never stop")
9+
}
10+
11+
#[expect(unused_doc_comments)]
12+
/// This comment triggers the `unused_doc_comments` lint
13+
let _sheep = "wolf";
14+
15+
let x = 123;
16+
#[expect(ellipsis_inclusive_range_patterns)]
17+
match x {
18+
0...100 => {}
19+
_ => {}
20+
}
21+
}
22+
23+
fn main() {}

0 commit comments

Comments
 (0)