Skip to content

[ty] Add invalid-enum-member-annotation lint rule#23648

Merged
AlexWaygood merged 13 commits intomainfrom
claude/enum-annotation-diagnostic-bfZuG
Mar 2, 2026
Merged

[ty] Add invalid-enum-member-annotation lint rule#23648
AlexWaygood merged 13 commits intomainfrom
claude/enum-annotation-diagnostic-bfZuG

Conversation

@AlexWaygood
Copy link
Member

@AlexWaygood AlexWaygood commented Mar 1, 2026

Summary

This PR fixes the last remaining conformance failure on enums_members.py in the conformance suite.

Implements a new lint rule invalid-enum-member-annotation that detects type annotations on enum members. According to the typing spec, enum members should not have explicit type annotations, as the actual runtime type is the enum class itself, not the annotated type.

The rule:

  • Flags annotated enum members (e.g., DOG: int = 2 in an Enum class)
  • Allows bare Final annotations (which don't specify a type)
  • Excludes dunder names, private names, and special sunder names like _value_ and _ignore_
  • Excludes pure declarations without values (non-members)

Test Plan

mdtests

@AlexWaygood AlexWaygood added the ty Multi-file analysis & type inference label Mar 1, 2026
@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 1, 2026

Typing conformance results improved 🎉

The percentage of diagnostics emitted that were expected errors increased from 85.90% to 85.92%. The percentage of expected errors that received a diagnostic increased from 78.04% to 78.13%.

Summary

Metric Old New Diff Outcome
True Positives 853 854 +1 ⏫ (✅)
False Positives 140 140 +0
False Negatives 240 239 -1 ⏬ (✅)
Total Diagnostics 993 994 +1
Precision 85.90% 85.92% +0.01% ⏫ (✅)
Recall 78.04% 78.13% +0.09% ⏫ (✅)

True positives added

Details
Location Name Message
enums_members.py:50:10 invalid-enum-member-annotation Type annotation on enum member DOG is not allowed

@AlexWaygood AlexWaygood changed the title Add invalid-enum-member-annotation lint rule [ty] Add invalid-enum-member-annotation lint rule Mar 1, 2026
@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 1, 2026

mypy_primer results

Changes were detected when running on open source projects
pip (https://github.com/pypa/pip)
- src/pip/_internal/req/req_uninstall.py:132:42: error[invalid-argument-type] Argument to function `norm_join` is incorrect: Expected `str`, found `Unknown | Sized`
+ src/pip/_internal/req/req_uninstall.py:132:42: error[invalid-argument-type] Argument to function `norm_join` is incorrect: Expected `str`, found `Sized | Unknown`
- src/pip/_internal/req/req_uninstall.py:133:40: error[invalid-argument-type] Argument to function `norm_join` is incorrect: Expected `str`, found `Unknown | Sized`
+ src/pip/_internal/req/req_uninstall.py:133:40: error[invalid-argument-type] Argument to function `norm_join` is incorrect: Expected `str`, found `Sized | Unknown`
- src/pip/_internal/req/req_uninstall.py:139:27: error[unsupported-operator] Operator `+` is not supported between objects of type `Unknown | Sized` and `LiteralString`
+ src/pip/_internal/req/req_uninstall.py:139:27: error[unsupported-operator] Operator `+` is not supported between objects of type `Sized | Unknown` and `LiteralString`

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 | bytes | Unknown | ... omitted 3 union elements]`

aiortc (https://github.com/aiortc/aiortc)
- src/aiortc/sdp.py:446:52: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `None | Unknown | str`
+ src/aiortc/sdp.py:446:52: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `None | str | Unknown`

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

meson (https://github.com/mesonbuild/meson)
- mesonbuild/dependencies/cuda.py:137:76: error[invalid-argument-type] Argument to function `version_compare_many` is incorrect: Expected `str`, found `str | None | Unknown`
+ mesonbuild/dependencies/cuda.py:137:76: error[invalid-argument-type] Argument to function `version_compare_many` is incorrect: Expected `str`, found `Unknown | str | None`

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 `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler] | Coroutine[Any, Any, T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]]`
+ 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/utilities/asyncutils.py:198:16: error[invalid-return-type] Return type does not match returned value: expected `R@run_coro_as_sync | None`, found `CoroutineType[Any, Any, R@run_coro_as_sync | None] | R@run_coro_as_sync | None`
+ src/prefect/utilities/asyncutils.py:207:20: error[invalid-return-type] Return type does not match returned value: expected `R@run_coro_as_sync | None`, found `CoroutineType[Any, Any, R@run_coro_as_sync | None] | R@run_coro_as_sync | None`
- Found 5798 diagnostics
+ Found 5800 diagnostics

pandas (https://github.com/pandas-dev/pandas)
- pandas/core/methods/describe.py:210:21: error[not-iterable] Object of type `Unknown | Sized` may not be iterable
+ pandas/core/methods/describe.py:210:21: error[not-iterable] Object of type `Sized | Unknown` may not be iterable

dd-trace-py (https://github.com/DataDog/dd-trace-py)
- ddtrace/debugging/_redaction.py:16:5: error[unsupported-operator] Operator `|` is not supported between objects of type `frozenset[Unknown | str]` and `Unknown | EnvVariable[set[Unknown]]`
+ ddtrace/debugging/_redaction.py:16:5: error[unsupported-operator] Operator `|` is not supported between objects of type `frozenset[str | Unknown]` and `Unknown | EnvVariable[set[Unknown]]`

ibis (https://github.com/ibis-project/ibis)
- ibis/selectors.py:333:16: error[invalid-return-type] Return type does not match returned value: expected `frozenset[str]`, found `frozenset[str | Buffer | Unknown]`
+ ibis/selectors.py:333:16: error[invalid-return-type] Return type does not match returned value: expected `frozenset[str]`, found `frozenset[Unknown | str | Buffer]`
- ibis/selectors.py:428:13: error[invalid-assignment] Object of type `frozenset[str | Unknown]` is not assignable to `tuple[str | Column, ...]`
+ ibis/selectors.py:428:13: error[invalid-assignment] Object of type `frozenset[Unknown | str]` is not assignable to `tuple[str | Column, ...]`

materialize (https://github.com/MaterializeInc/materialize)
+ misc/python/materialize/cli/mz_workload_anonymize.py:251:13: error[no-matching-overload] No overload of bound method `join` matches arguments
- Found 527 diagnostics
+ Found 528 diagnostics

sympy (https://github.com/sympy/sympy)
+ sympy/algebras/tests/test_quaternion.py:423:33: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/codegen/tests/test_matrix_nodes.py:28:21: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/expressions/tests/test_blockmatrix.py:236:13: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/expressions/tests/test_blockmatrix.py:236:33: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/expressions/tests/test_blockmatrix.py:236:53: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/expressions/tests/test_blockmatrix.py:460:12: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ 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 `MatrixBase | Expr`
+ sympy/matrices/expressions/tests/test_matpow.py:125:47: error[unsupported-operator] Operator `+` is not supported between two objects of type `ImmutableDenseMatrix`
+ 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:393:11: error[unsupported-operator] Operator `+` is not supported between objects of type `MatrixBase` and `MatrixBase | Expr | Unknown`
+ sympy/matrices/matrixbase.py:979:18: error[unsupported-operator] Operator `+` is not supported between two objects of type `Self@_eval_wilkinson`
+ sympy/matrices/matrixbase.py:3256:16: error[invalid-return-type] Return type does not match returned value: expected `MatrixBase`, found `T2'return@call_highest_priority | T1'return@call_highest_priority`
+ sympy/matrices/matrixbase.py:3256:29: error[invalid-argument-type] Argument is incorrect: Expected `T2'return@call_highest_priority | T1'return@call_highest_priority`, found `MatrixBase`
+ sympy/matrices/matrixbase.py:3310:16: error[unsupported-operator] Operator `+` is not supported between two objects of type `MatrixBase`
+ sympy/matrices/matrixbase.py:3314:16: error[invalid-return-type] Return type does not match returned value: expected `Tmat@__sub__`, found `MatrixBase`
+ sympy/matrices/matrixbase.py:4386:16: error[unsupported-operator] Operator `+` is not supported between two objects of type `Self@add`
+ sympy/matrices/repmatrix.py:321:17: error[unsupported-operator] Operator `-` is not supported between two objects of type `Self@_eval_is_symmetric`
+ sympy/matrices/tests/test_commonmatrix.py:1250:31: error[unsupported-operator] Operator `+` is not supported between objects of type `MutableDenseMatrix` and `ImmutableDenseNDimArray`
+ 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_immutable.py:106:23: error[unsupported-operator] Operator `+` is not supported between two objects of type `ImmutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:122:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:124:32: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:142:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2180:22: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2208:26: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2909:21: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2922:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2937:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2938:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2949:14: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:3472:21: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ 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_matrixbase.py:492:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:494:32: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:545:12: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:824:31: error[unsupported-operator] Operator `+` is not supported between objects of type `MutableDenseMatrix` and `ImmutableDenseNDimArray`
+ sympy/matrices/tests/test_matrixbase.py:877:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:879:32: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:901:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:2932:22: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:2960:26: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:3611:21: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:3625:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:3640:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:3641:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:3653:14: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_reductions.py:378:21: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_reductions.py:385:12: error[unresolved-attribute] Attribute `rank` is not defined on `MatrixExpr` in union `MatrixBase | MatrixExpr | Unknown`
+ sympy/matrices/tests/test_reductions.py:386:12: error[unresolved-attribute] Attribute `rank` is not defined on `MatrixExpr` in union `MatrixBase | MatrixExpr | Unknown`
+ sympy/matrices/tests/test_solvers.py:69:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_sparse.py:574:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableSparseMatrix`
+ sympy/matrices/tests/test_sparse.py:578:52: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableSparseMatrix`
+ sympy/matrices/tests/test_sparse.py:594:17: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableSparseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:13:6: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:16:38: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:16:84: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:16:131: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:21:44: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:21:90: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:21:137: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:25:37: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:25:83: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:25:130: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/mathematica.py:692:38: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `Iterable[Never]`, found `Unknown | list[Unknown | str]`
+ sympy/physics/control/tests/test_lti.py:3778:31: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/physics/control/tests/test_lti.py:3778:38: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/physics/mechanics/lagrange.py:223:23: error[unsupported-operator] Operator `-` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/physics/mechanics/lagrange.py:347:17: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/physics/mechanics/linearize.py:218:28: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/physics/mechanics/linearize.py:230:29: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/physics/mechanics/linearize.py:242:29: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/physics/mechanics/tests/test_jointsmethod.py:248:17: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/physics/mechanics/tests/test_jointsmethod.py:250:17: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/physics/quantum/tests/test_represent.py:90:17: error[unsupported-operator] Operator `+` is not supported between objects of type `MatrixBase | Expr` and `MatrixBase`
+ sympy/physics/quantum/tests/test_represent.py:92:24: error[unsupported-operator] Operator `-` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/physics/quantum/tests/test_represent.py:94:28: error[unsupported-operator] Operator `+` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/physics/vector/functions.py:381:21: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `Iterable[Unknown]`, found `MatrixBase | Unknown`
+ sympy/solvers/tests/test_numeric.py:138:11: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
- sympy/solvers/tests/test_pde.py:109:16: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(str | Unknown, /) -> Unknown`, found `<class 'Function'>`
+ sympy/solvers/tests/test_pde.py:109:16: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(Unknown | str, /) -> Unknown`, found `<class 'Function'>`
- sympy/solvers/tests/test_pde.py:130:22: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(str | Unknown, /) -> Unknown`, found `<class 'Function'>`
+ sympy/solvers/tests/test_pde.py:130:22: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(Unknown | str, /) -> Unknown`, found `<class 'Function'>`
- sympy/solvers/tests/test_pde.py:138:16: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(str | Unknown, /) -> Unknown`, found `<class 'Function'>`
+ sympy/solvers/tests/test_pde.py:138:16: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(Unknown | str, /) -> Unknown`, found `<class 'Function'>`
- sympy/solvers/tests/test_pde.py:164:16: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(str | Unknown, /) -> Unknown`, found `<class 'Function'>`
+ sympy/solvers/tests/test_pde.py:164:16: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(Unknown | str, /) -> Unknown`, found `<class 'Function'>`
- sympy/solvers/tests/test_pde.py:202:16: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(str | Unknown, /) -> Unknown`, found `<class 'Function'>`
+ sympy/solvers/tests/test_pde.py:202:16: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(Unknown | str, /) -> Unknown`, found `<class 'Function'>`
- sympy/solvers/tests/test_pde.py:216:16: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(str | Unknown, /) -> Unknown`, found `<class 'Function'>`
+ sympy/solvers/tests/test_pde.py:216:16: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(Unknown | str, /) -> Unknown`, found `<class 'Function'>`
+ sympy/solvers/tests/test_solvers.py:723:19: error[unsupported-operator] Operator `-` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/solvers/tests/test_solvers.py:724:19: error[unsupported-operator] Operator `-` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/solvers/tests/test_solvers.py:725:19: error[unsupported-operator] Operator `-` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/solvers/tests/test_solvers.py:725:30: error[unsupported-operator] Operator `-` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/stats/tests/test_symbolic_multivariate.py:85:36: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/stats/tests/test_symbolic_multivariate.py:85:84: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/stats/tests/test_symbolic_multivariate.py:86:36: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/tensor/tests/test_tensor.py:1694:19: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/tensor/tests/test_tensor.py:1695:23: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
- Found 16069 diagnostics
+ Found 16158 diagnostics

static-frame (https://github.com/static-frame/static-frame)
- static_frame/test/unit/test_bus.py:2137:26: error[unresolved-attribute] Attribute `to_pairs` is not defined on `ndarray[Any, Any]` in union `@Todo | Series[Any, Any] | ndarray[Any, Any]`
+ static_frame/test/unit/test_bus.py:2137:26: error[unresolved-attribute] Attribute `to_pairs` is not defined on `ndarray[Any, Any]` in union `ndarray[Any, Any] | @Todo | Series[Any, Any]`
- static_frame/test/unit/test_bus.py:2138:26: error[unresolved-attribute] Attribute `to_pairs` is not defined on `ndarray[Any, Any]` in union `@Todo | Series[Any, Any] | ndarray[Any, Any]`
+ static_frame/test/unit/test_bus.py:2138:26: error[unresolved-attribute] Attribute `to_pairs` is not defined on `ndarray[Any, Any]` in union `ndarray[Any, Any] | @Todo | Series[Any, Any]`
- static_frame/test/unit/test_bus.py:2166:26: error[unresolved-attribute] Attribute `to_pairs` is not defined on `ndarray[Any, Any]` in union `@Todo | Series[Any, Any] | ndarray[Any, Any]`
+ static_frame/test/unit/test_bus.py:2166:26: error[unresolved-attribute] Attribute `to_pairs` is not defined on `ndarray[Any, Any]` in union `ndarray[Any, Any] | @Todo | Series[Any, Any]`
- static_frame/test/unit/test_bus.py:2167:26: error[unresolved-attribute] Attribute `to_pairs` is not defined on `ndarray[Any, Any]` in union `@Todo | Series[Any, Any] | ndarray[Any, Any]`
+ static_frame/test/unit/test_bus.py:2167:26: error[unresolved-attribute] Attribute `to_pairs` is not defined on `ndarray[Any, Any]` in union `ndarray[Any, Any] | @Todo | Series[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1389:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1389:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1397:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1397:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1408:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1408:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1411:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1411:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1431:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1431:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1439:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1439:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1481:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1481:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1489:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1489:13: error[unresolved-attribute] Attribute `to_pairs` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1549:26: error[unresolved-attribute] Attribute `tolist` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1549:26: error[unresolved-attribute] Attribute `tolist` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1550:26: error[unresolved-attribute] Attribute `tolist` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1550:26: error[unresolved-attribute] Attribute `tolist` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1553:26: error[unresolved-attribute] Attribute `tolist` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1553:26: error[unresolved-attribute] Attribute `tolist` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1554:26: error[unresolved-attribute] Attribute `tolist` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1554:26: error[unresolved-attribute] Attribute `tolist` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`
- static_frame/test/unit/test_frame_iter.py:1684:29: error[unresolved-attribute] Attribute `shape` is not defined on `tuple[Any, Any]` in union `tuple[Any, Any] | Any`
+ static_frame/test/unit/test_frame_iter.py:1684:29: error[unresolved-attribute] Attribute `shape` is not defined on `tuple[Any, Any]` in union `Any | tuple[Any, Any]`

rotki (https://github.com/rotki/rotki)
- rotkehlchen/tests/unit/test_makerdao.py:170:9: error[invalid-argument-type] Argument is incorrect: Expected `defaultdict[Asset, defaultdict[str, Balance]]`, found `defaultdict[Asset | Unknown, defaultdict[str, Balance] | Balance | dict[Unknown | str, Unknown | Balance] | Unknown]`
+ rotkehlchen/tests/unit/test_makerdao.py:170:9: error[invalid-argument-type] Argument is incorrect: Expected `defaultdict[Asset, defaultdict[str, Balance]]`, found `defaultdict[Asset | Unknown, defaultdict[str, Balance] | Balance | Unknown | dict[Unknown | str, Unknown | Balance]]`
- rotkehlchen/tests/unit/test_makerdao.py:171:9: error[invalid-argument-type] Argument is incorrect: Expected `defaultdict[Asset, defaultdict[str, Balance]]`, found `defaultdict[Asset | Unknown, defaultdict[str, Balance] | Balance | dict[Unknown | str, Unknown | Balance] | Unknown]`
+ rotkehlchen/tests/unit/test_makerdao.py:171:9: error[invalid-argument-type] Argument is incorrect: Expected `defaultdict[Asset, defaultdict[str, Balance]]`, found `defaultdict[Asset | Unknown, defaultdict[str, Balance] | Balance | Unknown | dict[Unknown | str, Unknown | Balance]]`

scikit-learn (https://github.com/scikit-learn/scikit-learn)
- sklearn/externals/array_api_compat/common/_linalg.py:113:15: error[unresolved-attribute] Attribute `max` is not defined on `tuple[Any, ...]` in union `tuple[Any, ...] | Any`
+ sklearn/externals/array_api_compat/common/_linalg.py:113:15: error[unresolved-attribute] Attribute `max` is not defined on `tuple[Any, ...]` in union `Any | tuple[Any, ...]`
- sklearn/externals/array_api_compat/common/_linalg.py:113:76: error[unresolved-attribute] Attribute `dtype` is not defined on `tuple[Any, ...]` in union `tuple[Any, ...] | Any`
+ sklearn/externals/array_api_compat/common/_linalg.py:113:76: error[unresolved-attribute] Attribute `dtype` is not defined on `tuple[Any, ...]` in union `Any | tuple[Any, ...]`
- sklearn/externals/array_api_compat/common/_linalg.py:117:15: error[unresolved-attribute] Attribute `max` is not defined on `tuple[Any, ...]` in union `tuple[Any, ...] | Any`
+ sklearn/externals/array_api_compat/common/_linalg.py:117:15: error[unresolved-attribute] Attribute `max` is not defined on `tuple[Any, ...]` in union `Any | tuple[Any, ...]`
- sklearn/utils/tests/test_multiclass.py:399:27: error[unresolved-attribute] Attribute `toarray` is not defined on `list[Unknown | list[Unknown | int]] & SparseABC`, `ndarray[tuple[Any, ...], dtype[Any]] & SparseABC`, `_NotAnArray & SparseABC`, `list[Unknown | int] & SparseABC`, `list[Unknown | str] & SparseABC`, `list[Unknown | list[Unknown | str]] & SparseABC`, `list[Unknown] & SparseABC`, `list[Unknown | int | float] & SparseABC`, `list[Unknown | list[Unknown]] & SparseABC`, `list[Unknown | tuple[()]] & SparseABC`, `list[Unknown | ndarray[tuple[Any, ...], dtype[Unknown]]] & SparseABC`, `list[Unknown | set[Unknown | int]] & SparseABC`, `list[Unknown | frozenset[Unknown | int]] & SparseABC`, `list[Unknown | dict[Unknown | int, Unknown | str]] & SparseABC` in union `(Unknown & SparseABC) | (list[Unknown | list[Unknown | int]] & SparseABC) | (ndarray[tuple[Any, ...], dtype[Any]] & SparseABC) | ... omitted 12 union elements`
+ sklearn/utils/tests/test_multiclass.py:399:27: error[unresolved-attribute] Attribute `toarray` is not defined on `list[Unknown | list[Unknown | int]] & SparseABC`, `ndarray[tuple[Any, ...], dtype[Any]] & SparseABC`, `_NotAnArray & SparseABC`, `list[Unknown | int] & SparseABC`, `list[Unknown | str] & SparseABC`, `list[Unknown | list[Unknown | str]] & SparseABC`, `list[Unknown] & SparseABC`, `list[Unknown | int | float] & SparseABC`, `list[Unknown | list[Unknown]] & SparseABC`, `list[Unknown | tuple[()]] & SparseABC`, `list[Unknown | ndarray[tuple[Any, ...], dtype[Unknown]]] & SparseABC`, `list[Unknown | set[Unknown | int]] & SparseABC`, `list[Unknown | frozenset[int | Unknown]] & SparseABC`, `list[Unknown | dict[Unknown | int, Unknown | str]] & SparseABC` in union `(Unknown & SparseABC) | (list[Unknown | list[Unknown | int]] & SparseABC) | (ndarray[tuple[Any, ...], dtype[Any]] & SparseABC) | ... omitted 12 union elements`

pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
- tests/test_string_accessors.py:31:11: error[type-assertion-failure] Type `Index[Unknown | bytes]` does not match asserted type `Index[bytes]`
+ tests/test_string_accessors.py:31:11: error[type-assertion-failure] Type `Index[bytes | Unknown]` does not match asserted type `Index[bytes]`

core (https://github.com/home-assistant/core)
- homeassistant/components/teslemetry/climate.py:154:37: error[unresolved-attribute] Attribute `index` is not defined on `None` in union `Unknown | list[Unknown | str] | list[str] | None`
+ homeassistant/components/teslemetry/climate.py:154:37: error[unresolved-attribute] Attribute `index` is not defined on `None` in union `Unknown | list[str | Unknown] | list[str] | None`


@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 1, 2026

Memory usage report

Summary

Project Old New Diff Outcome
prefect 694.30MB 696.06MB +0.25% (1.76MB)
sphinx 267.75MB 268.07MB +0.12% (324.24kB)
trio 118.62MB 118.81MB +0.15% (188.11kB)
flake8 48.17MB 48.19MB +0.02% (11.98kB)

Significant changes

Click to expand detailed breakdown

prefect

Name Old New Diff Outcome
infer_definition_types 86.47MB 87.85MB +1.60% (1.38MB)
Type<'db>::class_member_with_policy_ 16.96MB 17.09MB +0.80% (139.34kB)
code_generator_of_static_class 1.72MB 1.79MB +3.79% (66.85kB)
code_generator_of_static_class::interned_arguments 890.93kB 924.12kB +3.73% (33.19kB)
Type<'db>::member_lookup_with_policy_ 15.25MB 15.28MB +0.21% (32.11kB)
Type<'db>::class_member_with_policy_::interned_arguments 9.13MB 9.15MB +0.29% (26.81kB)
Type<'db>::member_lookup_with_policy_::interned_arguments 5.39MB 5.41MB +0.48% (26.51kB)
Type<'db>::try_call_dunder_get_ 10.25MB 10.25MB +0.08% (8.16kB)
enum_ignored_names 0.00B 6.47kB +6.47kB (new)
StaticClassLiteral<'db>::try_mro_ 6.12MB 6.12MB +0.10% (6.33kB)
StaticClassLiteral<'db>::implicit_attribute_inner_ 9.81MB 9.81MB +0.04% (4.09kB)
StaticClassLiteral<'db>::implicit_attribute_inner_::interned_arguments 5.09MB 5.09MB +0.07% (3.47kB)
CallableType 1.92MB 1.92MB +0.18% (3.45kB)
Specialization 2.54MB 2.54MB +0.10% (2.48kB)
is_redundant_with_impl::interned_arguments 5.58MB 5.59MB +0.04% (2.41kB)
... 22 more

sphinx

Name Old New Diff Outcome
infer_definition_types 24.31MB 24.40MB +0.38% (94.96kB)
Type<'db>::class_member_with_policy_ 7.51MB 7.59MB +1.17% (89.78kB)
code_generator_of_static_class 496.61kB 534.65kB +7.66% (38.04kB)
code_generator_of_static_class::interned_arguments 248.84kB 267.61kB +7.54% (18.77kB)
Type<'db>::member_lookup_with_policy_ 6.11MB 6.13MB +0.29% (18.00kB)
Type<'db>::member_lookup_with_policy_::interned_arguments 2.54MB 2.55MB +0.62% (16.15kB)
Type<'db>::class_member_with_policy_::interned_arguments 4.00MB 4.01MB +0.39% (16.15kB)
StaticClassLiteral<'db>::try_mro_ 2.17MB 2.18MB +0.47% (10.49kB)
StaticClassLiteral<'db>::implicit_attribute_inner_ 2.38MB 2.39MB +0.13% (3.24kB)
enum_ignored_names 0.00B 3.19kB +3.19kB (new)
Specialization 1.05MB 1.06MB +0.26% (2.83kB)
StaticClassLiteral<'db>::implicit_attribute_inner_::interned_arguments 1.91MB 1.91MB +0.14% (2.72kB)
StaticClassLiteral<'db>::try_mro_::interned_arguments 501.12kB 503.16kB +0.41% (2.04kB)
GenericAlias 469.69kB 471.45kB +0.37% (1.76kB)
enum_metadata 737.04kB 737.94kB +0.12% (916.00B)
... 21 more

trio

Name Old New Diff Outcome
infer_definition_types 7.58MB 7.64MB +0.76% (59.18kB)
Type<'db>::class_member_with_policy_ 1.98MB 2.02MB +1.56% (31.71kB)
code_generator_of_static_class 197.79kB 212.95kB +7.66% (15.16kB)
Type<'db>::member_lookup_with_policy_ 1.70MB 1.71MB +0.61% (10.59kB)
Type<'db>::class_member_with_policy_::interned_arguments 1.11MB 1.12MB +0.74% (8.43kB)
Type<'db>::member_lookup_with_policy_::interned_arguments 868.16kB 875.98kB +0.90% (7.82kB)
code_generator_of_static_class::interned_arguments 98.23kB 105.75kB +7.66% (7.52kB)
CallableType 577.57kB 582.91kB +0.93% (5.34kB)
StaticClassLiteral<'db>::try_mro_ 890.63kB 894.86kB +0.47% (4.23kB)
ClassType<'db>::into_callable_ 3.88kB 7.63kB +96.68% (3.75kB)
FunctionType 1.50MB 1.51MB +0.17% (2.59kB)
lookup_dunder_new_inner 69.42kB 71.98kB +3.69% (2.56kB)
StaticClassLiteral<'db>::implicit_attribute_inner_ 771.63kB 774.15kB +0.33% (2.52kB)
Type<'db>::try_call_dunder_get_ 1.38MB 1.39MB +0.18% (2.49kB)
infer_deferred_types 2.36MB 2.36MB +0.10% (2.48kB)
... 40 more

flake8

Name Old New Diff Outcome
Type<'db>::class_member_with_policy_ 551.39kB 554.27kB +0.52% (2.88kB)
code_generator_of_static_class 59.27kB 60.97kB +2.87% (1.70kB)
infer_definition_types 1.89MB 1.89MB +0.05% (1.03kB)
Type<'db>::member_lookup_with_policy_ 411.05kB 411.92kB +0.21% (888.00B)
code_generator_of_static_class::interned_arguments 29.53kB 30.38kB +2.86% (864.00B)
CallableType 168.54kB 169.24kB +0.42% (720.00B)
enum_ignored_names 0.00B 672.00B +672.00B (new)
Type<'db>::member_lookup_with_policy_::interned_arguments 207.70kB 208.30kB +0.29% (624.00B)
Type<'db>::class_member_with_policy_::interned_arguments 303.37kB 303.98kB +0.20% (624.00B)
StaticClassLiteral<'db>::implicit_attribute_inner_ 294.70kB 295.25kB +0.19% (560.00B)
Type<'db>::try_call_dunder_get_ 376.69kB 377.23kB +0.14% (556.00B)
StaticClassLiteral<'db>::implicit_attribute_inner_::interned_arguments 239.25kB 239.72kB +0.20% (480.00B)
ClassType<'db>::into_callable_ 216.00B 432.00B +100.00% (216.00B)
TupleType 78.83kB 78.95kB +0.16% (128.00B)
Type<'db>::try_call_dunder_get_::interned_arguments 85.31kB 85.41kB +0.12% (104.00B)
... 1 more

@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 1, 2026

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 1, 2026

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-argument-type 1 0 0
Total 1 0 0

Full report with detailed diff (timing results)

Comment on lines +9682 to +9694
if let Some(name_expr) = target.as_name_expr()
&& !name_expr.id.starts_with("__")
&& !matches!(name_expr.id.as_str(), "_ignore_" | "_value_" | "_name_")
// Not bare Final (bare Final is allowed on enum members)
&& !(declared.qualifiers.contains(TypeQualifiers::FINAL)
&& matches!(declared.inner_type(), Type::Dynamic(DynamicType::Unknown)))
// Value type would be an enum member at runtime (exclude callables,
// which are never members)
&& !inferred_ty.is_subtype_of(
self.db(),
Type::Callable(CallableType::unknown(self.db()))
.top_materialization(self.db()),
)
Copy link
Member Author

Choose a reason for hiding this comment

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

this all feels a little duplicative of the logic we have elsewhere for deciding whether an assignment in an enum class is an enum member to begin with, but I think it's okay

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, it's just different enough in form that I agree that we shouldn't bend over backwards to eliminate the copy/pasta. My only thought is that maybe this logic should live as a top-level helper method in types/enums.rs, so that all of this related logic is defined close to each other in the ty source? Then this would become a simple check:

if !allowed_enum_member_annotation(name_expr, inferred_ty, current_scope)

But I'm also fine leaving as-is

@AlexWaygood AlexWaygood marked this pull request as ready for review March 1, 2026 16:53
@AlexWaygood AlexWaygood force-pushed the claude/enum-annotation-diagnostic-bfZuG branch from ff695ba to 8810a82 Compare March 2, 2026 13:08
Comment on lines +119 to +120
DOG: int = 2 # error: [invalid-enum-member-annotation] "Type annotation on enum member `DOG` is not allowed"
BIRD: str = "bird" # error: [invalid-enum-member-annotation]
Copy link
Member

Choose a reason for hiding this comment

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

nit: I would suggest either checking both error messages, or neither. (Probably preferably neither, unless you switch to using a snapshot test for that)

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, I disagree -- I think it's useful to assert the error message once, and a snapshot test feels overkill for that unless you have detailed secondary annotations etc. But asserting it more than once makes it tedious to update the mdtests in the future if you ever change the error message.

Comment on lines +199 to +202
_ignore_ = "A B"
A: int = 42 # OK: `A` is listed in `_ignore_`
B: str = "hello" # OK: `B` is listed in `_ignore_`
C: int = 3 # error: [invalid-enum-member-annotation]
Copy link
Member

Choose a reason for hiding this comment

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

😵‍💫

Comment on lines +9682 to +9694
if let Some(name_expr) = target.as_name_expr()
&& !name_expr.id.starts_with("__")
&& !matches!(name_expr.id.as_str(), "_ignore_" | "_value_" | "_name_")
// Not bare Final (bare Final is allowed on enum members)
&& !(declared.qualifiers.contains(TypeQualifiers::FINAL)
&& matches!(declared.inner_type(), Type::Dynamic(DynamicType::Unknown)))
// Value type would be an enum member at runtime (exclude callables,
// which are never members)
&& !inferred_ty.is_subtype_of(
self.db(),
Type::Callable(CallableType::unknown(self.db()))
.top_materialization(self.db()),
)
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, it's just different enough in form that I agree that we shouldn't bend over backwards to eliminate the copy/pasta. My only thought is that maybe this logic should live as a top-level helper method in types/enums.rs, so that all of this related logic is defined close to each other in the ty source? Then this would become a simple check:

if !allowed_enum_member_annotation(name_expr, inferred_ty, current_scope)

But I'm also fine leaving as-is

bxff and others added 12 commits March 2, 2026 17:22
…(`RUF055`) (#23634)

## Summary

Fixes #23629.

`re.split("", s)` is flagged by RUF055 and auto-fixed to `s.split("")`,
but `str.split("")` raises `ValueError: empty separator` while
`re.split("", s)` succeeds (returning `["", "a", "b", "c", ""]`). The
same applies to bytes (`rb""`).

This adds a guard to skip the diagnostic when the separator pattern is
an empty string or bytes literal specifically for `re.split` calls.
Other `re` functions (`sub`, `match`, `search`, `fullmatch`) are not
affected — their `str` equivalents all handle empty strings
equivalently.

## Test Plan

Added test cases for empty string and bytes patterns in `RUF055_0.py`
and `RUF055_3.py`. Verified that no diagnostics are emitted for these
cases and all existing RUF055 snapshot tests continue to pass:

```
cargo test -p ruff_linter -- "preview_rules::rule_unnecessaryregularexpression"
test result: ok. 4 passed; 0 failed; 0 ignored
```
- Shorten second paragraph of "Why is this bad?" docs
- Change lint status from 0.0.16 to 0.0.20
- Change default severity from Error to Warn (no runtime error)
- Merge report_lint guard into the let chain above it

https://claude.ai/code/session_01MzfceBgafJtwtAwLXarq4o
The previous `matches!(inferred_ty, Type::Callable(_) | Type::FunctionLiteral(_))`
was fragile and missed many callable types (bound methods, class instances
with `__call__`, etc.). Replace with a proper subtype check against the top
materialization of `Callable[..., object]`.

Also add test coverage for the callable exclusion.

https://claude.ai/code/session_01MzfceBgafJtwtAwLXarq4o
Code blocks within the same subsection are implicitly merged before ty
runs on them, so repeated `from enum import Enum` imports are unnecessary.

https://claude.ai/code/session_01MzfceBgafJtwtAwLXarq4o
By placing the `[environment] python-version = "3.11"` block at the
top of "### Annotated enum members", all Python snippets merge into a
single group, so we only need one import block for the entire section.

https://claude.ai/code/session_01MzfceBgafJtwtAwLXarq4o
The typing spec does not say that using `member` as a type annotation
on an enum member (e.g. `DOG: member = 2`) should be exempt from the
invalid-enum-member-annotation diagnostic, and no other type checker
exempts it. Remove the special-case logic and the associated test.

https://claude.ai/code/session_01MzfceBgafJtwtAwLXarq4o
Enums with `_ignore_ = "A B"` should not emit the diagnostic for
names A and B, since those are explicitly excluded from membership.

Extract `enum_ignored_names` as a standalone function so it can be
queried independently of `enum_metadata` (which returns `None` when
an enum has no remaining members after filtering).

https://claude.ai/code/session_01MzfceBgafJtwtAwLXarq4o
@AlexWaygood AlexWaygood force-pushed the claude/enum-annotation-diagnostic-bfZuG branch from 8810a82 to c9efb49 Compare March 2, 2026 17:23
@AlexWaygood AlexWaygood enabled auto-merge (squash) March 2, 2026 17:25
@AlexWaygood AlexWaygood merged commit cd8e8d5 into main Mar 2, 2026
50 checks passed
@AlexWaygood AlexWaygood deleted the claude/enum-annotation-diagnostic-bfZuG branch March 2, 2026 17:31
carljm added a commit that referenced this pull request Mar 2, 2026
* main: (30 commits)
  [ty] Introduce `types::bool`, `types::context_manager` and `types::iteration` (#23681)
  [ty] Move `KnownInstanceType`, and related types, to a new `known_instance.rs` submodule (#23680)
  [ty] Add `invalid-enum-member-annotation` lint rule (#23648)
  [`ruff`] Fix false positive for `re.split` with empty string pattern (`RUF055`) (#23634)
  [ty] Move `UnionType` and `IntersectionType` to a new `types::set_theoretic` submodule (#23678)
  [ty] Add unbound type variable detection in annotations (#23641)
  [ty] Remove `specialize_constrained` from constraint set module (#23677)
  [ty] Add partial support and validation for `Unpack` when used with tuple types (#23651)
  Update prek dependencies (#23661)
  [ty] make `StaticClassLiteral::explicit_bases` converge better in cycles (#23601)
  Improvements to CLAUDE.md (#23633)
  [ty] Move subscript logic out of `builder.rs` (#23653)
  Update Artifact GitHub Actions dependencies (#23676)
  Update actions/attest-build-provenance to 4.1.0 (#23654)
  Update Rust crate clearscreen to v4.0.5 (#23664)
  fix renovate `actions/*-artifact` updates (#23675)
  Update Rust crate clap to v4.5.60 (#23663)
  Update Rust crate unicode-ident to v1.0.24 (#23668)
  Update Rust crate anyhow to v1.0.102 (#23662)
  Update Rust crate pyproject-toml to v0.13.7 (#23666)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ecosystem-analyzer ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants