Skip to content

fix Overloaded function is not assignable to Callable #2273#2277

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

fix Overloaded function is not assignable to Callable #2273#2277
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:2273

Conversation

@asukaminato0721
Copy link
Contributor

Summary

Fixes #2273

Adjusted overload-to-Callable subtyping so single-parameter overloads can satisfy a union-parameter Callable (the case in issue 2273), while keeping the existing per‑signature fallback.

Test Plan

Added a regression test.

@meta-cla meta-cla bot added the cla signed label Jan 31, 2026
@asukaminato0721 asukaminato0721 marked this pull request as ready for review January 31, 2026 16:24
Copilot AI review requested due to automatic review settings January 31, 2026 16:24
Copy link

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

This pull request fixes issue #2273 by enabling overloaded functions with single-parameter signatures to be assignable to Callable types that accept a union of those parameter types. The fix allows Overload[(x: int) -> str, (x: str) -> str] to be treated as compatible with Callable[[int | str], str].

Changes:

  • Added logic to merge single-parameter overload signatures into a unified callable when matching against a callable with union parameters
  • Added a test case verifying the fix for the reported issue

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
pyrefly/lib/solver/subset.rs Implements overload-to-Callable subtyping by detecting single-parameter overloads that can be merged into a union-parameter callable, with fallback to existing behavior
pyrefly/lib/test/overload.rs Adds regression test for overload assignability to Callable with union parameters

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

Comment on lines +1126 to +1133
&& u.callable_signatures()
.first()
.is_some_and(|sig| match &sig.params {
Params::List(params) if params.len() == 1 => {
matches!(params.items()[0].as_type(), Type::Union(_))
}
_ => false,
})
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

The check at line 1127 using .first() only verifies the first signature when the target type could potentially be an Overload with multiple signatures. While correctness is preserved by the subsequent is_subset_eq check and fallback logic, consider adding a length check to ensure u.callable_signatures().len() == 1 before attempting this optimization. This would avoid unnecessary work when the target is an Overload with multiple signatures where only the first matches the pattern.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

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

pywin32 (https://github.com/mhammond/pywin32)
- ERROR win32/Lib/win32timezone.py:672:9-15: Class member `TimeZoneInfo.tzname` overrides parent class `tzinfo` in an inconsistent manner [bad-override]
- ERROR win32/Lib/win32timezone.py:727:9-18: Class member `TimeZoneInfo.utcoffset` overrides parent class `tzinfo` in an inconsistent manner [bad-override]
- ERROR win32/Lib/win32timezone.py:738:9-12: Class member `TimeZoneInfo.dst` overrides parent class `tzinfo` in an inconsistent manner [bad-override]
- ::error file=win32/Lib/win32timezone.py,line=672,col=9,endLine=672,endColumn=15,title=Pyrefly bad-override::Class member `TimeZoneInfo.tzname` overrides parent class `tzinfo` in an inconsistent manner%0A  `TimeZoneInfo.tzname` has type `BoundMethod[TimeZoneInfo, Overload[%0A  (self: TimeZoneInfo, dt: datetime) -> str%0A  (self: TimeZoneInfo, dt: None) -> None%0A]]`, which is not assignable to `BoundMethod[TimeZoneInfo, (self: TimeZoneInfo, dt: datetime | None, /) -> str | None]`, the type of `tzinfo.tzname`
- ::error file=win32/Lib/win32timezone.py,line=727,col=9,endLine=727,endColumn=18,title=Pyrefly bad-override::Class member `TimeZoneInfo.utcoffset` overrides parent class `tzinfo` in an inconsistent manner%0A  `TimeZoneInfo.utcoffset` has type `BoundMethod[TimeZoneInfo, Overload[%0A  (self: TimeZoneInfo, dt: None) -> None%0A  (self: TimeZoneInfo, dt: datetime) -> timedelta%0A]]`, which is not assignable to `BoundMethod[TimeZoneInfo, (self: TimeZoneInfo, dt: datetime | None, /) -> timedelta | None]`, the type of `tzinfo.utcoffset`
- ::error file=win32/Lib/win32timezone.py,line=738,col=9,endLine=738,endColumn=12,title=Pyrefly bad-override::Class member `TimeZoneInfo.dst` overrides parent class `tzinfo` in an inconsistent manner%0A  `TimeZoneInfo.dst` has type `BoundMethod[TimeZoneInfo, Overload[%0A  (self: TimeZoneInfo, dt: None) -> None%0A  (self: TimeZoneInfo, dt: datetime) -> timedelta%0A]]`, which is not assignable to `BoundMethod[TimeZoneInfo, (self: TimeZoneInfo, dt: datetime | None, /) -> timedelta | None]`, the type of `tzinfo.dst`

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.

Overloaded function is not assignable to Callable

3 participants