Skip to content

Lint #[deprecated] on use items, where it has no effect - #165842

Open
johncarmack1984 wants to merge 1 commit into
rust-lang:mainfrom
johncarmack1984:deprecated-reexport-lint
Open

johncarmack1984 wants to merge 1 commit into
rust-lang:mainfrom
johncarmack1984:deprecated-reexport-lint

Conversation

@johncarmack1984

@johncarmack1984 johncarmack1984 commented Nov 12, 2026 •

Copy link
Copy Markdown

#[deprecated] on a use item is accepted and then ignored: deprecation is checked on the resolved item, not on the imports a path went through, so deprecating a re-export that way warns nobody (#30827).

This adds ineffective_deprecated_reexports, a warn-by-default lint that says so at the attribute, notes that it's a long-standing bug, and suggests what does work: deprecating the item itself, or a #[deprecated] type alias or wrapper function where one applies.

Choices made:

  • A new lint, warn-by-default. useless_deprecated is deny-by-default, and the review on Add lint rule for #[deprecated] on re-exports (rebase) #142731 asked for a warning instead of an error.
  • Emitted from the stability checker in rustc_passes, next to ineffective_unstable_reexports (lint ineffective #[unstable] annotations on re-exports #161178).
  • The help is prose, not a structured suggestion, because no single rewrite fits: a type alias doesn't carry tuple or unit struct constructors or use Alias::Variant, a function needs a wrapper, and a module or macro re-export has no equivalent.
  • core (alloc::LayoutErr) and std (collections::Bound) each carry one of these attributes. Both get an item-level #[expect], which std's deny-warnings build turns into an error once the lint stops firing there; core gets a FIXME, std already had one. The run-rustfix test in tests/ui/imports carries its expectation on the item: a crate-level one is unfulfilled in the fixed output, which deletes the annotated use.

The fix for #30827 should delete this lint.

Supersedes #142731 (I asked GrigorenkoPV there on Oct 22 whether they planned to return to it and haven't heard back). Closes #142436.

r? @WaffleLapkin

LLM disclosure: I wrote this lint. Claude Code (Fable 5.1, then Opus 5.5, both max effort) were used to evaluate design options from the issue's history for inherent virtues or flaws, after which I drafted the implementation, docs and tests, while Claude ran the test suites. Codex reviewed. Before posting, I pared and re-reviewed every line myself.

@rustbot rustbot added A-allocators Area: Custom and system allocators A-collections Area: `std::collections` (prefer A-binaryheap, A-btree, A-hashtable, A-linkedlist, A-vecdeque) labels Nov 12, 2026
@rustbot

rustbot commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator

WaffleLapkin is currently at their maximum review capacity.
They may take a while to respond.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Nov 12, 2026
@rustbot

rustbot commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the pull request, and welcome! The Rust Project has assigned @WaffleLapkin (or someone else) to review your changes, you should hear from them (or someone else) within the next two weeks.

Please see the contribution instructions and our LLM policy for more information.

@rustbot

This comment has been minimized.

Deprecation is checked on the item a path resolves to, so a
`#[deprecated]` attribute on a `use` item is accepted and never consulted
at use sites. Deprecating a re-export that way warns nobody.

Add `ineffective_deprecated_reexports`, a warn-by-default lint emitted
from the stability checker for every `use` item carrying `#[deprecated]`.
Its note says this is a long-standing bug and links the tracking issue;
its help suggests deprecating the item itself, or a `#[deprecated]` type
alias or wrapper function where one applies.

core (`alloc::LayoutErr`) and std (`collections::Bound`) each carry one
of these attributes. Both get an item-level `#[expect]`, which std's
deny-warnings build turns into an error once the lint stops firing there,
so the annotations go away with the fix for deprecating re-exports. The
run-rustfix import test carries its expectation on the item too: a
crate-level one is unfulfilled in the fixed output, which removes the
annotated `use`.
@johncarmack1984
johncarmack1984 force-pushed the deprecated-reexport-lint branch from ee5fc9e to 0c50040 Compare November 12, 2026 04:07
@theemathas

Copy link
Copy Markdown
Contributor

What exactly is the LLM involvement here? What does "I wrote this lint" entail?

@Kivooeo

Kivooeo commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

docs

Hi, first of all, all user-facing components including PR description should be written manually from start to finish; otherwise, this violates our policy. Second, you should have found a pre-arranged LLM reviewer in #llm-reviews before opening a PR.

More you can read in our LLM policy.

find_attr!(self.tcx, item.owner_id.def_id, Deprecated { span, .. } => *span)
{
self.tcx.emit_node_span_lint(
INEFFECTIVE_DEPRECATED_REEXPORTS,

@JonathanBrouwer JonathanBrouwer Nov 12, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is better implemented by making this line here Warn instead of Allow, rather than here.
That would not make it its own lint, and rather a variant of UNUSED_ATTRIBUTES, which all other invalid targets also are.

View changes since the review

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this on the PR head, and found check_target routes a misplaced deprecated to useless_deprecated unless the target is an expression, closure, statement, arm or macro call, so Warn(Target::Use) gives this, deny-by-default:

error: the `deprecated` attribute cannot be used on use statements
   = help: the `deprecated` attribute can be applied to associated consts, [...] and type aliases
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: `#[deny(useless_deprecated)]` on by default

core stops building at LayoutErr, and every crate with one of these fails the same way. It's the same error #142731's review asked not to have. Given the attribute is wanted (it just doesn't work yet), with this change the text would say the opposite of where #30827 would take it.

Adding Target::Use to that exclusion list gets unused_attributes instead, but the message still says "cannot be used" and "being phased out". Changing those would mean a deprecated-on-use special case inside the generic target checker.

A lint of its own is what #161178 did for #[unstable] on re-exports, so I went the same way to follow the precedent I could find for this kind of case. If you would rather I write it as a special case in the target checker, I'll move it there.

Comment thread compiler/rustc_lint_defs/src/builtin.rs Resolved
@JonathanBrouwer

Copy link
Copy Markdown
Member

drafted the implementation

I believe this part violates the LLM policy as well.

@JonathanBrouwer JonathanBrouwer added the llm-assisted An LLM-assisted PR as defined by the LLM policy. Requires ahead-of-time consent by assignee. label Nov 12, 2026
@johncarmack1984

johncarmack1984 commented Nov 12, 2026 •

Copy link
Copy Markdown
Author

What exactly is the LLM involvement here? What does "I wrote this lint" entail?

It means only that; I sat down in front of my code editor in mid-October and thought through the problem one character at a time until it was solved.

docs

Hi, first of all, all user-facing components including PR description should be written manually from start to finish; otherwise, this violates our policy.

The PR description and docs are my own writing. The LLM was used for correctness checks when drafting, but the prose is my own.

I address this on the Zulip thread, and I apologize that it makes things hard for reviewers, but when trying to be thorough and clear, I actually do sound a lot like an LLM. And I miss being able to use em-dashes and the word “delve”. Would be happy to give you a call on zoom/teams/FaceTime if that sounds hard to believe. I get very excited and agreeable and try to sound like everyone’s favorite Reddit commenter from 2009. It only became a problem in 2023.

Second, you should have found a pre-arranged LLM reviewer in #llm-reviews before opening a PR.

That… is fair. Oversight on my part. I can do that now.

drafted the implementation

I believe this part violates the LLM policy as well.

The LLM was used when choosing between approaches (and I know this sounds ridiculous but it’s what I did to stay in accordance with the policy): I would have the tool create implementations in a folder I refused to look at, based on instructions I gave it, and have it run tests & benchmarks to ensure given approaches would not create regressions, unexpected drawbacks, etc..

If a given approach did not have inherent flaws under this system, I would then go about hand-typing a naive implementation from the prompt I had previously given the LLM. The submitted code in this PR was hand-typed by a human without significant portions being written by an LLM.

@steffahn

steffahn commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

That… is fair. Oversight on my part. I can do that now.

To clarify the policy, I don't see you've missed anything here. As far as I can tell with your latest explanations here (thank you for those), you did not use LLMs in a way that would run into the need for pre-arranging reviewers.

@Kivooeo

Kivooeo commented Nov 12, 2026

Copy link
Copy Markdown
Member

Could you please rewrite the disclosure in the PR description to reflect the actual workflow? As it stands, some points contradict each other and are too ambiguous.

@johncarmack1984

Copy link
Copy Markdown
Author

Could you please rewrite the disclosure in the PR description to reflect the actual workflow? As it stands, some points contradict each other and are too ambiguous.

Done. I believe the new version removes the ambiguities and resolves the contradictions they created, open to feedback if it still seems otherwise.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-allocators Area: Custom and system allocators A-collections Area: `std::collections` (prefer A-binaryheap, A-btree, A-hashtable, A-linkedlist, A-vecdeque) llm-assisted An LLM-assisted PR as defined by the LLM policy. Requires ahead-of-time consent by assignee. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Warn that #[deprecated] does not work on re-exports

7 participants