You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
unfulfilled_lint_expectations false-positive for unused struct field inside unused struct #160942
// This struct is only used on windows.#[cfg_attr(not(target_os = "windows"), expect(unused))]structFoo{// This field is never used regardless of whether on windows or other.#[expect(unused)]x:u32,}
Current output
On linux:
warning: this lint expectation is unfulfilled
--> src/lib.rs:5:14
|
5 |#[expect(unused)]| ^^^^^^
|
= note: `#[warn(unfulfilled_lint_expectations)]` on by default
Desired output
No warning.
Rationale and extra context
In this example, we have a struct Foo that may or may not be used, depending on the platform. So we conditionally set it to expect(unused).
We also have a field x that is never used, regardless of the platform. So we always set it to expect(unused).
It seems that when we have an expect(unused) field inside an expect(unused) struct, rust will warn that the field's lint expectation is unfulfilled. But this seems wrong because the field is always unused.
We could instead use #[cfg_attr(target_os = "windows", expect(unused))] on the field to avoid the warning, but this seems unnecessary and overly verbose, and it's easy for the two "cfg_attr" conditions to become out-of-sync.
Rust Version
This is in the playground, where:
Build using the Nightly version: 1.99.0-nightly (2026-08-10 12c36e2539c54397c51d)
From what I understand, if dead_code lint fires on the struct itself (e.g., struct Foo is never constructed, in your example this is suppressed by expect(unused) at line 1), it won't further fire on all its fields one-by-one. Thus, adding a #[expect(unused)] on the struct's field triggers unfulfilled_lint_expectations lint.
If you change struct Foo to pub struct Foo, then you can see dead_code lint fire on field x, because now Foo is reachable from outside world and we cannot treat it as dead code. In that case, fields of Foo would be checked individually.
Current behavior seems reasonable to me, I am not sure if there is something really need to be fixed here.
Current behavior seems reasonable to me, I am not sure if there is something really need to be fixed here.
Yeah I guess this makes sense from a technical viewpoint if you know how the unfulfilled_lint_expectations lint works. It does mean that expect(unused) is a bit of a footgun if you don't though. For example adding #![allow(unused)] to the lib.rs will break all instances of #[expect(unused)] on struct fields for non-public structs in the crate. (Edit: This was a bad example.) So I guess then that expect(unused) isn't the right tool for enforcing that something in the code isn't used, which is maybe a bit unexpected.
I see there's discussion in #161005 but I'll post here so I don't sidetrack it.
While I do think it would be nice if the original example worked, I also think that if the proposed behaviour isn't the intended behaviour, then just improving the error message would be useful. The compiler does a good job at explaining confusing/unexpected behaviour, and I think this is a case where a better error (well, warning) message could make the intent of expect clearer. Some sort of message that the expect(unused) can never be satisfied for fields when the struct itself is unused. But I'm sure this is easier said than done.
Activity
dronavallipranav commentedon Aug 12, 2026
@rustbot claim
gonna try to take a look at this as a first real issue
cclfmht commentedon Aug 13, 2026
From what I understand, if
dead_codelint fires on the struct itself (e.g., structFoois never constructed, in your example this is suppressed byexpect(unused)at line 1), it won't further fire on all its fields one-by-one. Thus, adding a#[expect(unused)]on the struct's field triggersunfulfilled_lint_expectationslint.If you change
struct Footopub struct Foo, then you can seedead_codelint fire on fieldx, because nowFoois reachable from outside world and we cannot treat it as dead code. In that case, fields ofFoowould be checked individually.Current behavior seems reasonable to me, I am not sure if there is something really need to be fixed here.
tor-proto: 'expect' -> 'allow' in `CircReactorHandle`
opara-tor commentedon Aug 13, 2026
Yeah I guess this makes sense from a technical viewpoint if you know how the
unfulfilled_lint_expectationslint works. It does mean thatexpect(unused)is a bit of a footgun if you don't though.For example adding(Edit: This was a bad example.) So I guess then that#![allow(unused)]to thelib.rswill break all instances of#[expect(unused)]on struct fields for non-public structs in the crate.expect(unused)isn't the right tool for enforcing that something in the code isn't used, which is maybe a bit unexpected.opara-tor commentedon Aug 25, 2026
I see there's discussion in #161005 but I'll post here so I don't sidetrack it.
While I do think it would be nice if the original example worked, I also think that if the proposed behaviour isn't the intended behaviour, then just improving the error message would be useful. The compiler does a good job at explaining confusing/unexpected behaviour, and I think this is a case where a better error (well, warning) message could make the intent of
expectclearer. Some sort of message that theexpect(unused)can never be satisfied for fields when the struct itself is unused. But I'm sure this is easier said than done.Rollup merge of rust-lang#161005 - dronavallipranav:fix-nested-dead-c…
Rollup merge of rust-lang#161005 - dronavallipranav:fix-nested-dead-c…
Rollup merge of rust-lang#161005 - dronavallipranav:fix-nested-dead-c…
Rollup merge of rust-lang#161005 - dronavallipranav:fix-nested-dead-c…
Rollup merge of rust-lang#161005 - dronavallipranav:fix-nested-dead-c…
Rollup merge of rust-lang#161005 - dronavallipranav:fix-nested-dead-c…
Unrolled build for #161005 in rollup 162989
Rollup merge of #161005 - dronavallipranav:fix-nested-dead-code-expec…
Rollup merge of #161005 - dronavallipranav:fix-nested-dead-code-expec…