Skip to content

Conversation

@tannguyencse19
Copy link

Summary

  • AtomicNarrowOp::TypeIs now use distribute_over_union return types and uses intersect_with_fallback per member

Fixes #1597

Test Plan

Using the issue sandbox link as the testcase

@meta-cla
Copy link

meta-cla bot commented Dec 23, 2025

Hi @tannguyencse19!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@tannguyencse19 tannguyencse19 changed the title fix/issue-1597-final fix: Pyrefly should narrow to intersection, not Never, for a TypeIs call Dec 23, 2025
@meta-cla
Copy link

meta-cla bot commented Dec 23, 2025

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@meta-cla meta-cla bot added the cla signed label Dec 23, 2025
@rchen152 rchen152 self-assigned this Dec 23, 2025
@github-actions

This comment has been minimized.

Copy link
Contributor

@rchen152 rchen152 left a comment

Choose a reason for hiding this comment

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

Thanks, @tannguyencse19! This PR looks about right to me, but it looks like there are a couple test failures that need fixing:

  • The test::narrow::test_typeis_union failure seems to be due to the asserted type in the test being wrong. Could you change this line from assert_type(y, A) to reveal_type(y, A) # E: (B & C) | A? (You'll also need to import reveal_type).
  • The test::narrow::test_callable failure is due to a missing case for Type::Intersect in as_call_target_impl. Implementing the Intersect case fully might be a bit tricky, but for now, I think you can get away with just using the fallback type.

@tannguyencse19
Copy link
Author

Thanks, @tannguyencse19! This PR looks about right to me, but it looks like there are a couple test failures that need fixing:

  • The test::narrow::test_typeis_union failure seems to be due to the asserted type in the test being wrong. Could you change this line from assert_type(y, A) to reveal_type(y, A) # E: (B & C) | A? (You'll also need to import reveal_type).

  • The test::narrow::test_callable failure is due to a missing case for Type::Intersect in as_call_target_impl. Implementing the Intersect case fully might be a bit tricky, but for now, I think you can get away with just using the fallback type.

Okay, I will do it

…fix test_callable failure due to missing case for Type::Intersect
@tannguyencse19
Copy link
Author

@rchen152 I fixed. Can you take a look

@rchen152
Copy link
Contributor

@rchen152 I fixed. Can you take a look

Thanks! I'll take a look when I'm back in the office on Monday.

@github-actions
Copy link

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

beartype (https://github.com/beartype/beartype)
- ERROR beartype/_util/api/standard/utilfunctools.py:319:12-30: Returned type `_lru_cache_wrapper[Unknown]` is not assignable to declared return type `BeartypeableT` [bad-return]
+ ERROR beartype/vale/_core/_valecore.py:322:30-46: `object | str` is not assignable to attribute `_get_repr` with type `(() -> str) | str` [bad-assignment]

jinja (https://github.com/pallets/jinja)
+ ERROR src/jinja2/runtime.py:688:38-66: `bool | object` is not assignable to variable `default_autoescape` with type `bool | None` [bad-assignment]
+ ERROR src/jinja2/runtime.py:770:40-50: Argument `bool | object | None` is not assignable to parameter `autoescape` with type `bool` in function `Macro._invoke` [bad-argument-type]

setuptools (https://github.com/pypa/setuptools)
- ERROR setuptools/_vendor/typing_extensions.py:2855:17-35: `str` is not assignable to attribute `__deprecated__` with type `Never` [bad-assignment]
+ ERROR setuptools/config/expand.py:334:28-41: No matching overload found for function `map.__new__` called with arguments: (type[map[_S]], type[str], Iterable[int | str] | object | Unknown) [no-matching-overload]

aiohttp (https://github.com/aio-libs/aiohttp)
+ ERROR aiohttp/client.py:872:17-45: Type `object` is not awaitable [not-async]

freqtrade (https://github.com/freqtrade/freqtrade)
+ ERROR freqtrade/strategy/informative_decorator.py:172:21-32: Argument `object | str` is not assignable to parameter `date_column` with type `str` in function `freqtrade.strategy.strategy_helper.merge_informative_pair` [bad-argument-type]

tornado (https://github.com/tornadoweb/tornado)
+ ERROR tornado/escape.py:352:28-52: Object of class `object` has no attribute `strip` [missing-attribute]

scipy (https://github.com/scipy/scipy)
- ERROR scipy/optimize/_tstutils.py:135:24-25: Cannot set item in `dict[Unknown, None]` [unsupported-operation]

psycopg (https://github.com/psycopg/psycopg)
+ ERROR psycopg_pool/psycopg_pool/pool.py:652:20-35: Returned type `object | str` is not assignable to declared return type `str` [bad-return]
+ ERROR psycopg_pool/psycopg_pool/pool.py:662:20-33: Returned type `dict[str, Any] | object` is not assignable to declared return type `dict[str, Any]` [bad-return]
+ ERROR psycopg_pool/psycopg_pool/pool_async.py:708:20-53: Returned type `object | str` is not assignable to declared return type `str` [bad-return]
+ ERROR psycopg_pool/psycopg_pool/pool_async.py:718:20-51: Returned type `dict[str, Any] | object` is not assignable to declared return type `dict[str, Any]` [bad-return]

websockets (https://github.com/aaugustin/websockets)
+ ERROR src/websockets/legacy/server.py:632:29-70: `Headers | Iterable[tuple[str, str]] | Mapping[str, str] | SupportsKeysAndGetItem | object` is not assignable to variable `extra_headers` with type `((str, Headers) -> HeadersLike) | Headers | Iterable[tuple[str, str]] | Mapping[str, str] | SupportsKeysAndGetItem | None` [bad-assignment]
+ ERROR src/websockets/legacy/server.py:634:37-50: Argument `((str, Headers) -> HeadersLike) | Headers | Iterable[tuple[str, str]] | Mapping[str, str] | SupportsKeysAndGetItem` is not assignable to parameter `*args` with type `Headers | Iterable[tuple[str, str]] | Mapping[str, str] | SupportsKeysAndGetItem` in function `websockets.datastructures.Headers.update` [bad-argument-type]

meson (https://github.com/mesonbuild/meson)
+ ERROR mesonbuild/compilers/compilers.py:1314:26-42: `list[str] | object` is not assignable to variable `extra_args` with type `((CompileCheckMode) -> list[str]) | CompilerArgs | list[str] | None` [bad-assignment]
+ ERROR mesonbuild/compilers/compilers.py:1336:9-27: `+=` is not supported between `CompilerArgs` and `(CompileCheckMode) -> list[str]` [unsupported-operation]
+ ERROR mesonbuild/compilers/d.py:563:30-66: `list[str] | object` is not assignable to variable `extra_args` with type `((CompileCheckMode) -> list[str]) | list[str] | None` [bad-assignment]
+ ERROR mesonbuild/compilers/vala.py:159:26-42: `list[str] | object` is not assignable to variable `extra_args` with type `((CompileCheckMode) -> list[str]) | CompilerArgs | list[str] | None` [bad-assignment]
+ ERROR mesonbuild/compilers/vala.py:195:9-27: `+=` is not supported between `CompilerArgs` and `(CompileCheckMode) -> list[str]` [unsupported-operation]

schemathesis (https://github.com/schemathesis/schemathesis)
+ ERROR src/schemathesis/core/marks.py:34:20-35: Returned type `object | T` is not assignable to declared return type `T | None` [bad-return]

archinstall (https://github.com/archlinux/archinstall)
+ ERROR archinstall/lib/output.py:34:12-43: Returned type `object | Unknown` is not assignable to declared return type `dict[str, Any]` [bad-return]

kornia (https://github.com/kornia/kornia)
+ ERROR kornia/utils/helpers.py:387:12-46: Returned type `DataclassInstance` is not assignable to declared return type `T` [bad-return]

strawberry (https://github.com/strawberry-graphql/strawberry)
+ ERROR strawberry/types/fields/resolver.py:211:16-50: Returned type `object | T | Unknown` is not assignable to declared return type `T` [bad-return]

poetry (https://github.com/python-poetry/poetry)
+ ERROR src/poetry/utils/cache.py:149:16-21: Returned type `object | T` is not assignable to declared return type `T` [bad-return]

dulwich (https://github.com/dulwich/dulwich)
+ ERROR dulwich/repo.py:2837:23-39: `object` is not assignable to variable `message` with type `bytes | None` [bad-assignment]
+ ERROR dulwich/worktree.py:570:23-54: `bytes | object` is not assignable to variable `message` with type `((Any, Commit) -> bytes) | bytes | str | None` [bad-assignment]
+ ERROR dulwich/worktree.py:598:33-47: Object of class `FunctionType` has no attribute `encode` [missing-attribute]
+ ERROR dulwich/worktree.py:643:29-56: `+` is not supported between `Literal[b'commit: ']` and `(Any, Commit) -> bytes` [unsupported-operation]
+ ERROR dulwich/worktree.py:661:29-56: `+` is not supported between `Literal[b'commit: ']` and `(Any, Commit) -> bytes` [unsupported-operation]

nox (https://github.com/wntrblm/nox)
+ ERROR nox/_option_set.py:162:20-35: Returned type `bool | list[str] | object | str | None` is not assignable to declared return type `bool | list[str] | str | None` [bad-return]

static-frame (https://github.com/static-frame/static-frame)
+ ERROR static_frame/core/container_util.py:575:36-57: `((...) -> IndexBase) | (((...) -> object) & Iterable[TIndexCtorSpecifier]) | (((...) -> object) & Sequence[TIndexCtorSpecifier]) | (((...) -> object) & ndarray[Any, dtype[object_]]) | type[Index[Any]] | type[IndexAutoConstructorFactory]` is not assignable to variable `explicit_constructor` with type `((...) -> IndexBase) | IndexConstructorFactoryBase | type[Index[Any]] | type[IndexConstructorFactoryBase] | None` [bad-assignment]
- ERROR static_frame/core/frame.py:4587:42-84: Argument `Generator[((...) -> IndexBase) | type[Index[Any]] | type[IndexAutoConstructorFactory], None, None]` is not assignable to parameter `iterable` with type `Iterable[TIndexCtorSpecifier]` in function `list.extend` [bad-argument-type]
+ ERROR static_frame/core/frame.py:4587:42-84: Argument `Generator[((...) -> IndexBase) | (((...) -> object) & Iterable[TIndexCtorSpecifier]) | (((...) -> object) & Sequence[TIndexCtorSpecifier]) | (((...) -> object) & ndarray[Any, dtype[object_]]) | type[Index[Any]] | type[IndexAutoConstructorFactory], None, None]` is not assignable to parameter `iterable` with type `Iterable[TIndexCtorSpecifier]` in function `list.extend` [bad-argument-type]
+ ERROR static_frame/core/frame.py:8299:25-36: Argument `((...) -> Any) | (((...) -> object) & Mapping[TLabel, (...) -> Any]) | None` is not assignable to parameter `func_single` with type `((...) -> ndarray[Any, Any]) | None` in function `static_frame.core.pivot.pivot_core` [bad-argument-type]
+ ERROR static_frame/core/frame.py:8300:22-30: Argument `tuple[tuple[TLabel, (...) -> Any], ...] | tuple[()] | tuple[tuple[Literal[''], ((...) -> Any) | (((...) -> object) & Mapping[TLabel, (...) -> Any])]]` is not assignable to parameter `func_map` with type `Sequence[tuple[TLabel, (...) -> ndarray[Any, Any]]]` in function `static_frame.core.pivot.pivot_core` [bad-argument-type]
+ ERROR static_frame/core/index_hierarchy.py:309:38-56: Argument `((...) -> IndexBase) | (((...) -> object) & Iterable[TIndexCtorSpecifier]) | (((...) -> object) & Sequence[TIndexCtorSpecifier]) | (((...) -> object) & ndarray[Any, dtype[object_]]) | type[Index[Any]] | type[IndexAutoConstructorFactory]` is not assignable to parameter `explicit_constructor` with type `((...) -> IndexBase) | IndexConstructorFactoryBase | type[Index[Any]] | type[IndexConstructorFactoryBase] | None` in function `static_frame.core.container_util.constructor_from_optional_constructor` [bad-argument-type]

mypy_primer (https://github.com/hauntsaninja/mypy_primer)
+ ERROR mypy_primer/git_utils.py:65:17-46: Type `object` is not awaitable [not-async]

typeshed-stats (https://github.com/AlexWaygood/typeshed-stats)
- ERROR src/typeshed_stats/gather.py:999:28-1002:10: `Pattern[Unknown] | @7264 | None` is not assignable to upper bound `bytes | str` of type variable `AnyStr` [bad-specialization]
+ ERROR src/typeshed_stats/gather.py:999:28-1002:10: `Pattern[Unknown] | @7255 | None` is not assignable to upper bound `bytes | str` of type variable `AnyStr` [bad-specialization]

vision (https://github.com/pytorch/vision)
+ ERROR test/datasets_utils.py:835:57-94: Argument `Sequence[int] | int | object | tuple[int, int, int]` is not assignable to parameter `size` with type `Sequence[int] | int` in function `create_image_file` [bad-argument-type]

sphinx (https://github.com/sphinx-doc/sphinx)
+ ERROR sphinx/environment/__init__.py:396:25-31: `((Node) -> bool) | (((...) -> object) & str)` is not assignable to variable `condition` with type `Literal[False] | ((Node) -> bool)` [bad-assignment]

pandas (https://github.com/pandas-dev/pandas)
+ ERROR pandas/core/apply.py:1154:42-45: Argument `object | Unknown` is not assignable to parameter `obj` with type `Sized` in function `len` [bad-argument-type]
+ ERROR pandas/core/apply.py:1522:9-12: Class member `SeriesApply.agg` overrides parent class `NDFrameApply` in an inconsistent manner [bad-override]
+ ERROR pandas/io/formats/style.py:4022:41-45: Argument `(Interval[Unknown] & Iterable[Any]) | (Iterable[Any] & Timedelta) | (Iterable[Any] & Timestamp) | (Iterable[Any] & bool) | (Iterable[Any] & complex) | (Iterable[Any] & complexfloating[Any, Any]) | (Iterable[Any] & date) | (Iterable[Any] & datetime) | (Iterable[Any] & datetime64[date | int | None]) | (Iterable[Any] & float) | (Iterable[Any] & floating[Any]) | (Iterable[Any] & int) | (Iterable[Any] & integer[Any]) | (Iterable[Any] & timedelta) | (Iterable[Any] & timedelta64[int | timedelta | None]) | NDFrame | Sequence[Unknown] | bytes | ndarray[tuple[Any, ...], dtype[Any]]` is not assignable to parameter `arg` with type `NDFrame | Sequence[Unknown] | ndarray[tuple[Any, ...], dtype[Any]]` in function `_validate_apply_axis_arg` [bad-argument-type]
+ ERROR pandas/io/formats/style.py:4025:42-47: Argument `(Interval[Unknown] & Iterable[Any]) | (Iterable[Any] & Timedelta) | (Iterable[Any] & Timestamp) | (Iterable[Any] & bool) | (Iterable[Any] & complex) | (Iterable[Any] & complexfloating[Any, Any]) | (Iterable[Any] & date) | (Iterable[Any] & datetime) | (Iterable[Any] & datetime64[date | int | None]) | (Iterable[Any] & float) | (Iterable[Any] & floating[Any]) | (Iterable[Any] & int) | (Iterable[Any] & integer[Any]) | (Iterable[Any] & timedelta) | (Iterable[Any] & timedelta64[int | timedelta | None]) | NDFrame | Sequence[Unknown] | bytes | ndarray[tuple[Any, ...], dtype[Any]]` is not assignable to parameter `arg` with type `NDFrame | Sequence[Unknown] | ndarray[tuple[Any, ...], dtype[Any]]` in function `_validate_apply_axis_arg` [bad-argument-type]
+ ERROR pandas/io/formats/style.py:4236:9-17: `object | Unknown` is not assignable to `float` [bad-assignment]
+ ERROR pandas/io/formats/style.py:4269:24-32: `-` is not supported between `Literal[0]` and `object` [unsupported-operation]
+ ERROR pandas/io/formats/style.py:4269:24-32: `-` is not supported between `float` and `object` [unsupported-operation]
+ ERROR pandas/io/formats/style.py:4269:34-43: `-` is not supported between `Literal[0]` and `object` [unsupported-operation]
+ ERROR pandas/io/formats/style.py:4269:34-43: `-` is not supported between `float` and `object` [unsupported-operation]
+ ERROR pandas/io/formats/style.py:4279:25-33: `-` is not supported between `Literal[0]` and `object` [unsupported-operation]
+ ERROR pandas/io/formats/style.py:4279:25-33: `-` is not supported between `float` and `object` [unsupported-operation]
+ ERROR pandas/io/formats/style.py:4280:25-34: `-` is not supported between `Literal[0]` and `object` [unsupported-operation]
+ ERROR pandas/io/formats/style.py:4280:25-34: `-` is not supported between `float` and `object` [unsupported-operation]
+ ERROR pandas/tests/window/test_ewm.py:668:20-57: Object of class `object` has no attribute `reset_index` [missing-attribute]
+ ERROR pandas/tests/window/test_ewm.py:712:20-49: Object of class `object` has no attribute `reset_index` [missing-attribute]
+ ERROR pandas/tests/window/test_expanding.py:764:20-57: Object of class `object` has no attribute `reset_index` [missing-attribute]
+ ERROR pandas/tests/window/test_expanding.py:805:20-49: Object of class `object` has no attribute `reset_index` [missing-attribute]
+ ERROR pandas/tests/window/test_rolling.py:1953:16-53: Object of class `object` has no attribute `reset_index` [missing-attribute]
+ ERROR pandas/tests/window/test_rolling.py:1994:20-49: Object of class `object` has no attribute `reset_index` [missing-attribute]

prefect (https://github.com/PrefectHQ/prefect)
+ ERROR src/prefect/client/orchestration/__init__.py:832:29-40: Argument `int | list[int] | object` is not assignable to parameter `retry_delay` with type `Decimal | Iterable[LaxFloat] | bool | bytes | float | int | str | None` in function `prefect.client.schemas.objects.TaskRunPolicy.__init__` [bad-argument-type]
+ ERROR src/prefect/client/orchestration/__init__.py:1493:29-40: Argument `int | list[int] | object` is not assignable to parameter `retry_delay` with type `Decimal | Iterable[LaxFloat] | bool | bytes | float | int | str | None` in function `prefect.client.schemas.objects.TaskRunPolicy.__init__` [bad-argument-type]
- ERROR src/prefect/flow_engine.py:359:20-27: Returned type `type[NotSet] | R | Unknown` is not assignable to declared return type `State[Any] | R | None` [bad-return]
+ ERROR src/prefect/flow_engine.py:359:20-27: Returned type `type[NotSet] | R | Any` is not assignable to declared return type `State[Any] | R | None` [bad-return]
- ERROR src/prefect/flow_engine.py:946:20-27: Returned type `type[NotSet] | R` is not assignable to declared return type `State[Any] | R | None` [bad-return]
+ ERROR src/prefect/flow_engine.py:946:20-27: Returned type `type[NotSet] | R | Any` is not assignable to declared return type `State[Any] | R | None` [bad-return]
+ ERROR src/prefect/task_engine.py:209:25-49: Argument `list[float] | object` is not assignable to parameter `retry_delay` with type `Decimal | Iterable[LaxFloat] | bool | bytes | float | int | str | None` in function `prefect.client.schemas.objects.TaskRunPolicy.__init__` [bad-argument-type]
+ ERROR src/prefect/task_engine.py:672:41-46: Argument `float | object` is not assignable to parameter `seconds` with type `float` in function `datetime.timedelta.__new__` [bad-argument-type]
+ ERROR src/prefect/task_engine.py:1275:41-46: Argument `float | object` is not assignable to parameter `seconds` with type `float` in function `datetime.timedelta.__new__` [bad-argument-type]
- ERROR src/prefect/tasks.py:575:17-36: `NoneType | float | int | list[float]` is not assignable to attribute `retry_delay_seconds` with type `list[float]` [bad-assignment]
- ERROR src/prefect/tasks.py:799:17-801:46: Argument `((int) -> list[float]) | float | int | list[float] | type[NotSet]` is not assignable to parameter `retry_delay_seconds` with type `((int) -> list[float]) | float | int | list[float] | None` in function `Task.__init__` [bad-argument-type]
+ ERROR src/prefect/tasks.py:799:17-801:46: Argument `((int) -> list[float]) | float | int | list[float] | object | type[NotSet]` is not assignable to parameter `retry_delay_seconds` with type `((int) -> list[float]) | float | int | list[float] | None` in function `Task.__init__` [bad-argument-type]
+ ERROR src/prefect/tasks.py:1079:33-57: Argument `list[float] | object` is not assignable to parameter `retry_delay` with type `Decimal | Iterable[LaxFloat] | bool | bytes | float | int | str | None` in function `prefect.client.schemas.objects.TaskRunPolicy.__init__` [bad-argument-type]
+ ERROR src/prefect/utilities/_engine.py:55:12-25: Returned type `object | str` is not assignable to declared return type `str` [bad-return]
+ ERROR src/prefect/utilities/_engine.py:64:13-31: Argument `(() -> str) | (((...) -> object) & str) | TaskRunNameCallbackWithParameters` is not assignable to parameter `callable` with type `(...) -> str` in function `prefect.tasks.TaskRunNameCallbackWithParameters.is_callback_with_parameters` [bad-argument-type]
+ ERROR src/prefect/utilities/_engine.py:85:12-25: Returned type `object | str` is not assignable to declared return type `str` [bad-return]
+ ERROR src/integrations/prefect-dask/prefect_dask/task_runners.py:354:25-68: Argument `object | Unknown` is not assignable to parameter `cm` with type `AbstractContextManager[@_, bool | None]` in function `contextlib._BaseExitStack.enter_context` [bad-argument-type]

scrapy (https://github.com/scrapy/scrapy)
+ ERROR scrapy/downloadermiddlewares/retry.py:110:22-30: `Exception | object` is not assignable to variable `reason` with type `Exception | str | type[Exception]` [bad-assignment]
+ ERROR scrapy/linkextractors/lxmlhtml.py:72:13-74:74: `((str) -> bool) | (((...) -> object) & str)` is not assignable to attribute `scan_tag` with type `(str) -> bool` [bad-assignment]
+ ERROR scrapy/linkextractors/lxmlhtml.py:77:13-79:75: `((str) -> bool) | (((...) -> object) & str)` is not assignable to attribute `scan_attr` with type `(str) -> bool` [bad-assignment]

werkzeug (https://github.com/pallets/werkzeug)
+ ERROR src/werkzeug/middleware/profiler.py:143:36-65: No matching overload found for function `posixpath.join` called with arguments: (str, object | str) [no-matching-overload]
+ ERROR src/werkzeug/utils.py:498:19-32: `int | object | None` is not assignable to variable `max_age` with type `((str | None) -> int | None) | int | None` [bad-assignment]
+ ERROR src/werkzeug/utils.py:501:12-23: `>` is not supported between `(str | None) -> int | None` and `Literal[0]` [unsupported-operation]
+ ERROR src/werkzeug/utils.py:505:36-43: `((str | None) -> int | None) | int` is not assignable to attribute `max_age` with type `int | None` [bad-assignment]
+ ERROR src/werkzeug/wsgi.py:244:25-36: `list[(() -> None) | (((...) -> object) & Iterable[() -> None])]` is not assignable to variable `callbacks` with type `(() -> None) | Iterable[() -> None] | None` [bad-assignment]
+ ERROR src/werkzeug/wsgi.py:249:13-29: Object of class `FunctionType` has no attribute `insert`
+ Object of class `Iterable` has no attribute `insert`
+ Object of class `NoneType` has no attribute `insert` [missing-attribute]
+ ERROR src/werkzeug/wsgi.py:259:25-40: Type `() -> None` is not iterable [not-iterable]
+ ERROR src/werkzeug/wsgi.py:259:25-40: Type `None` is not iterable [not-iterable]

graphql-core (https://github.com/graphql-python/graphql-core)
+ ERROR src/graphql/type/definition.py:316:12-49: Returned type `object | T` is not assignable to declared return type `T` [bad-return]

bokeh (https://github.com/bokeh/bokeh)
+ ERROR src/bokeh/core/property/bases.py:187:24-31: Returned type `(() -> T) | (((...) -> object) & T)` is not assignable to declared return type `T` [bad-return]
- ERROR src/bokeh/core/property/bases.py:187:24-31: Returned type `() -> T` is not assignable to declared return type `T` [bad-return]
+ ERROR src/bokeh/core/property/bases.py:188:20-29: Returned type `object | T` is not assignable to declared return type `T` [bad-return]
+ ERROR src/bokeh/io/notebook.py:586:30-33: Argument `object | str` is not assignable to parameter `url` with type `str` in function `bokeh.embed.server.server_document` [bad-argument-type]
+ ERROR src/bokeh/plotting/graph.py:134:76-88: Argument `dict[int | str, Sequence[float]] | object` is not assignable to parameter `graph_layout` with type `dict[int | str, Sequence[float]]` in function `bokeh.models.graphs.StaticLayoutProvider.__init__` [bad-argument-type]
+ ERROR src/bokeh/server/tornado.py:286:56-68: Argument `((Document) -> None) | (((...) -> object) & Application) | (((...) -> object) & Mapping[str, ((Document) -> None) | Application])` is not assignable to parameter `func` with type `(Document) -> None` in function `bokeh.application.handlers.function.FunctionHandler.__init__` [bad-argument-type]
+ ERROR src/bokeh/server/tornado.py:295:71-74: Argument `((Document) -> None) | (((...) -> object) & Application)` is not assignable to parameter `func` with type `(Document) -> None` in function `bokeh.application.handlers.function.FunctionHandler.__init__` [bad-argument-type]

@meta-codesync
Copy link

meta-codesync bot commented Dec 30, 2025

@rchen152 has imported this pull request. If you are a Meta employee, you can view this in D89907556.

Copy link
Contributor

@rchen152 rchen152 left a comment

Choose a reason for hiding this comment

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

Thanks! I'll work on getting this merged.

if let Type::TypeIs(t) = ret {
return self.intersect(ty, &t);
return self.distribute_over_union(&t, |right| {
self.intersect_with_fallback(ty, right, &|| right.clone())
Copy link
Contributor

Choose a reason for hiding this comment

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

This change turned out to be a little too noisy when I ran internal tests, so I tweaked this to fall back to Never when the lhs is a union. (No action needed on your part, just FYI.)

Copy link
Author

Choose a reason for hiding this comment

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

Okay

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.

Pyrefly should narrow to intersection, not Never, for a TypeIs call

2 participants