Skip to content

Add off-by-default rule for unused call results#3906

Open
nitishagar wants to merge 1 commit into
facebook:mainfrom
nitishagar:nitishagar/issue-3719-unused-call-result
Open

Add off-by-default rule for unused call results#3906
nitishagar wants to merge 1 commit into
facebook:mainfrom
nitishagar:nitishagar/issue-3719-unused-call-result

Conversation

@nitishagar

Copy link
Copy Markdown
Contributor

Introduce an unused-call-result diagnostic that fires when a bare
expression statement is a function/method call whose result is discarded
and the result type is informative (not None, Any, or Never).

The check sits in binding_to_type_stmt_expr as an else if branch
after the existing unused-coroutine check, so the two diagnostics
are mutually exclusive: a discarded coroutine call still emits only
unused-coroutine. The guard matches!(e, Expr::Call(_)) ensures
assignments, bare names, comparisons, and similar non-call statements
are not flagged. Results of type Any or that extend Any are also
exempted, consistent with the coroutine rule. The rule defaults to
Severity::Ignore and must be explicitly enabled.

A new test file covers every spec boundary: the golden-path discard,
assigned/None/Any/Never/extends-Any exemptions, method and constructor
calls, non-call bare statements, the R5 coroutine mutual-exclusion case
(rule ON + coroutine discard → exactly one unused-coroutine error),
and the default-off regression.

Fixes #3719

Test Plan:

  • cargo test -p pyrefly_config test_doc_headers test_doc_severities
  • cargo test -p pyrefly --lib unused_call_result
  • cargo test -p pyrefly --lib simple::test_unused_coroutine
  • python3 test.py --no-test --no-conformance --no-jsonschema
@meta-cla meta-cla Bot added the cla signed label Jun 23, 2026
@nitishagar nitishagar force-pushed the nitishagar/issue-3719-unused-call-result branch from 38bfcf8 to ca5efe3 Compare June 25, 2026 09:19
@github-actions github-actions Bot added size/l and removed size/l labels Jun 25, 2026
Introduce an `unused-call-result` diagnostic that fires when a bare
expression statement is a function/method call whose result is discarded
and the result type is informative (not `None`, `Any`, or `Never`).

The check sits in `binding_to_type_stmt_expr` as an `else if` branch
after the existing `unused-coroutine` check, so the two diagnostics
are mutually exclusive: a discarded coroutine call still emits only
`unused-coroutine`. The guard `matches!(e, Expr::Call(_))` ensures
assignments, bare names, comparisons, and similar non-call statements
are not flagged. Results of type `Any` or that extend `Any` are also
exempted, consistent with the coroutine rule. The rule defaults to
`Severity::Ignore` and must be explicitly enabled.

A new test file covers every spec boundary: the golden-path discard,
assigned/None/Any/Never/extends-Any exemptions, method and constructor
calls, non-call bare statements, the R5 coroutine mutual-exclusion case
(rule ON + coroutine discard → exactly one `unused-coroutine` error),
and the default-off regression.

Fixes facebook#3719

Test Plan:
- cargo test -p pyrefly_config test_doc_headers test_doc_severities
- cargo test -p pyrefly --lib unused_call_result
- cargo test -p pyrefly --lib simple::test_unused_coroutine
- python3 test.py --no-test --no-conformance --no-jsonschema
@nitishagar nitishagar force-pushed the nitishagar/issue-3719-unused-call-result branch from ca5efe3 to c141411 Compare June 25, 2026 09:32
@github-actions github-actions Bot added size/l and removed size/l labels Jun 25, 2026
@github-actions

Copy link
Copy Markdown

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

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

1 participant