Skip to content

[ty] support enum _value_ annotation#22228

Merged
charliermarsh merged 17 commits intoastral-sh:mainfrom
silamon:enum_value_annotation
Feb 26, 2026
Merged

[ty] support enum _value_ annotation#22228
charliermarsh merged 17 commits intoastral-sh:mainfrom
silamon:enum_value_annotation

Conversation

@silamon
Copy link
Contributor

@silamon silamon commented Dec 27, 2025

Summary

The _value_ attribute is used inside an Enum class to explicitly define the underlying value of an enum member. Typing can be verified on the members.

Test Plan

Added a mdtest

@carljm carljm changed the title Support enum _value_ annotation [ty] support enum _value_ annotation Dec 27, 2025
@carljm carljm added the ty Multi-file analysis & type inference label Dec 27, 2025
@astral-sh-bot
Copy link

astral-sh-bot bot commented Dec 27, 2025

Typing conformance results improved 🎉

The percentage of diagnostics emitted that were expected errors increased from 84.96% to 84.99%. The percentage of expected errors that received a diagnostic increased from 75.14% to 75.25%.

Summary

Metric Old New Diff Outcome
True Positives 819 821 +2 ⏫ (✅)
False Positives 145 145 +0
False Negatives 271 270 -1 ⏬ (✅)
Total Diagnostics 964 966 +2
Precision 84.96% 84.99% +0.03% ⏫ (✅)
Recall 75.14% 75.25% +0.11% ⏫ (✅)

True positives added

Details
Location Name Message
enums_member_values.py:78:5 invalid-assignment Enum member GREEN value is not assignable to expected type

Optional Diagnostics Removed

Details
Location Name Message
enums_member_values.py:96:1 type-assertion-failure Type Unknown does not match asserted type int

Optional Diagnostics Added

Details
Location Name Message
enums_member_values.py:50:5 invalid-assignment Enum member MARS is incompatible with __init__
enums_member_values.py:51:5 invalid-assignment Enum member JUPITER is incompatible with __init__

@astral-sh-bot
Copy link

astral-sh-bot bot commented Dec 27, 2025

mypy_primer results

