Skip to content

[refurb] Mark fixes that remove unknown separators as unsafe (FURB105) - #27200

Merged
ntBre merged 1 commit into
astral-sh:mainfrom
jesco-absolut:fix-20919-furb105-sep-safety
Jul 27, 2026
Merged

[refurb] Mark fixes that remove unknown separators as unsafe (FURB105)#27200
ntBre merged 1 commit into
astral-sh:mainfrom
jesco-absolut:fix-20919-furb105-sep-safety

Conversation

@jesco-absolut

@jesco-absolut jesco-absolut commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #20919.

The main learning point after working on this was, that python validates sep even when it is unused;
removing an unknown value can suppress a TypeError; therefore only known-valid separators receive a safe fix.

FURB105 can suggest removing an unused sep argument from a print call. The fix was previously considered safe unless
evaluating the separator had observable side effects.

Python still validates sep even when the call only prints one value. If the separator is neither None nor a string,
the original call raises a TypeError. Removing an unknown separator can therefore change the program's behavior even
when evaluating its expression has no side effects.

This change makes the fix conservative: removing sep is considered safe when its value is statically known to be a
string literal or None. Other separator expressions retain the FURB105 diagnostic, but their fix is marked unsafe.

The fixtures cover both a known-valid None separator and a separator supplied through an unknown variable. The rule
documentation and snapshots are updated to reflect the safety distinction.

Test Plan

  • Ran the focused FURB105 fixture and snapshot test:
    cargo test -p ruff_linter --lib rule_printemptystring_path_new_furb105_py_expects
  • Ran cargo fmt --all --check

@astral-sh-bot
astral-sh-bot Bot requested a review from ntBre July 26, 2026 23:00
@astral-sh-bot

astral-sh-bot Bot commented Jul 26, 2026

Copy link
Copy Markdown

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@ntBre ntBre added the fixes Related to suggested fixes for violations label Jul 27, 2026

@ntBre ntBre left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks! I was initially worried that this is quite a restrictive check, but I think trying to make it more permissive isn't worth the complexity it would introduce. For example, we could try to use our typing module to make cases like this safe:

def p(sep: str): print(1, sep=sep)
def p(sep: None): print(1, sep=sep)
def p(sep: str | None): print(1, sep=sep)

but then we'd need separate handling for a case like:

def foo():
    sep = ""
    print(1, sep=sep)

and other cases. Given that literals are probably the most common case and that this doesn't show any negative ecosystem impact, I think this is an acceptable tradeoff.

We can try to expand the check again when we get access to ty's type inference.

@ntBre ntBre changed the title FURB105: mark fixes that remove unknown separators as unsafe [refurb] Mark fixes that remove unknown separators as unsafe (FURB105) Jul 27, 2026
@ntBre
ntBre merged commit 1673aa7 into astral-sh:main Jul 27, 2026
47 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fixes Related to suggested fixes for violations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FURB105 fix should be unsafe when it removes a sep with a possibly incorrect type

2 participants