Skip to content

Fix property access for function types - #21885

Open
daleselaji-dev wants to merge 3 commits into
python:masterfrom
daleselaji-dev:fix/property-function-type-narrowing-21879
Open

Fix property access for function types#21885
daleselaji-dev wants to merge 3 commits into
python:masterfrom
daleselaji-dev:fix/property-function-type-narrowing-21879

Conversation

@daleselaji-dev

@daleselaji-dev daleselaji-dev commented Aug 24, 2026

Copy link
Copy Markdown

Problem

Mypy treats a property returning types.FunctionType as a bound method when the value is accessed from an instance. A valid isinstance(..., FunctionType) assertion is therefore reported as an impossible intersection with MethodType when --warn-unreachable is enabled.

Root Cause

Member analysis can apply descriptor access a second time after a property getter has already produced its value. The original fix skipped that duplicate pass for read-only properties, but the first review repair also exposed an existing dataclass-transform descriptor case whose synthetic read-only field still needs descriptor access.

Solution

Skip the duplicate descriptor pass for ordinary read-only property results while preserving descriptor evaluation for fields recorded in the dataclass-transform metadata. This keeps the reported FunctionType property narrowing correct without regressing generic descriptor-backed dataclass fields.

Changes

  • Avoid the second descriptor binding for ordinary read-only property results in analyze_var.
  • Preserve descriptor access for synthetic dataclass fields by checking the field metadata.
  • Keep the original focused FunctionType/MethodType regression and descriptor fixture.
  • Fix the related CI regression on check-dataclass-transform.test.

Testing

  • Reproduction before fix: current main revealed wrapped.__func__ as types.MethodType and emitted two [unreachable] errors.
  • Property regression plus dataclass regression: pytest -n0 mypy/test/testcheck.py -k 'testPropertyReturningFunctionType or testDataclassTransformGenericDescriptor' — 3 passed.
  • Full check-classes.test: 610 passed, 1 existing xfailed.
  • Self typecheck: python -m mypy --config-file mypy_self_check.ini -p mypy — 196 source files, no issues.
  • Ruff: not verified; the local environment has no Ruff module.
  • git diff --check: passed.
  • CI repair evidence: run 32691141642 failed consistently on the pre-existing check-dataclass-transform.test expectation after the original diff; the new same-scope head is 3f4c859 and the local regression is green.

Compatibility/Risk

Only static member-type analysis is changed. Ordinary read-only properties retain value semantics, settable properties retain their descriptor behavior, and synthetic dataclass-transform descriptor fields retain instance access through __get__. Runtime Python behavior is unchanged.

Notes for Reviewer

The added metadata check is intentionally narrow: it identifies a dataclass field by the existing info.metadata["dataclass"]["attributes"] record instead of broadening descriptor handling for every property. This contribution was AI-assisted.

Linked Issue

Fixes #21879

@daleselaji-dev
daleselaji-dev marked this pull request as ready for review August 24, 2026 03:17
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

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

colour (https://github.com/colour-science/colour)
- colour/continuous/signal.py:1207: error: Argument 1 to "as_float_array" has incompatible type "ndarray[tuple[int], dtype[Any]] | ExtensionArray"; expected "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str]"  [arg-type]
+ colour/continuous/signal.py:1207: error: Argument 1 to "as_float_array" has incompatible type "ndarray[tuple[int], dtype[Any]] | ExtensionArray | Categorical[object]"; expected "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str]"  [arg-type]

freqtrade (https://github.com/freqtrade/freqtrade)
+ freqtrade/freqai/freqai_interface.py:950: error: Argument 1 to "to_datetime" has incompatible type "Any | object"; expected "float | str | datetime | datetime64[Any] | date"  [arg-type]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant