Skip to content

Conversation

@danparizher
Copy link
Contributor

Summary

Fixes #21136. The rule was incorrectly treating tuple(generator) as always truthy, but tuple(empty_generator) is falsy.

Problem Analysis

SIM222 was incorrectly suggesting to remove or None from tuple(item for item in items) or None because it was treating the tuple call as always truthy. However, when a generator expression is empty, tuple(empty_generator) produces an empty tuple (), which is falsy. Removing or None would change the runtime behavior.

Approach

Updated Truthiness::from_expr to return Unknown for tuple(generator), tuple(list_comp), and tuple(set_comp) calls, since we cannot statically determine if the resulting tuple will be empty or not. This prevents SIM222 from flagging these cases incorrectly.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 1, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

@ntBre ntBre added bug Something isn't working rule Implementing or modifying a lint rule labels Nov 3, 2025
// is falsy.
if matches!(
&arguments.args[0],
Expr::Generator(_) | Expr::ListComp(_) | Expr::SetComp(_)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this only needs to include Generator, not the comprehension types. Recursing into the Self::from_expr arm below should already return Self::Unknown for other comprehensions. Generators are the only special case on 1223, if I'm following correctly.

The last two new tests already suppress the rule, for example: https://play.ruff.rs/a211c51a-b6f3-4dae-b259-431a75788464

@danparizher danparizher requested a review from ntBre November 7, 2025 23:22
@MichaReiser MichaReiser merged commit 04e7cec into astral-sh:main Nov 10, 2025
35 of 37 checks passed
@danparizher danparizher deleted the fix-21136 branch November 10, 2025 15:52
dcreager added a commit that referenced this pull request Nov 11, 2025
* origin/main: (38 commits)
  [ty] Make implicit submodule imports only occur in global scope (#21370)
  [ty] introduce local variables for `from` imports of submodules in `__init__.py(i)` (#21173)
  [`ruff`] Ignore `str()` when not used for simple conversion (`RUF065`) (#21330)
  [ty] implement `typing.NewType` by adding `Type::NewTypeInstance`
  [ty] supress inlay hints for `+1` and `-1` (#21368)
  [ty] Use type context for inference of generic constructors (#20933)
  [ty] Improve generic call expression inference (#21210)
  [ty] supress some trivial expr inlay hints (#21367)
  [`configuration`] Fix unclear error messages for line-length values exceeding `u16::MAX` (#21329)
  [ty] Fix incorrect inference of `enum.auto()` for enums with non-`int` mixins, and imprecise inference of `enum.auto()` for single-member enums (#20541)
  [`refurb`] Detect empty f-strings (`FURB105`) (#21348)
  [ty] provide `import` completion when in `from <name> <name>` statement (#21291)
  [ty] elide redundant inlay hints for function args (#21365)
  Fix syntax error false positive on alternative `match` patterns (#21362)
  Add a new "Opening a PR" section to the contribution guide (#21298)
  [`flake8-simplify`] Fix SIM222 false positive for `tuple(generator) or None` (`SIM222`) (#21187)
  Rebuild ruff binary instead of sharing it across jobs (#21361)
  [ty] Fix `--exclude` and `src.exclude` merging (#21341)
  [ty] Add support for properties that return `Self` (#21335)
  Add upstream linter URL to `ruff linter --output-format=json` (#21316)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working rule Implementing or modifying a lint rule

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SIM222 overstepping

3 participants