Skip to content

hir-ty: walk container exprs for unused_must_use#22405

Open
MavenRain wants to merge 2 commits into
rust-lang:masterfrom
MavenRain:feat-must-use-container-exprs
Open

hir-ty: walk container exprs for unused_must_use#22405
MavenRain wants to merge 2 commits into
rust-lang:masterfrom
MavenRain:feat-must-use-container-exprs

Conversation

@MavenRain
Copy link
Copy Markdown
Contributor

ExprValidator::check_unused_must_use previously matched only Expr::Call and Expr::MethodCall directly on the expression of a Statement::Expr with semicolon. This left several stmt-with-semi cases unwarned: blocks whose tail is a #[must_use] call ({ produces() };), unsafe-blocks (unsafe { produces() };), if/else arms, match arms, and const blocks.

Refactors check_unused_must_use into a recursive collector that walks into Expr::Block { tail, .. }, Expr::Unsafe { tail, .. }, Expr::If { then_branch, else_branch, .. }, Expr::Match { arms, .. }, and Expr::Const(inner) before applying the existing leaf check (callee or method #[must_use] attribute, or #[must_use] ADT return type). The diagnostic stays at the leaf call so the span points to the actual must_use producer rather than the wrapping block.

Adds ide-diagnostics tests covering each new container case (block tail, unsafe block tail, nested blocks, if/else branches, match arms, const block, #[must_use] ADT through a block) and lock-in tests confirming that the existing RustcLint plumbing already honors #[allow(unused_must_use)], #[allow(unused)], and #[deny(unused_must_use)] attribute resolution.

Follow-up to #22239.

ExprValidator::check_unused_must_use previously matched only Expr::Call
and Expr::MethodCall directly on the expression of a Statement::Expr
with semicolon.  This left several stmt-with-semi cases unwarned:
blocks whose tail is a #[must_use] call (`{ produces() };`),
unsafe-blocks (`unsafe { produces() };`), if/else arms, match arms,
and const blocks.

Refactors check_unused_must_use into a recursive collector that walks
into Expr::Block { tail, .. }, Expr::Unsafe { tail, .. },
Expr::If { then_branch, else_branch, .. }, Expr::Match { arms, .. },
and Expr::Const(inner) before applying the existing leaf check (callee
or method #[must_use] attribute, or #[must_use] ADT return type).
The diagnostic stays at the leaf call so the span points to the actual
must_use producer rather than the wrapping block.

Adds ide-diagnostics tests covering each new container case (block
tail, unsafe block tail, nested blocks, if/else branches, match arms,
const block, #[must_use] ADT through a block) and lock-in tests
confirming that the existing RustcLint plumbing already honors
#[allow(unused_must_use)], #[allow(unused)], and
#[deny(unused_must_use)] attribute resolution.

Follow-up to rust-lang#22239.

Signed-off-by: Onyeka Obi <softwareengineerasaservant@isurvivable.cv>
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 19, 2026
Comment thread crates/hir-ty/src/diagnostics/expr.rs Outdated
fn collect_unused_must_use(
&self,
expr: ExprId,
diags: &mut Vec<BodyValidationDiagnostic<'db>>,
Copy link
Copy Markdown
Contributor

@ChayimFriedman2 ChayimFriedman2 May 19, 2026

Choose a reason for hiding this comment

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

You can just push to self.diagnostics.

View changes since the review

Comment thread crates/hir-ty/src/diagnostics/expr.rs Outdated
// Walk through container expressions so that the value-producing leaf is
// checked even when wrapped in a block, `unsafe { .. }`, `if`/`match`, or
// a `const { .. }` block.
match &self.body[expr] {
Copy link
Copy Markdown
Contributor

@ChayimFriedman2 ChayimFriedman2 May 19, 2026

Choose a reason for hiding this comment

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

Or better, there is no need for a recursion here, given a block has up to one tail expression. Instead loop until you reach it.

View changes since the review

MavenRain added a commit to MavenRain/rust-analyzer that referenced this pull request May 20, 2026
  Address ChayimFriedman2 review feedback on rust-lang#22405:

  * Push directly to self.diagnostics rather than threading a
    &mut Vec parameter through the recursion.  Drops the
    check_unused_must_use / collect_unused_must_use split and the
    allocation in the thin wrapper.

  * Replace the recursive single-tail-chain walk (Block/Unsafe/Const)
    with a loop that reassigns expr until reaching a non-chain leaf.
    Branching containers (If/Match) still recurse since they have
    multiple arms.

  The borrow checker required hoisting the Statement::Expr pass
  out of the main loop in validate_block, since MatchCheckCtx
  holds &self.infcx and the must_use pass now needs &mut self.
  The two passes are independent (must_use on expression
  statements, non_exhaustive_let on let statements) so order is
  free.

  19 unused_must_use tests + 981 hir-ty tests + 693
  ide-diagnostics tests pass.

Signed-off-by: Onyeka Obi <softwareengineerasaservant@isurvivable.cv>
@rustbot

This comment has been minimized.

    Address ChayimFriedman2 review feedback on rust-lang#22405:

    * Push directly to self.diagnostics rather than threading a
      &mut Vec parameter through the recursion.  Drops the
      check_unused_must_use / collect_unused_must_use split and the
      allocation in the thin wrapper.

    * Replace the recursive single-tail-chain walk (Block/Unsafe/Const)
      with a loop that reassigns expr until reaching a non-chain leaf.
      Branching containers (If/Match) still recurse since they have
      multiple arms.

    The borrow checker required hoisting the Statement::Expr pass
    out of the main loop in validate_block, since MatchCheckCtx
    holds &self.infcx and the must_use pass now needs &mut self.
    The two passes are independent (must_use on expression
    statements, non_exhaustive_let on let statements) so order is
    free.

    19 unused_must_use tests + 981 hir-ty tests + 693
    ide-diagnostics tests pass.

Signed-off-by: Onyeka Obi <softwareengineerasaservant@isurvivable.cv>
@MavenRain MavenRain force-pushed the feat-must-use-container-exprs branch from 2db699b to ffe5641 Compare May 21, 2026 09:42
@MavenRain MavenRain requested a review from ChayimFriedman2 May 21, 2026 09:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants