Skip to content

fix str.join with and/or expression narrowing #2875#2906

Open
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:2875
Open

fix str.join with and/or expression narrowing #2875#2906
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:2875

Conversation

@asukaminato0721
Copy link
Copy Markdown
Contributor

@asukaminato0721 asukaminato0721 commented Mar 26, 2026

Summary

Fixes #2875

boolean-expression inference now keeps the truthiness-refined slice of a non-final operand instead of the full operand type, which stops (e and e.__name__) or "None" from leaking type[Any] into the result.

Test Plan

add test

@meta-cla meta-cla bot added the cla signed label Mar 26, 2026
@asukaminato0721 asukaminato0721 marked this pull request as ready for review March 26, 2026 10:58
Copilot AI review requested due to automatic review settings March 26, 2026 10:58
@asukaminato0721 asukaminato0721 marked this pull request as draft March 26, 2026 10:58
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a Pyrefly-specific narrowing issue where and/or boolean expressions involving type | None could leave an imprecise type that then broke overload resolution for str.join (issue #2875).

Changes:

  • Generalize boolop result-type narrowing by reusing atomic_narrow(..., IsTruthy/IsFalsy) for intermediate operands.
  • Make Type::Type(_) statically truthy in Type::as_bool() to support correct and/or narrowing for class objects.
  • Add a regression test ensuring sorted((e and e.__name__) or "None" ...) produces list[str] and is accepted by ", ".join(...).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
pyrefly/lib/test/literal.rs Adds regression test covering str.join with and/or narrowing over `type
pyrefly/lib/alt/narrow.rs Exposes atomic_narrow to other alt modules (pub(crate)) so boolop inference can reuse it.
pyrefly/lib/alt/expr.rs Updates boolop inference to narrow intermediate results via atomic_narrow(IsTruthy/IsFalsy) instead of bespoke literal cases.
crates/pyrefly_types/src/types.rs Treats Type::Type(_) as statically truthy for as_bool(), enabling the intended narrowing behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@asukaminato0721 asukaminato0721 marked this pull request as ready for review March 26, 2026 12:04
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

Diff from mypy_primer, showing the effect of this PR on open source code:

steam.py (https://github.com/Gobot1234/steam.py)
- ERROR steam/ext/commands/commands.py:826:11-25: `type[Command] | type[C]` is not assignable to variable `cls` with type `type[C]` [bad-assignment]

@github-actions
Copy link
Copy Markdown

Primer Diff Classification

✅ 1 improvement(s) | 1 project(s) total | -1 errors

1 improvement(s) across steam.py.

Project Verdict Changes Error Kinds Root Cause
steam.py ✅ Improvement -1 bad-assignment crates/pyrefly_types/src/types.rs
Detailed analysis

✅ Improvement (1)

steam.py (-1)

This is an improvement. The PR correctly identifies that type[X] objects are always truthy in Python (no class object is ever falsy). This allows pyrefly to properly narrow cls or Command where cls: type[C] to just type[C], eliminating the false positive bad-assignment error. The old error was wrong because it included type[Command] in the result type of an or expression whose left operand (type[C]) is always truthy — meaning the right operand (Command) is unreachable.
Attribution: The change in crates/pyrefly_types/src/types.rs adding Type::Type(_) => Some(true) is the direct cause. This tells pyrefly that type[X] values are always truthy. Combined with the refactored boolean expression narrowing in pyrefly/lib/alt/expr.rs (which now uses atomic_narrow with IsTruthy/IsFalsy instead of ad-hoc special cases), pyrefly correctly determines that in cls or Command where cls: type[C], the left operand is always truthy, so the result type is just type[C] (not type[C] | type[Command]).


Was this helpful? React with 👍 or 👎

Classification by primer-classifier (1 LLM)

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

str.join with and/or expression narrowing

2 participants