Skip to content

Commit c23f6fe

Browse files
committed
Auto merge of #158943 - Albab-Hasan:expect-derive-cfg-experiment, r=<try>
fulfill `#[expect]` expectations from derive generated code
2 parents b69e089 + 2a300cf commit c23f6fe

11 files changed

Lines changed: 435 additions & 184 deletions

compiler/rustc_lint/src/levels.rs

Lines changed: 272 additions & 166 deletions
Large diffs are not rendered by default.

tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-2.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// Make sure that the copied `#[expect]` attr in the derived code does not trigger an unfulfilled
2-
// expectation as it's linked to the original one which is fulfilled.
1+
// Make sure that sharing the `#[expect]` attr with the derived code does not trigger an
2+
// unfulfilled expectation there when the expectation is fulfilled at the original item.
33
//
44
// See <https://github.com/rust-lang/rust/issues/150553#issuecomment-3780810363> for rational.
55

tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-3.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
// FIXME: Bring back duplication of the `#[expect]` attribute when deriving.
2-
//
3-
// Make sure we produce the unfulfilled expectation lint if neither the struct or the
4-
// derived code fulfilled it.
1+
// Make sure we produce the unfulfilled expectation lint exactly once if neither the
2+
// struct nor the derived code fulfilled it: one written attribute is one expectation,
3+
// no matter how many impls are derived from the item.
54

65
//@ check-pass
76

87
#[expect(unexpected_cfgs)]
98
//~^ WARN this lint expectation is unfulfilled
10-
//FIXME ~^^ WARN this lint expectation is unfulfilled
119
#[derive(Debug)]
1210
pub struct MyStruct {
1311
pub t_ref: i64,

tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-3.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: this lint expectation is unfulfilled
2-
--> $DIR/derive-expect-issue-150553-3.rs:8:10
2+
--> $DIR/derive-expect-issue-150553-3.rs:7:10
33
|
44
LL | #[expect(unexpected_cfgs)]
55
| ^^^^^^^^^^^^^^^
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// An `#[expect]` on an item is shared with the impls derived from it, but not with
2+
// hand-written impls for the same type: lints there must still fire.
3+
4+
#![deny(redundant_lifetimes)]
5+
6+
#[derive(Clone)]
7+
#[expect(redundant_lifetimes)]
8+
pub struct W<'a>
9+
where
10+
'a: 'static,
11+
{
12+
pub r: &'a u8,
13+
}
14+
15+
impl<'a> W<'a>
16+
//~^ ERROR unnecessary lifetime parameter `'a`
17+
where
18+
'a: 'static,
19+
{
20+
pub fn get(&self) -> &'a u8 {
21+
self.r
22+
}
23+
}
24+
25+
fn main() {}

tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553.stderr renamed to tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-5.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
error: unnecessary lifetime parameter `'a`
2-
--> $DIR/derive-expect-issue-150553.rs:16:23
2+
--> $DIR/derive-expect-issue-150553-5.rs:15:6
33
|
4-
LL | pub struct RefWrapper<'a, T>
5-
| ^^
4+
LL | impl<'a> W<'a>
5+
| ^^
66
|
77
= note: you can use the `'static` lifetime directly, in place of `'a`
88
note: the lint level is defined here
9-
--> $DIR/derive-expect-issue-150553.rs:10:9
9+
--> $DIR/derive-expect-issue-150553-5.rs:4:9
1010
|
1111
LL | #![deny(redundant_lifetimes)]
1212
| ^^^^^^^^^^^^^^^^^^^
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// The `#[expect]` sharing with derived code must survive `#[cfg]`/`#[cfg_attr]`
2+
// processing of the derive input: the attribute-id duplication this caused is why
3+
// #152289 (copying the attribute to the derived impl) was reverted in #153055.
4+
// One written attribute is one expectation, fulfilled by the item or its derived
5+
// code, and reported exactly once when genuinely unfulfilled.
6+
7+
//@ check-pass
8+
9+
#![deny(redundant_lifetimes)]
10+
11+
use std::fmt::Debug;
12+
13+
#[derive(Debug)]
14+
#[expect(redundant_lifetimes)]
15+
pub struct CfgField<'a, T: Debug>
16+
where
17+
'a: 'static,
18+
{
19+
pub t_ref: &'a T,
20+
#[cfg(false)]
21+
pub gone: u8,
22+
}
23+
24+
#[derive(Debug)]
25+
#[cfg_attr(all(), expect(redundant_lifetimes))]
26+
pub struct CfgAttrExpect<'a, T: Debug>
27+
where
28+
'a: 'static,
29+
{
30+
pub t_ref: &'a T,
31+
#[cfg(false)]
32+
pub gone: u8,
33+
}
34+
35+
#[derive(Debug)]
36+
#[expect(unexpected_cfgs)]
37+
//~^ WARN this lint expectation is unfulfilled
38+
pub struct Unfulfilled {
39+
pub x: i64,
40+
#[cfg(false)]
41+
pub gone: u8,
42+
}
43+
44+
fn main() {}
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/derive-expect-issue-150553-6.rs:36:10
3+
|
4+
LL | #[expect(unexpected_cfgs)]
5+
| ^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(unfulfilled_lint_expectations)]` on by default
8+
9+
warning: 1 warning emitted
10+
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// The `#[expect]` sharing with derive-generated code also applies when the
2+
// derive itself is expanded from a macros 2.0 macro: the derive expansion is
3+
// the innermost one, so the expansion-kind gate recognizes the impl no matter
4+
// what macro produced the derived item. A genuinely unfulfilled expectation
5+
// is still reported exactly once.
6+
7+
//@ check-pass
8+
9+
#![feature(decl_macro)]
10+
#![deny(redundant_lifetimes)]
11+
12+
use std::fmt::Debug;
13+
14+
macro fulfilled() {
15+
#[derive(Debug)]
16+
#[expect(redundant_lifetimes)]
17+
pub struct RefWrapper<'a, T>
18+
where
19+
'a: 'static,
20+
T: Debug,
21+
{
22+
pub t_ref: &'a T,
23+
}
24+
}
25+
26+
fulfilled!();
27+
28+
macro passthrough($i:item) {
29+
$i
30+
}
31+
32+
passthrough! {
33+
#[derive(Debug)]
34+
#[expect(redundant_lifetimes)]
35+
pub struct RefWrapperPassthrough<'a, T>
36+
where
37+
'a: 'static,
38+
T: Debug,
39+
{
40+
pub t_ref: &'a T,
41+
}
42+
}
43+
44+
macro unfulfilled() {
45+
#[derive(Debug)]
46+
#[expect(unexpected_cfgs)]
47+
//~^ WARN this lint expectation is unfulfilled
48+
pub struct Unfulfilled {
49+
pub x: i64,
50+
#[cfg(false)]
51+
pub gone: u8,
52+
}
53+
}
54+
55+
unfulfilled!();
56+
57+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
warning: this lint expectation is unfulfilled
2+
--> $DIR/derive-expect-issue-150553-7.rs:46:14
3+
|
4+
LL | #[expect(unexpected_cfgs)]
5+
| ^^^^^^^^^^^^^^^
6+
...
7+
LL | unfulfilled!();
8+
| -------------- in this macro invocation
9+
|
10+
= note: `#[warn(unfulfilled_lint_expectations)]` on by default
11+
= note: this warning originates in the macro `unfulfilled` (in Nightly builds, run with -Z macro-backtrace for more info)
12+
13+
warning: 1 warning emitted
14+

0 commit comments

Comments
 (0)