Changes were detected when running on open source projects
spack (https://github.com/spack/spack)
- lib/spack/spack/detection/path.py:169:33: error[invalid-argument-type] Argument to function `dedupe_paths` is incorrect: Expected `list[str]`, found `Unknown | list[int | str | bytes | ... omitted 3 union elements]`
+ lib/spack/spack/detection/path.py:169:33: error[invalid-argument-type] Argument to function `dedupe_paths` is incorrect: Expected `list[str]`, found `Unknown | list[int | Unknown | str | ... omitted 3 union elements]`
- lib/spack/spack/llnl/util/filesystem.py:1668:35: error[invalid-argument-type] Argument to function `exists` is incorrect: Expected `int | str | bytes | PathLike[str] | PathLike[bytes]`, found `Unknown | Sized`
+ lib/spack/spack/llnl/util/filesystem.py:1668:35: error[invalid-argument-type] Argument to function `exists` is incorrect: Expected `int | str | bytes | PathLike[str] | PathLike[bytes]`, found `Sized | Unknown`
- lib/spack/spack/llnl/util/filesystem.py:1674:25: error[invalid-argument-type] Argument to function `move` is incorrect: Expected `str | PathLike[str]`, found `Unknown | Sized`
+ lib/spack/spack/llnl/util/filesystem.py:1674:25: error[invalid-argument-type] Argument to function `move` is incorrect: Expected `str | PathLike[str]`, found `Sized | Unknown`
- lib/spack/spack/verify_libraries.py:164:46: error[invalid-argument-type] Argument to function `candidate_matches` is incorrect: Expected `bytes`, found `Unknown | bytes | str | PathLike[str] | PathLike[bytes]`
+ lib/spack/spack/verify_libraries.py:164:46: error[invalid-argument-type] Argument to function `candidate_matches` is incorrect: Expected `bytes`, found `bytes | Unknown | str | PathLike[str] | PathLike[bytes]`
- lib/spack/spack/verify_libraries.py:165:17: error[invalid-assignment] Invalid subscript assignment with key of type `Unknown | bytes | str | PathLike[str] | PathLike[bytes]` and value of type `Unknown | bytes | str | PathLike[str] | PathLike[bytes]` on object of type `dict[bytes, bytes]`
+ lib/spack/spack/verify_libraries.py:165:17: error[invalid-assignment] Invalid subscript assignment with key of type `bytes | Unknown | str | PathLike[str] | PathLike[bytes]` and value of type `bytes | Unknown | str | PathLike[str] | PathLike[bytes]` on object of type `dict[bytes, bytes]`
- lib/spack/spack/verify_libraries.py:170:57: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `list[bytes]`, found `list[Unknown | bytes | str | PathLike[str] | PathLike[bytes]]`
+ lib/spack/spack/verify_libraries.py:170:57: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `list[bytes]`, found `list[bytes | Unknown | str | PathLike[str] | PathLike[bytes]]`
- lib/spack/spack/verify_libraries.py:170:69: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `list[bytes]`, found `list[Unknown | bytes | str | PathLike[str] | PathLike[bytes]]`
+ lib/spack/spack/verify_libraries.py:170:69: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `list[bytes]`, found `list[bytes | Unknown | str | PathLike[str] | PathLike[bytes]]`

rich (https://github.com/Textualize/rich)
- tests/test_tools.py:17:17: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Iterable[tuple[bool, str | Unknown]]`
+ tests/test_tools.py:17:17: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Iterable[tuple[bool, Unknown | str]]`
- tests/test_tools.py:18:17: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Iterable[tuple[bool, str | Unknown]]`
+ tests/test_tools.py:18:17: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Iterable[tuple[bool, Unknown | str]]`
- tests/test_tools.py:19:17: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Iterable[tuple[bool, str | Unknown]]`
+ tests/test_tools.py:19:17: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Iterable[tuple[bool, Unknown | str]]`
- tests/test_tools.py:20:17: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Iterable[tuple[bool, str | Unknown]]`
+ tests/test_tools.py:20:17: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Iterable[tuple[bool, Unknown | str]]`

porcupine (https://github.com/Akuli/porcupine)
- porcupine/pluginmanager.py:133:49: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `Iterable[Never]`, found `Unknown | str`
- Found 25 diagnostics
+ Found 24 diagnostics

sockeye (https://github.com/awslabs/sockeye)
- sockeye/output_handler.py:254:80: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `Iterable[Unknown | list[str]]`, found `list[list[str]] | None`
+ sockeye/output_handler.py:254:80: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `Iterable[list[str] | Unknown]`, found `list[list[str]] | None`

pydantic (https://github.com/pydantic/pydantic)
- pydantic/_internal/_core_metadata.py:87:54: error[invalid-assignment] Invalid assignment to key "pydantic_js_extra" with declared type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | ((dict[str, Divergent], type[Any], /) -> None)` on TypedDict `CoreMetadata`: value of type `dict[object, object]`
+ pydantic/_internal/_core_metadata.py:87:54: error[invalid-assignment] Invalid assignment to key "pydantic_js_extra" with declared type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | ((dict[str, int | float | str | ... omitted 3 union elements], type[Any], /) -> None)` on TypedDict `CoreMetadata`: value of type `dict[object, object]`
- pydantic/fields.py:949:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:949:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:989:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:989:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1032:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1032:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1072:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1072:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1115:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1115:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1154:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1154:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1194:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1194:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1573:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`, found `Top[dict[Unknown, Unknown]] | (((dict[str, Divergent], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`
+ pydantic/fields.py:1573:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`, found `Top[dict[Unknown, Unknown]] | (((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`

artigraph (https://github.com/artigraph/artigraph)
- tests/arti/types/test_types.py:100:51: error[invalid-argument-type] Argument is incorrect: Expected `frozenset[Any]`, found `frozenset[float | Unknown | int] | list[Unknown | int | float] | tuple[float | Unknown | int, ...]`
+ tests/arti/types/test_types.py:100:51: error[invalid-argument-type] Argument is incorrect: Expected `frozenset[Any]`, found `frozenset[float | Unknown | int] | list[int | Unknown | float] | tuple[float | Unknown | int, ...]`

Expression (https://github.com/cognitedata/Expression)
+ tests/test_compose.py:21:16: error[invalid-assignment] Object of type `(Never, /) -> Never` is not assignable to `(int, /) -> int`
- Found 204 diagnostics
+ Found 205 diagnostics

openlibrary (https://github.com/internetarchive/openlibrary)
- openlibrary/catalog/utils/__init__.py:132:17: error[unresolved-attribute] Attribute `search` is not defined on `str` in union `str | Unknown`
+ openlibrary/catalog/utils/__init__.py:132:17: error[unresolved-attribute] Attribute `search` is not defined on `str` in union `Unknown | str`

cloud-init (https://github.com/canonical/cloud-init)
- tests/unittests/distros/test_user_data_normalize.py:24:31: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `dict[Unknown, Unknown]`, found `Unknown | dict[Unknown | str, Unknown | str] | str | ... omitted 3 union elements`
+ tests/unittests/distros/test_user_data_normalize.py:24:31: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `dict[Unknown, Unknown]`, found `Unknown | bool | list[Unknown] | ... omitted 3 union elements`
- tests/unittests/sources/test_gce.py:71:31: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `dict[Unknown, Unknown]`, found `Unknown | dict[Unknown | str, Unknown | str] | str | ... omitted 3 union elements`
+ tests/unittests/sources/test_gce.py:71:31: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `dict[Unknown, Unknown]`, found `Unknown | bool | list[Unknown] | ... omitted 3 union elements`

prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/input/run_input.py:672:20: error[invalid-return-type] Return type does not match returned value: expected `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]`, found `Unknown | Coroutine[Any, Any, Unknown]`
+ src/prefect/input/run_input.py:672:20: error[invalid-return-type] Return type does not match returned value: expected `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]`, found `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler] | Coroutine[Any, Any, T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]]`

scikit-build-core (https://github.com/scikit-build/scikit-build-core)
+ src/scikit_build_core/build/wheel.py:99:20: error[no-matching-overload] No overload of bound method `__init__` matches arguments
- Found 57 diagnostics
+ Found 58 diagnostics

django-stubs (https://github.com/typeddjango/django-stubs)
- tests/assert_type/db/models/_enums.py:22:1: error[type-assertion-failure] Type `tuple[Literal["N"], Literal["North"]]` does not match asserted type `str`
+ tests/assert_type/db/models/_enums.py:22:1: error[type-assertion-failure] Type `Any` does not match asserted type `str`
- tests/assert_type/db/models/test_enums.py:90:19: error[subclass-of-final-class] Class `VoidChoices` cannot inherit from final class `BaseEmptyChoices`
- tests/assert_type/db/models/test_enums.py:144:1: error[type-assertion-failure] Type `tuple[Literal[4], _StrPromise]` does not match asserted type `int`
+ tests/assert_type/db/models/test_enums.py:144:1: error[type-assertion-failure] Type `Any` does not match asserted type `int`
- tests/assert_type/db/models/test_enums.py:155:1: error[type-assertion-failure] Type `tuple[Literal["SR"], _StrPromise]` does not match asserted type `str`
+ tests/assert_type/db/models/test_enums.py:155:1: error[type-assertion-failure] Type `Any` does not match asserted type `str`
- tests/assert_type/db/models/test_enums.py:167:1: error[type-assertion-failure] Type `tuple[Literal[1], Literal["Carriage"]]` does not match asserted type `int`
+ tests/assert_type/db/models/test_enums.py:167:1: error[type-assertion-failure] Type `Any` does not match asserted type `int`
- tests/assert_type/db/models/test_enums.py:169:1: error[type-assertion-failure] Type `Literal[Vehicle.__empty__]` does not match asserted type `_StrPromise`
+ tests/assert_type/db/models/test_enums.py:169:1: error[type-assertion-failure] Type `Unknown | _StrPromise` does not match asserted type `_StrPromise`
- tests/assert_type/db/models/test_enums.py:181:1: error[type-assertion-failure] Type `Literal["M"]` does not match asserted type `str`
+ tests/assert_type/db/models/test_enums.py:181:1: error[type-assertion-failure] Type `Any` does not match asserted type `str`
- tests/assert_type/db/models/test_enums.py:183:1: error[type-assertion-failure] Type `Literal[Gender.__empty__]` does not match asserted type `str`
+ tests/assert_type/db/models/test_enums.py:183:1: error[type-assertion-failure] Type `Unknown | Literal["(Undeclared)"]` does not match asserted type `str`
- tests/assert_type/db/models/test_enums.py:223:1: error[type-assertion-failure] Type `Literal[Constants.__empty__]` does not match asserted type `str`
+ tests/assert_type/db/models/test_enums.py:223:1: error[type-assertion-failure] Type `Unknown | Literal["NULL"]` does not match asserted type `str`
- tests/assert_type/db/models/test_enums.py:262:1: error[type-assertion-failure] Type `tuple[Literal["N"], Literal["North"]]` does not match asserted type `str`
+ tests/assert_type/db/models/test_enums.py:262:1: error[type-assertion-failure] Type `Any` does not match asserted type `str`
- tests/assert_type/db/models/test_enums.py:274:1: error[type-assertion-failure] Type `tuple[Literal["N"], Literal["North"]]` does not match asserted type `str`
+ tests/assert_type/db/models/test_enums.py:274:1: error[type-assertion-failure] Type `Any` does not match asserted type `str`
- Found 484 diagnostics
+ Found 483 diagnostics

sympy (https://github.com/sympy/sympy)
- sympy/algebras/quaternion.py:132:22: error[invalid-assignment] Object of type `Basic | int | float | complex | Any` is not assignable to `Expr | int | float | complex`
+ sympy/algebras/quaternion.py:132:22: error[invalid-assignment] Object of type `Basic` is not assignable to `Expr | int | float | complex`
- sympy/algebras/quaternion.py:132:22: error[invalid-assignment] Object of type `Basic | int | float | complex | Any` is not assignable to `Expr | int | float | complex`
+ sympy/algebras/quaternion.py:132:22: error[invalid-assignment] Object of type `Basic` is not assignable to `Expr | int | float | complex`
- sympy/algebras/quaternion.py:132:22: error[invalid-assignment] Object of type `Basic | int | float | complex | Any` is not assignable to `Expr | int | float | complex`
+ sympy/algebras/quaternion.py:132:22: error[invalid-assignment] Object of type `Basic` is not assignable to `Expr | int | float | complex`
- sympy/algebras/quaternion.py:132:22: error[invalid-assignment] Object of type `Basic | int | float | complex | Any` is not assignable to `Expr | int | float | complex`
+ sympy/algebras/quaternion.py:132:22: error[invalid-assignment] Object of type `Basic` is not assignable to `Expr | int | float | complex`
- sympy/algebras/tests/test_quaternion.py:76:10: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/algebras/tests/test_quaternion.py:76:10: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/functions/combinatorial/factorials.py:967:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `Basic | int | float | complex | Any`
+ sympy/functions/combinatorial/factorials.py:967:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `Basic`
- sympy/functions/combinatorial/factorials.py:968:29: error[unresolved-attribute] Attribute `is_nonnegative` is not defined on `int`, `float`, `complex` in union `Basic | int | float | complex | Any`
- sympy/functions/combinatorial/factorials.py:968:47: error[unresolved-attribute] Attribute `is_integer` is not defined on `int`, `complex` in union `Basic | int | float | complex | Any`
- sympy/functions/combinatorial/factorials.py:969:12: error[unresolved-attribute] Attribute `is_zero` is not defined on `int`, `float`, `complex` in union `Basic | int | float | complex | Any`
- sympy/functions/combinatorial/factorials.py:972:13: error[unsupported-operator] Operator `-` is not supported between objects of type `Basic | int | float | complex | Any` and `Literal[1]`
+ sympy/functions/combinatorial/factorials.py:972:13: error[unsupported-operator] Operator `-` is not supported between objects of type `Basic` and `Literal[1]`
- sympy/functions/combinatorial/factorials.py:975:12: error[unresolved-attribute] Attribute `is_integer` is not defined on `int`, `complex` in union `Basic | int | float | complex | Any`
- sympy/functions/combinatorial/factorials.py:976:16: error[unresolved-attribute] Attribute `is_negative` is not defined on `int`, `float`, `complex` in union `Basic | int | float | complex | Any`
- sympy/functions/combinatorial/factorials.py:978:18: error[unresolved-attribute] Attribute `is_number` is not defined on `int`, `float`, `complex` in union `Basic | int | float | complex | Any`
- sympy/functions/combinatorial/factorials.py:984:14: error[unresolved-attribute] Attribute `is_number` is not defined on `int`, `float`, `complex` in union `Basic | int | float | complex | Any`
- sympy/functions/combinatorial/factorials.py:986:26: error[unsupported-operator] Operator `+` is not supported between objects of type `Basic | int | float | complex | Any` and `Literal[1]`
+ sympy/functions/combinatorial/factorials.py:986:26: error[unsupported-operator] Operator `+` is not supported between objects of type `Basic` and `Literal[1]`
- sympy/functions/combinatorial/factorials.py:986:40: error[unsupported-operator] Operator `+` is not supported between objects of type `Basic | int | float | complex | Any` and `Literal[1]`
+ sympy/functions/combinatorial/factorials.py:986:40: error[unsupported-operator] Operator `+` is not supported between objects of type `Basic` and `Literal[1]`
- sympy/functions/combinatorial/factorials.py:986:53: error[unsupported-operator] Operator `-` is not supported between two objects of type `Basic | int | float | complex | Any`
+ sympy/functions/combinatorial/factorials.py:986:53: error[unsupported-operator] Operator `-` is not supported between two objects of type `Basic`
- sympy/geometry/point.py:1296:25: error[unresolved-attribute] Attribute `tolist` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/geometry/point.py:1296:25: error[unresolved-attribute] Attribute `tolist` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/geometry/polygon.py:1501:12: error[unresolved-attribute] Attribute `is_Number` is not defined on `int`, `float`, `complex` in union `Basic | int | float | complex | Any`
- sympy/geometry/polygon.py:1502:20: error[invalid-argument-type] Argument to function `as_int` is incorrect: Expected `SupportsIndex`, found `Basic | int | float | complex | Any`
+ sympy/geometry/polygon.py:1502:20: error[invalid-argument-type] Argument to function `as_int` is incorrect: Expected `SupportsIndex`, found `Basic`
- sympy/geometry/polygon.py:1503:16: error[unsupported-operator] Operator `<` is not supported between objects of type `Basic | int | float | complex | Any` and `Literal[3]`
+ sympy/geometry/polygon.py:1503:16: error[unsupported-operator] Operator `<` is not supported between objects of type `Basic` and `Literal[3]`
- sympy/geometry/polygon.py:1510:40: error[unresolved-attribute] Attribute `is_number` is not defined on `int`, `float`, `complex` in union `Basic | int | float | complex | Any`
- sympy/integrals/prde.py:90:11: error[unresolved-attribute] Attribute `as_poly` is not defined on `int` in union `int | Unknown`
+ sympy/integrals/prde.py:90:11: error[unresolved-attribute] Attribute `as_poly` is not defined on `int` in union `Unknown | int`
- sympy/integrals/prde.py:90:61: error[unresolved-attribute] Attribute `as_poly` is not defined on `int` in union `int | Unknown`
+ sympy/integrals/prde.py:90:61: error[unresolved-attribute] Attribute `as_poly` is not defined on `int` in union `Unknown | int`
- sympy/integrals/prde.py:91:10: error[unresolved-attribute] Attribute `as_poly` is not defined on `int` in union `int | Unknown`
+ sympy/integrals/prde.py:91:10: error[unresolved-attribute] Attribute `as_poly` is not defined on `int` in union `Unknown | int`
- sympy/integrals/tests/test_heurisch.py:390:17: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
+ sympy/integrals/tests/test_heurisch.py:391:26: error[not-subscriptable] Cannot subscript object of type `Expr` with no `__getitem__` method
+ sympy/matrices/decompositions.py:1321:16: error[unresolved-attribute] Attribute `diagonalize` is not defined on `Expr` in union `MatrixBase | Expr`
+ sympy/matrices/decompositions.py:1336:16: error[unresolved-attribute] Attribute `diagonalize` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/matrices/decompositions.py:1321:16: error[unresolved-attribute] Attribute `diagonalize` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
- sympy/matrices/decompositions.py:1334:13: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MatrixBase`
- sympy/matrices/decompositions.py:1336:16: error[unresolved-attribute] Attribute `diagonalize` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
- sympy/matrices/decompositions.py:1348:13: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MatrixBase`
- sympy/matrices/decompositions.py:1350:12: error[invalid-return-type] Return type does not match returned value: expected `tuple[Tmat@_singular_value_decomposition, Tmat@_singular_value_decomposition, Tmat@_singular_value_decomposition]`, found `tuple[Unknown | MatrixBase, MatrixBase, MatrixBase | Unknown]`
+ sympy/matrices/decompositions.py:1350:12: error[invalid-return-type] Return type does not match returned value: expected `tuple[Tmat@_singular_value_decomposition, Tmat@_singular_value_decomposition, Tmat@_singular_value_decomposition]`, found `tuple[MatrixBase | Expr | Unknown, MatrixBase, MatrixBase | Expr | Unknown]`
- sympy/matrices/eigen.py:328:22: error[invalid-argument-type] Argument to bound method `_as_type` is incorrect: Expected `MatrixBase`, found `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Unknown`
- sympy/matrices/expressions/hadamard.py:82:22: error[invalid-argument-type] Argument to function `validate_matadd_integer` is incorrect: Expected `MatrixExpr`, found `Any | Basic | int | float | complex`
+ sympy/matrices/expressions/hadamard.py:82:22: error[invalid-argument-type] Argument to function `validate_matadd_integer` is incorrect: Expected `MatrixExpr`, found `Basic`
- sympy/matrices/expressions/kronecker.py:110:16: error[unresolved-attribute] Attribute `is_Identity` is not defined on `Basic`, `int`, `float`, `complex` in union `Any | Basic | int | float | complex`
- sympy/matrices/expressions/kronecker.py:111:33: error[unresolved-attribute] Attribute `rows` is not defined on `Basic`, `int`, `float`, `complex` in union `Any | Basic | int | float | complex`
+ sympy/matrices/expressions/kronecker.py:110:16: error[unresolved-attribute] Object of type `Basic` has no attribute `is_Identity`
+ sympy/matrices/expressions/kronecker.py:111:33: error[unresolved-attribute] Object of type `Basic` has no attribute `rows`
- sympy/matrices/expressions/matadd.py:61:22: error[invalid-argument-type] Argument to function `validate_matadd_integer` is incorrect: Expected `MatrixExpr`, found `Unknown | Basic | int | float | complex`
+ sympy/matrices/expressions/matadd.py:61:22: error[invalid-argument-type] Argument to function `validate_matadd_integer` is incorrect: Expected `MatrixExpr`, found `Unknown | Basic`
- sympy/matrices/expressions/tests/test_derivatives.py:552:26: error[unsupported-operator] Operator `+` is not supported between two objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/expressions/tests/test_derivatives.py:552:26: error[unsupported-operator] Operator `+` is not supported between two objects of type `MatrixBase | Expr`
- sympy/matrices/expressions/tests/test_matadd.py:37:12: error[unsupported-operator] Operator `+` is not supported between objects of type `MatrixBase` and `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/expressions/tests/test_matadd.py:37:12: error[unsupported-operator] Operator `+` is not supported between objects of type `MatrixBase` and `MatrixBase | Expr`
+ sympy/matrices/expressions/tests/test_matmul.py:159:68: error[unresolved-attribute] Attribute `as_explicit` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/matrices/expressions/tests/test_matmul.py:159:68: error[unresolved-attribute] Attribute `as_explicit` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
- sympy/matrices/expressions/tests/test_matpow.py:124:46: error[unsupported-operator] Operator `**` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `Literal[2]`
- sympy/matrices/expressions/tests/test_permutation.py:28:12: error[unresolved-attribute] Attribute `as_explicit` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/expressions/tests/test_permutation.py:28:12: error[unresolved-attribute] Attribute `as_explicit` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/matrices/inverse.py:384:11: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MatrixBase`
+ sympy/matrices/inverse.py:385:11: error[unsupported-operator] Operator `-` is not supported between objects of type `MatrixBase` and `MatrixBase | Expr | Unknown`
- sympy/matrices/inverse.py:392:11: error[unsupported-operator] Unary operator `-` is not supported for object of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
- sympy/matrices/inverse.py:393:19: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MatrixBase | Expr`
+ sympy/matrices/inverse.py:393:11: error[unsupported-operator] Operator `+` is not supported between objects of type `MatrixBase` and `MatrixBase | Expr | Unknown`
- sympy/matrices/inverse.py:393:22: error[unsupported-operator] Unary operator `-` is not supported for object of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
- sympy/matrices/matrixbase.py:2955:13: error[unsupported-operator] Operator `*=` is not supported between objects of type `T2'return@call_highest_priority` and `Self@_eval_pow_by_cayley`
- sympy/matrices/matrixbase.py:2955:13: error[unsupported-operator] Operator `*=` is not supported between objects of type `T1'return@call_highest_priority` and `Self@_eval_pow_by_cayley`
- sympy/matrices/matrixbase.py:3046:5: error[invalid-argument-type] Argument is incorrect: Expected `(T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr, T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr, /) -> T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`, found `Overload[[Self](self, other: Self) -> Self, (self, other: MatrixBase) -> MatrixBase, (self, other: Expr) -> MatrixBase]`
+ sympy/matrices/matrixbase.py:3046:5: error[invalid-argument-type] Argument is incorrect: Expected `(MatrixBase, MatrixBase | Expr, /) -> MatrixBase | Expr`, found `Overload[[Self](self, other: Self) -> Self, (self, other: MatrixBase) -> MatrixBase, (self, other: Expr) -> MatrixBase]`
- sympy/matrices/matrixbase.py:3944:39: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/matrixbase.py:3944:39: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/matrixbase.py:4640:16: error[invalid-return-type] Return type does not match returned value: expected `Self@D`, found `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/matrixbase.py:4640:16: error[invalid-return-type] Return type does not match returned value: expected `Self@D`, found `MatrixBase | Expr`
- sympy/matrices/matrixbase.py:4748:16: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/matrixbase.py:4748:16: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/matrixbase.py:4922:13: error[unsupported-operator] Operator `*=` is not supported between objects of type `T2'return@call_highest_priority` and `Self@analytic_func`
- sympy/matrices/matrixbase.py:4922:13: error[unsupported-operator] Operator `*=` is not supported between objects of type `T1'return@call_highest_priority` and `Self@analytic_func`
- sympy/matrices/matrixbase.py:5073:28: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `Self@log`
- sympy/matrices/matrixbase.py:5076:19: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `Self@log`
+ sympy/matrices/matrixbase.py:5073:28: error[invalid-argument-type] Argument is incorrect: Expected `Self@log`, found `MatrixBase | Expr | Unknown`
+ sympy/matrices/matrixbase.py:5078:16: error[invalid-return-type] Return type does not match returned value: expected `Self@log`, found `MatrixBase | Expr | Unknown`
- sympy/matrices/solvers.py:637:27: error[invalid-argument-type] Argument to bound method `vstack` is incorrect: Argument type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Unknown` does not satisfy upper bound `MatrixBase` of type variable `Self`
- sympy/matrices/solvers.py:637:27: error[invalid-argument-type] Argument to bound method `vstack` is incorrect: Expected `Tmat@_gauss_jordan_solve`, found `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Unknown`
- sympy/matrices/solvers.py:976:16: error[unresolved-attribute] Attribute `solve` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/solvers.py:976:16: error[unresolved-attribute] Attribute `solve` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/matrices/solvers.py:976:30: error[invalid-argument-type] Argument to bound method `solve` is incorrect: Argument type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` does not satisfy upper bound `MatrixBase` of type variable `Self`
+ sympy/matrices/solvers.py:976:30: error[invalid-argument-type] Argument to bound method `solve` is incorrect: Argument type `MatrixBase | Expr` does not satisfy upper bound `MatrixBase` of type variable `Self`
- sympy/matrices/solvers.py:976:30: error[invalid-argument-type] Argument to bound method `solve` is incorrect: Expected `MatrixBase`, found `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/solvers.py:976:30: error[invalid-argument-type] Argument to bound method `solve` is incorrect: Expected `MatrixBase`, found `MatrixBase | Expr`
- sympy/matrices/sparse.py:418:16: error[unresolved-attribute] Attribute `inv` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/sparse.py:418:16: error[unresolved-attribute] Attribute `inv` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/matrices/tests/test_decompositions.py:24:12: error[unresolved-attribute] Attribute `permute_rows` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_decompositions.py:24:12: error[unresolved-attribute] Attribute `permute_rows` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/matrices/tests/test_decompositions.py:33:12: error[unresolved-attribute] Attribute `permute_rows` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_decompositions.py:33:12: error[unresolved-attribute] Attribute `permute_rows` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/matrices/tests/test_decompositions.py:43:12: error[unresolved-attribute] Attribute `permute_rows` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_decompositions.py:43:12: error[unresolved-attribute] Attribute `permute_rows` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/matrices/tests/test_decompositions.py:52:12: error[unresolved-attribute] Attribute `permute_rows` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_decompositions.py:52:12: error[unresolved-attribute] Attribute `permute_rows` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/matrices/tests/test_decompositions.py:58:12: error[unresolved-attribute] Attribute `permute_rows` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_decompositions.py:58:12: error[unresolved-attribute] Attribute `permute_rows` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/matrices/tests/test_decompositions.py:78:19: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:85:19: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:91:19: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:104:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:111:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:124:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:132:21: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
+ sympy/matrices/tests/test_decompositions.py:132:12: error[no-matching-overload] No overload of function `simplify` matches arguments
- sympy/matrices/tests/test_decompositions.py:289:10: error[unresolved-attribute] Attribute `applyfunc` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_decompositions.py:289:10: error[unresolved-attribute] Attribute `applyfunc` is not defined on `Expr` in union `MatrixBase | Expr`
+ sympy/matrices/tests/test_decompositions.py:394:16: error[no-matching-overload] No overload of function `simplify` matches arguments
+ sympy/matrices/tests/test_decompositions.py:395:16: error[no-matching-overload] No overload of function `simplify` matches arguments
- sympy/matrices/tests/test_decompositions.py:291:13: error[unsupported-operator] Operator `-` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:346:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:349:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:356:23: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:394:25: error[unsupported-operator] Operator `*` is not supported between objects of type `Unknown | T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `Unknown | MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:395:25: error[unsupported-operator] Operator `*` is not supported between objects of type `Unknown | T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `Unknown | MutableDenseMatrix`
- sympy/matrices/tests/test_decompositions.py:396:16: error[unresolved-attribute] Attribute `H` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `Unknown | T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_decompositions.py:396:16: error[unresolved-attribute] Attribute `H` is not defined on `Expr` in union `Unknown | MatrixBase | Expr`
- sympy/matrices/tests/test_decompositions.py:397:16: error[unresolved-attribute] Attribute `H` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `Unknown | T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_decompositions.py:397:16: error[unresolved-attribute] Attribute `H` is not defined on `Expr` in union `Unknown | MatrixBase | Expr`
- sympy/matrices/tests/test_decompositions.py:440:22: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
+ sympy/matrices/tests/test_decompositions.py:440:13: error[no-matching-overload] No overload of function `simplify` matches arguments
- sympy/matrices/tests/test_decompositions.py:452:21: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
+ sympy/matrices/tests/test_decompositions.py:452:12: error[no-matching-overload] No overload of function `simplify` matches arguments
- sympy/matrices/tests/test_decompositions.py:465:21: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
+ sympy/matrices/tests/test_decompositions.py:465:12: error[no-matching-overload] No overload of function `simplify` matches arguments
- sympy/matrices/tests/test_decompositions.py:476:21: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
+ sympy/matrices/tests/test_decompositions.py:476:12: error[no-matching-overload] No overload of function `simplify` matches arguments
- sympy/matrices/tests/test_decompositions.py:489:21: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
+ sympy/matrices/tests/test_decompositions.py:489:12: error[no-matching-overload] No overload of function `simplify` matches arguments
+ sympy/matrices/tests/test_eigen.py:407:20: error[invalid-argument-type] Argument to function `max` is incorrect: Expected `Iterable[Unknown]`, found `MatrixBase | Unknown`
+ sympy/matrices/tests/test_eigen.py:478:12: error[no-matching-overload] No overload of function `simplify` matches arguments
+ sympy/matrices/tests/test_eigen.py:493:12: error[unresolved-attribute] Attribute `applyfunc` is not defined on `Expr` in union `MatrixBase | Expr | Unknown`
- sympy/matrices/tests/test_eigen.py:258:16: error[unresolved-attribute] Attribute `n` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
- sympy/matrices/tests/test_eigen.py:307:14: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `ImmutableDenseMatrix`
- sympy/matrices/tests/test_eigen.py:308:14: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_eigen.py:323:15: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `ImmutableDenseMatrix`
- sympy/matrices/tests/test_eigen.py:324:15: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_eigen.py:365:14: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `ImmutableDenseMatrix`
- sympy/matrices/tests/test_eigen.py:366:14: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_eigen.py:381:15: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `ImmutableDenseMatrix`
- sympy/matrices/tests/test_eigen.py:382:15: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_eigen.py:406:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_eigen.py:478:21: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_eigen.py:493:13: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_eigen.py:794:19: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_matrices.py:202:12: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:202:12: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:203:12: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:203:12: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:204:12: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:204:12: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:205:12: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:205:12: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:206:12: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:206:12: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:207:12: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:207:12: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:214:16: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:214:16: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:215:16: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:215:16: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:216:16: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:216:16: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:217:16: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:217:16: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:218:16: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:218:16: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:219:16: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:219:16: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrices.py:222:40: error[invalid-argument-type] Argument to bound method `multiply_elementwise` is incorrect: Expected `MatrixBase`, found `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_matrices.py:222:40: error[invalid-argument-type] Argument to bound method `multiply_elementwise` is incorrect: Expected `MatrixBase`, found `MatrixBase | Expr`
- sympy/matrices/tests/test_matrices.py:395:16: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:1740:12: error[no-matching-overload] No overload of function `simplify` matches arguments
- sympy/matrices/tests/test_matrices.py:1582:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_matrices.py:1588:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_matrices.py:1595:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_matrices.py:1600:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_matrices.py:1608:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_matrices.py:1617:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_matrices.py:1740:21: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_matrices.py:2558:12: error[unsupported-operator] Operator `*` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `MutableDenseMatrix`
- sympy/matrices/tests/test_matrices.py:2681:25: error[unsupported-operator] Operator `*` is not supported between objects of type `Unknown | T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `Unknown | MutableDenseMatrix`
- sympy/matrices/tests/test_matrices.py:2682:25: error[unsupported-operator] Operator `*` is not supported between objects of type `Unknown | T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr` and `Unknown | MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2681:16: error[no-matching-overload] No overload of function `simplify` matches arguments
+ sympy/matrices/tests/test_matrices.py:2682:16: error[no-matching-overload] No overload of function `simplify` matches arguments
- sympy/matrices/tests/test_matrices.py:2683:16: error[unresolved-attribute] Attribute `H` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `Unknown | T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_matrices.py:2683:16: error[unresolved-attribute] Attribute `H` is not defined on `Expr` in union `Unknown | MatrixBase | Expr`
- sympy/matrices/tests/test_matrices.py:2684:16: error[unresolved-attribute] Attribute `H` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `Unknown | T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_matrices.py:2684:16: error[unresolved-attribute] Attribute `H` is not defined on `Expr` in union `Unknown | MatrixBase | Expr`
- sympy/matrices/tests/test_matrices.py:2729:16: error[unresolved-attribute] Attribute `H` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `Unknown | T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_matrices.py:2729:16: error[unresolved-attribute] Attribute `H` is not defined on `Expr` in union `Unknown | MatrixBase | Expr`
- sympy/matrices/tests/test_matrices.py:2747:25: error[unresolved-attribute] Attribute `H` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `Unknown | T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_matrices.py:2747:25: error[unresolved-attribute] Attribute `H` is not defined on `Expr` in union `Unknown | MatrixBase | Expr`
- sympy/matrices/tests/test_matrices.py:3056:33: error[unresolved-attribute] Attribute `analytic_func` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_matrices.py:3056:33: error[unresolved-attribute] Attribute `analytic_func` is not defined on `Expr` in union `MatrixBase | Expr`
- sympy/matrices/tests/test_matrices.py:3072:60: error[unresolved-attribute] Attribute `exp` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority`, `Expr` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Expr`
+ sympy/matrices/tests/test_matrices.py:3072:60: error[unresolved-attribute] Attribute `exp` is not defined on `Expr` in union `MatrixBase | Expr`
+ sympy/matrices/tests/test_matrices.py:3479:12: error[unresolved-attribute] Attribute `rank` is not defined on `MatrixExpr` in union `MatrixBase | MatrixExpr | Unknown`
+ sympy/matrices/tests/test_matrices.py:3480:12: error[unresolved-attribute] Attribute `rank` is not defined on `MatrixExpr` in union `MatrixBase | MatrixExpr | Unknown`
- sympy/matrices/tests/test_matrices.py:3478:12: error[unresolved-attribute] Attribute `rank` is not defined on `T2'return@call_highest_priority`, `T1'return@call_highest_priority` in union `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Unknown`
- sympy/matrices/tests/test_matrices.py:3479:13: error[unsupported-operator] Operator `**` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Unknown` and `Literal[2]`
- sympy/matrices/tests/test_matrices.py:3480:13: error[unsupported-operator] Operator `**` is not supported between objects of type `T2'return@call_highest_priority | T1'return@call_highest_priority | MatrixBase | Unknown` and `Literal[3]`
- sympy/matrices/tests/test_matrixbase.py:964:12: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrixbase.py:964:12: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrixbase.py:965:12: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrixbase.py:965:12: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrixbase.py:966:12: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrixbase.py:966:12: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrixbase.py:967:12: error[not-subscriptable] Cannot subscript object of type `T2'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrixbase.py:967:12: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `__getitem__` method
- sympy/matrices/tests/test_matrixbase.py:968:12: error[not-subscriptable] Cannot subscript object of type `T1'return@call_highest_priority` with no `

... (truncated 382 lines) ...

@silamon
Copy link
Contributor Author

silamon commented Dec 28, 2025

Aside from some failing CI, there's still 2 more issues that got identified:

from enum import Enum

class Color(Enum):
    _value_: int
    RED = 1

reveal_type(Color.RED.value)  # revealed: Literal[1]
reveal_type(Color.RED._value_)  # revealed: Literal[1]

The _value_ revealed still holds Literal[1] there, while some other type checkers will show up int. What would we do here?

Second, this example came out the comformance testing:

from enum import Enum

class Planet2(Enum):
    _value_: str

    def __init__(self, value: int, mass: float, radius: float):
        self._value_ = value  # E

    MERCURY = (1, 3.303e23, 2.4397e6)

It's throwing an diagnostic currently on the last MERCURY line, while it shouldn't. While it's obviously what's happening here, it's not so obviously to me how to fix it.

@MichaReiser
Copy link
Member

Thank you for working on this. Almost the entire team is out this week. It may take a few days before someone finds time to answer your question. We're sorry for that. Happy holidays.

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

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

Nice, thank you! Sorry for the delay in reviewing this!!

@AlexWaygood
Copy link
Member

from enum import Enum

class Color(Enum):
    _value_: int
    RED = 1

reveal_type(Color.RED.value)  # revealed: Literal[1]
reveal_type(Color.RED._value_)  # revealed: Literal[1]

The value revealed still holds Literal[1] there, while some other type checkers will show up int. What would we do here?

I think inferring Literal[1] there is fine, since Literal[1] is assignable to int. Possibly it's unsound to infer Literal[1] if the enum class has a custom constructor method...? But the enum class in your example does not.

Second, this example came out the comformance testing:

from enum import Enum

class Planet2(Enum):
    _value_: str

    def __init__(self, value: int, mass: float, radius: float):
        self._value_ = value  # E

    MERCURY = (1, 3.303e23, 2.4397e6)

It's throwing an diagnostic currently on the last MERCURY line, while it shouldn't. While it's obviously what's happening here, it's not so obviously to me how to fix it.

The spec explains what to do here at https://typing.python.org/en/latest/spec/enums.html#member-values

@AlexWaygood AlexWaygood self-assigned this Jan 16, 2026
@silamon silamon force-pushed the enum_value_annotation branch 3 times, most recently from 13c83bc to 8e2b01e Compare January 23, 2026 20:37
@silamon
Copy link
Contributor Author

silamon commented Jan 23, 2026

I've applied your patch (thanks for that), and worked further on it. It's a better place than what I had first.
EnumClassInfo and EnumMetadata feels like they could be combined.

Conformance testing shows what I expected, unit tests succeed including the stub example.
I'll await review and then will include fixes for the markdown linting, which still fails.

Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

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

Thank you, this looks good!

I'll await review and then will include fixes for the markdown linting

For future reference: this should be a trivial fix with uvx prek -a, so it probably makes more sense to just go ahead and fix it rather than waiting for review first?

Comment on lines 79 to 84
/// Extracts the expected enum member type from `__init__` method parameters.
fn extract_init_member_type(
db: &'db dyn Db,
_class: StaticClassLiteral<'db>,
scope: ScopeId<'db>,
) -> Option<Type<'db>> {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we can assume that the first parameter of an Enum class's __init__ method always provides the _value_ type. I think we need to look at the type assigned to self._value_ inside the enum's __init__ method rather than attempting to extract the annotated type of the first parameter of the __init__ method

Copy link
Contributor

Choose a reason for hiding this comment

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

As I understand it, it's the entire signature of __init__ that determines the expected type assigned to members. If __init__ takes multiple arguments, it's a tuple of those types that we expect. If __init__ takes only a single argument, it's that type that is expected. That's what's implemented here, and it looks correct to me.

If we are discussing the type ultimately revealed by accessing _value_ on a member, that may be something else? But it also doesn't seem to be touched by this PR.

Copy link
Member

Choose a reason for hiding this comment

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

Oh I see, sorry. Yes, looks like you're right.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need to look at the type assigned to self._value_ inside the enum's __init__ method

I don't think other type checkers do this. Pyright appears to just fallback to Any as the type of the _value_ member, if there is an __init__.

So I do think that's an improvement we need (either the pyright fallback, or the more complex analysis you suggest), and it should probably go in this PR, although technically I think this PR is a strict improvement either way. Here's a test case:

from enum import Enum

class MyEnum(Enum):
    def __init__(self, x: int, y: str):
        self._value_ = y

    RED = (1, "red")
    BLUE = (2, "blue")

reveal_type(MyEnum.RED._value_)

Pyright reveals Any here (but reveals the precise assigned type if there is no __init__). We currently (and in this PR) reveal tuple[Literal[1], Literal["red"]], which is wrong. The ideal thing to reveal would be Literal["red"], but I think that would be quite hard and not worth it. Revealing str instead of Any doesn't seem too hard (though I'm still not sure it's worth it, given that there will always be more complex cases where we have to fall back to a union, if there are multiple assignments to _value_ in __init__, and that union could cause false positives.)

Copy link
Member

@AlexWaygood AlexWaygood Jan 23, 2026

Choose a reason for hiding this comment

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

Yeah, I agree it's out of scope for this PR, which as you say is a strict improvement over the status quo. Sorry for getting confused!

If the enum has a custom __init__ method I think we would ideally fallback to the _value_ annotation (either in __init__ or in the class body), if it's available, and fallback to Any if not. But if that's hard I'd also be okay with only falling back to _value_ if it's provided in the class body and ignoring assignments in __init__.

Copy link
Member

Choose a reason for hiding this comment

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

and to be clear, we should always make sure .value is consistent with ._value_, so this has implications for the type we store in the EnumMetadata::members mapping from enum members to their values.

Copy link
Contributor

@carljm carljm Jan 23, 2026

Choose a reason for hiding this comment

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

I think relatedly, we should probably revisit the earlier decision in this PR that it's OK for _value_ to reveal Literal[1] in this example, rather than int:

from enum import Enum

class MyEnum(Enum):
    _value_: int
    RED = 1
    BLUE = 2

reveal_type(MyEnum.RED._value_)

The reason is that it's possible for the RHS of these assignments to be e.g. a call that returns Any or Unknown, and in that case we should really reveal int, not Any or Unknown. In a sense this is just another version of astral-sh/ty#136, where it does matter that we respect the explicit type annotation given by the user.

Copy link
Contributor

@carljm carljm Jan 23, 2026

Choose a reason for hiding this comment

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

(Sorry, wasn't getting live updates on the PR thread, and posted all my comments here, and the main request-changes comment, before I saw any of your comments. I kind of changed my mind about these issues being out of scope for this PR, because I think the need to connect annotated _value_ type to eventual inferred type of _value_ / value member attributes could significantly change the implementation here.)

Copy link
Member

Choose a reason for hiding this comment

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

it makes me a bit sad that we'll lose literal types for .value for things like this -- Literal types seem much more important for enum values than for most other areas of Python typing:

class Foo(Enum):
    _value_: str
    X = 'A'
    Y = 'B'

but I do agree that it's important we don't infer Any or Unknown for .value for things like this:

def returns_unknown():
    return "foo"

class Bar(Enum):
    _value_: str
    X = returns_unknown()
    Y = returns_unknown()

Since enums are heavily special-cased anyway, it's possible we could do some kind of syntactic check here to see whether the type was inferred due to a literal value on the right-hand side (which will be by far the most common case) or something else, like a function call.

But given that _value_ annotations are pretty rare anyway, maybe we shouldn't worry about this too much. I definitely don't think we should make a rule that says we prefer the inferred type only if the inferred type is fully static; that would be very inconsistent with what e.g. mypy does, what users expect, and what I believe we're currently planning to do to address astral-sh/ty#136 (though the title of that issue still mentions only preferring "more precise" declared types).

Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

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

Given the discussion in the sub-thread, I think we should update this PR so that a) we always respect explicit _value_ annotation, if there is one, when inferring a type for accessing _value_ or value attribute on an enum member, and b) we fall back to Any for our inference of _value_ / value attributes if the enum has an __init__ method. (I think that if we want to do anything more precise than Any here -- and I'm not sure we should -- that's subtle enough that it should be a separate PR.)

I do also think it's worth considering just merging EnumClassInfo into EnumMetadata. I don't think this is critical, but it's also not clear to me that there's any benefit to them being separate. (And given the above changes will require having value_sunder_type also influence our inference of _value_ / value attribute types, it may simplify that implementation anyway.)

@silamon
Copy link
Contributor Author

silamon commented Jan 24, 2026

I'm going to work further on this later, thank you for your feedback.

@silamon silamon force-pushed the enum_value_annotation branch from cebc4ae to 39a1c81 Compare February 7, 2026 09:16
@silamon
Copy link
Contributor Author

silamon commented Feb 7, 2026

I've did the remarks:

  • Merged the EnumClassInfo into EnumMetadata
  • Removed the logic that resolved the type when a init exists and return Any type.

Somehow along the way I started to introduce something that resolves many types to Unknown, which causes a lot of tests to fail. I haven't been able to find it yet, if somebody could help me out I would appreciate it.

@sharkdp sharkdp removed their request for review February 9, 2026 09:57
@carljm
Copy link
Contributor

carljm commented Feb 13, 2026

@charliermarsh this might be another one in the queue that you could take a look at what it needs to get land-ready?

@astral-sh-bot
Copy link

astral-sh-bot bot commented Feb 14, 2026

Memory usage report

Summary

Project Old New Diff Outcome
prefect 710.27MB 710.57MB +0.04% (312.78kB)
sphinx 273.81MB 273.89MB +0.03% (86.52kB)
trio 121.47MB 121.49MB +0.02% (29.32kB)
flake8 49.57MB 49.58MB +0.02% (10.06kB)

Significant changes

Click to expand detailed breakdown

prefect

Name Old New Diff Outcome
enum_metadata 2.36MB 2.67MB +12.99% (314.20kB)
Type<'db>::class_member_with_policy_ 16.84MB 16.84MB -0.00% (852.00B)
infer_definition_types 85.96MB 85.96MB +0.00% (676.00B)
StaticClassLiteral<'db>::try_metaclass_ 1.17MB 1.17MB +0.04% (452.00B)
Type<'db>::class_member_with_policy_::interned_arguments 9.06MB 9.06MB -0.00% (312.00B)
Type<'db>::member_lookup_with_policy_::interned_arguments 5.35MB 5.35MB -0.01% (312.00B)
Type<'db>::member_lookup_with_policy_ 15.16MB 15.16MB -0.00% (288.00B)
is_redundant_with_impl::interned_arguments 5.57MB 5.57MB -0.00% (264.00B)
FunctionType 8.30MB 8.30MB -0.00% (224.00B)
all_narrowing_constraints_for_expression 5.52MB 5.52MB -0.00% (216.00B)
StaticClassLiteral<'db>::is_typed_dict_ 599.54kB 599.75kB +0.04% (216.00B)
is_redundant_with_impl 5.60MB 5.60MB -0.00% (144.00B)
OverloadLiteral 3.34MB 3.34MB -0.00% (112.00B)
EnumLiteralType 7.31kB 7.22kB -1.28% (96.00B)
StaticClassLiteral<'db>::inheritance_cycle_ 348.56kB 348.63kB +0.02% (72.00B)
... 6 more

sphinx

Name Old New Diff Outcome
enum_metadata 652.02kB 737.72kB +13.14% (85.70kB)
infer_definition_types 24.30MB 24.30MB +0.00% (536.00B)
StaticClassLiteral<'db>::is_typed_dict_ 182.14kB 182.25kB +0.06% (108.00B)
infer_scope_types_impl 15.63MB 15.63MB +0.00% (84.00B)
use_def_map 139.75kB 139.80kB +0.04% (60.00B)
place_table 226.70kB 226.76kB +0.03% (60.00B)

trio

Name Old New Diff Outcome
enum_metadata 208.91kB 238.17kB +14.01% (29.26kB)
StaticClassLiteral<'db>::try_metaclass_ 125.78kB 126.22kB +0.35% (452.00B)
infer_definition_types 7.59MB 7.59MB -0.00% (396.00B)
infer_scope_types_impl 4.79MB 4.79MB +0.00% (228.00B)
FunctionType 1.50MB 1.50MB -0.01% (224.00B)
OverloadLiteral 439.22kB 439.11kB -0.02% (112.00B)
StaticClassLiteral<'db>::is_typed_dict_ 65.74kB 65.84kB +0.16% (108.00B)
StaticClassLiteral<'db>::inheritance_cycle_ 34.27kB 34.34kB +0.21% (72.00B)
FunctionLiteral 240.44kB 240.38kB -0.03% (64.00B)

flake8

Name Old New Diff Outcome
enum_metadata 57.34kB 65.77kB +14.71% (8.43kB)
infer_definition_types 1.89MB 1.89MB +0.05% (1.05kB)
StaticClassLiteral<'db>::is_typed_dict_ 27.77kB 27.98kB +0.76% (216.00B)
place_by_id 143.60kB 143.72kB +0.08% (124.00B)
place_table 25.08kB 25.20kB +0.47% (120.00B)
place_by_id::interned_arguments 106.66kB 106.73kB +0.07% (72.00B)
use_def_map 19.69kB 19.75kB +0.30% (60.00B)

rayzeller added a commit to rayzeller/ruff that referenced this pull request Feb 20, 2026
…pport

Strip the `_value_` annotation lookup logic (`enum_value_annotation_type`
and `own_value_annotation`) to avoid overlap with astral-sh#22228, which handles
`_value_` semantics more broadly. Custom `__new__` enums now always fall
back to `Any` for the member value type.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
rayzeller added a commit to rayzeller/ruff that referenced this pull request Feb 20, 2026
…pport

Strip the `_value_` annotation lookup logic (`enum_value_annotation_type`
and `own_value_annotation`) to avoid overlap with astral-sh#22228, which handles
`_value_` semantics more broadly. Custom `__new__` enums now always fall
back to `Any` for the member value type.

Also remove the redundant known-class skip list from `has_custom_enum_new`
— the vendored path check already covers all stdlib classes.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
rayzeller added a commit to rayzeller/ruff that referenced this pull request Feb 20, 2026
…new`

Remove the `_value_` annotation lookup logic to avoid overlap with astral-sh#22228,
which handles `_value_` semantics more broadly. Custom `__new__` enums now
always fall back to `Any`. Also remove the redundant known-class skip list
from `has_custom_enum_new` — the vendored path check already covers all
stdlib classes.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

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

Just reviewed the tests for now -- will review the code once it looks like the tests are specifying the right semantics.

It looks to me like @AlexWaygood 's comments from a few days ago were exactly right -- no need to wait for me to confirm!

self._value_ = value # error: [invalid-assignment]

MERCURY = (1, 3.303e23, 2.4397e6)
SATURN = "saturn"
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah there should be an error on this line, we should be validating against the __init__ signature. I think the previous version of this PR did that correctly?

### `_value_` annotation with `__init__`

When `__init__` is defined, member values are passed through `__init__` rather than directly
assigned to `_value_`, so we fall back to `Any` for member value validation. The `_value_`
Copy link
Contributor

Choose a reason for hiding this comment

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

We shouldn't fall back to Any for validation. We should validate against the __init__ signature.

We should fall back to Any for the type of .value or ._value_ on individual members, if there is no annotated _value_ type on the enum class. (If there is, we should use that -- and validate assignments to self._value_ in __init__ according to that annotation, as you already do.)

Comment on lines 159 to 160
When `__init__` is defined but no explicit `_value_` annotation exists, we also fall back to `Any`
for member value validation:
Copy link
Contributor

Choose a reason for hiding this comment

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

We should never "fall back to Any for member value validation." What this test (correctly) shows is that we are falling back to Any for the type of .value and ._value_ on the resulting members. But this comment is wrong.

Comment on lines 177 to 192
### Inherited `_value_` annotation

A `_value_` annotation on a parent enum is not inherited by subclasses for the purpose of member
value validation:

```py
from enum import Enum

class Base(Enum):
_value_: int

class Child(Base):
A = 1
B = "not checked against int"

reveal_type(Child.A.value) # revealed: Literal[1]
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this specified, or just something observed in the ecosystem?

Copy link
Member

Choose a reason for hiding this comment

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

I think it's unspecified... I think Pyright does inherit _value_, mypy does not.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this PR currently doesn't inherit __init__ from a base class, and it needs to do so in order to match runtime behavior on e.g. this example:

from enum import Enum

class Base(Enum):
    def __init__(self, a: int, b: str):
        self._value_ = a

class Child(Base):
    A = (1, "foo")
    B = "should be checked against __init__"  # should error, currently doesn't

reveal_type(Child.A.value)  # should reveal `Any`, currently reveals `tuple[Literal[1], Literal["foo"]]`

At runtime A and B do pass through Base.__init__, so we should also model that.

And once we model that correctly, I think the only consistent/correct approach is also to inherit _value_ annotation from a base.

@charliermarsh charliermarsh force-pushed the enum_value_annotation branch 2 times, most recently from 3a7d627 to 6ddf331 Compare February 21, 2026 02:02
@charliermarsh
Copy link
Member

(We realized offline that I had addressed some feedback but pushed to the wrong branch... So I just updated this PR now.)

Comment on lines 177 to 192
### Inherited `_value_` annotation

A `_value_` annotation on a parent enum is not inherited by subclasses for the purpose of member
value validation:

```py
from enum import Enum

class Base(Enum):
_value_: int

class Child(Base):
A = 1
B = "not checked against int"

reveal_type(Child.A.value) # revealed: Literal[1]
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this PR currently doesn't inherit __init__ from a base class, and it needs to do so in order to match runtime behavior on e.g. this example:

from enum import Enum

class Base(Enum):
    def __init__(self, a: int, b: str):
        self._value_ = a

class Child(Base):
    A = (1, "foo")
    B = "should be checked against __init__"  # should error, currently doesn't

reveal_type(Child.A.value)  # should reveal `Any`, currently reveals `tuple[Literal[1], Literal["foo"]]`

At runtime A and B do pass through Base.__init__, so we should also model that.

And once we model that correctly, I think the only consistent/correct approach is also to inherit _value_ annotation from a base.

@charliermarsh charliermarsh requested a review from carljm February 23, 2026 16:56
Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

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

This is looking great! A couple nits and a couple things that need fixing, but happy for you to just land it once those are fixed.

@charliermarsh charliermarsh merged commit 14bd2b2 into astral-sh:main Feb 26, 2026
50 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants