Repository navigation
dead_code: Inherent associated types are unconditionally considered dead #110332
Copy link
Copy link
Open
Labels
A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.Area: Lints (warnings about flaws in source code) such as unused_mut.C-bugCategory: This is a bug.Category: This is a bug.F-inherent_associated_types`#![feature(inherent_associated_types)]``#![feature(inherent_associated_types)]`L-dead_codeLint: dead_codeLint: dead_codeL-false-positiveLint: False positive (should not have fired).Lint: False positive (should not have fired).S-blockedStatus: Blocked on something else such as an RFC or other implementation work.Status: Blocked on something else such as an RFC or other implementation work.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.This issue requires a nightly compiler in some way. When possible, use a F-* label instead.
Description
On nightly, the following code triggers dead_code even though it should not.
#![feature(inherent_associated_types)]
#![allow(incomplete_features)]
fn main() {
let _: Struct::Item = ();
}
struct Struct;
impl Struct { type Item = (); }warning: associated type `Item` is never used
--> min.rs:9:20
|
9 | impl Struct { type Item = (); }
| ----------- ^^^^
| |
| associated type in this implementation
|
= note: `#[warn(dead_code)]` on by default
warning: 1 warning emitted
Actually until recently, dead_code was never triggered at all for inherent associated types.
PR #110277 was just merged which started visiting more associated items exposing this bug.
The dead_code pass never considers IATs as live symbols (live_symbols) even in cases where they should be.
This feels like a regression but technically speaking it is not:
We switched from one extreme to the other. Thus not marking as such.
@rustbot label A-lint F-inherent_associated_types requires-nightly
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.Area: Lints (warnings about flaws in source code) such as unused_mut.C-bugCategory: This is a bug.Category: This is a bug.F-inherent_associated_types`#![feature(inherent_associated_types)]``#![feature(inherent_associated_types)]`L-dead_codeLint: dead_codeLint: dead_codeL-false-positiveLint: False positive (should not have fired).Lint: False positive (should not have fired).S-blockedStatus: Blocked on something else such as an RFC or other implementation work.Status: Blocked on something else such as an RFC or other implementation work.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.This issue requires a nightly compiler in some way. When possible, use a F-* label instead.
Type
Projects
- StatusShow more project fieldsIn Progress
Activity
[-]`dead_code` lint pass never considers inherent associated types alive[/-][+]`dead_code` pass unconditionally considers inherent associated types dead[/+][-]`dead_code` pass unconditionally considers inherent associated types dead[/-][+]`dead_code`: Inherent associated types are unconditionally considered dead[/+]Ezrashaw commentedon Apr 16, 2023
@rustbot claim
EDIT: just realized that the linked PR is mine lol 😅. I'd say it is a regression, albeit on an unstable feature.
Ezrashaw commentedon Apr 16, 2023
@fmease
Implementation is blocked on the following issue (not sure I'll be able to fix this):
Inherent associated types aren't resolving paths properly. This can be observed from the code example provided in the OP with
-Zunpretty=hir-tree:(note the
res: Err).I believe my impl of this issue is blocked on this.
fmease commentedon Apr 16, 2023
Right, I stopped investigating after noticing
Res::Err. I believe we are not writing back the resolution / typeck result for IATs. Gonna check if I can fix the latter with or withoutAliasKind::Inherent(#109410).Ezrashaw commentedon Apr 16, 2023
Ok, I have a pretty trivial fix ready for when that PR is merged.
fmease commentedon Apr 18, 2023
As a – not so happy – update, with some changes I was able to update the resolution from
Res::ErrtoRes::Def(DefKind::AssocTy, _)but that only works insideFnCtxts (used for function bodies, constants, etc.) and not insideItemCtxts (used for type aliases, struct bodies etc.), so this can't be the final solution (I added a method calledwrite_resolutionto traitAstConvwhoseFnCtxtimpl delegates toFnCtxt::write_resolutionand whoseItemCtxtimpl does nothing (!)).As far as I understand, that's not just a limitation of my implementation but a general architectural limitation: There generally isn't a meaningful
Resfor those path segments found outside of function-like bodies.handle_res(which I assume you want to modify) takes aResthat was acquired viaself.typeck_results().qpath_res(…)and the docstypeck_resultstalk about the same thing:rust/compiler/rustc_passes/src/dead.rs
Lines 63 to 70 in de96f3d
The way I understand it, this isn't a problem for trait associated types as they are unconditionally considered alive (which is also not ideal, see #66543).
There is a similar case where a path segment has
Res::Errand which doesn't involve inherent associated types:Since (trait) associated types are always alive, this works out "fine".
fmease commentedon Apr 18, 2023
I might be slightly wrong with my analysis but I think this roughly sums it. I'm gonna drop a message on Zulip later though to double-check.
As a temporary mitigation, we can consider IATs always alive, too.
Ezrashaw commentedon Apr 18, 2023
@fmease IIUC (and I don't know a lot about the compiler), it should be enough for now to only have the paths in the function body. We can then resolve it to a
DefIdand mark the inherent associated type live.For the case where the type isn't referenced from within a function, eg the following:
we can leave it as is for now, until a better solution is found.
As an aside (and this might be naive), we should never have
Res::Err, right? If we truly can't resolve a path, then we have to emit a error, else there is a correct resolution?fmease commentedon Apr 27, 2023
Sorry for the delay. I'm gonna look into the matter one more time to see what we can do about paths outside of
FnCtxts.If I don't find anything useful, I will open a PR to update the
Resof paths inFnCtxts so you can swoop in and solve half the issue. For that, personally I'd prefer to consider the assoc tys as always alive if we cannot tell for sure (less noise in the most common case).The presence of
Res::Errin legitimate paths afterhir_typeckhas run defo sounds fishy (both for IATs & for the stable example I gave above). Afaik, type-dependent paths areRes::Errafterrustc_resolvehas run and they are then updated on a case by case basis during typeck.Ezrashaw commentedon Apr 27, 2023
All good, time as much time as you need. I agree we should consider
Res::ErrIATs live if there isn't a good fix, however that should probably be looked at again before IATs are stabilized.johnDeSilencio commentedon Aug 26, 2025
Has there been any progress on this issue? As of today, IATs would be a really awesome addition to Rust that I'm hoping we can see stabilized in the near-ish future.
I've never worked on
rustcbefore, but is there anything I can do to help?fmease commentedon Aug 26, 2025
BoxyUwu is already working on this specific issue as well as on solving larger architectural blockers.
I'm not entirely sure if there's anything you could work on that would make sense to address right now. Boxy is currently working on rewriting important parts of the implementation and we probably want to wait for that work to conclude I'd say, otherwise there's a risk of doing work that gets thrown away, hard to tell for me right now