Skip to content

[ty] Detect generic Callables in function signatures#22954

Merged
dcreager merged 15 commits intomainfrom
dcreager/callable-genctx
Feb 4, 2026
Merged

[ty] Detect generic Callables in function signatures#22954
dcreager merged 15 commits intomainfrom
dcreager/callable-genctx

Conversation

@dcreager
Copy link
Member

When we coerce a generic function or class constructor into a Callable, the callable type remembers that it is generic:

def identity[T](t: T) -> T:
    return t

# revealed: ty_extensions.GenericContext[T@identity]
reveal_type(generic_context(identity))
# revealed: [T](t: T) -> T                <-- note the [T] generic context
reveal_type(into_callable(identity))
# revealed: ty_extensions.GenericContext[T@identity]
reveal_type(generic_context(into_callable(identity)))

However, there is no easy way to spell a generic Callable type in Python. The closest you can get is by defining a generic type alias:

Identity = Callable[[T], T]
type Identity[T] = Callable[[T], T]

To get around this, there is a common heuristic that if a generic function binds a typevar, but that typevar is only mentioned in a Callable in return position, then it's actually the callable that binds the typevar, not the function. (And if that's the only typevar mentioned in the function signature, the function ends up not being generic at all.) This comes up very often in decorator factories, where the factory function returns a decorator that is generic over one or more typevars:

def decorator_factory() -> Callable[[T], T]:
    def decorator(t: T) -> T:
        return t

Here, decorator_factory should not be considered generic; its Callable return type is.

Note that this is true for PEP-695 typevars, too!

def decorator_factory[T]() -> Callable[[T], T]:
    def decorator[T](t: T) -> T:
        return t

(This is one example where PEP-695 syntax is misleading! We can usually assume that a [T] binding context makes the item that it's attached to generic — and that we can determine this statically. But in this case we can't! We have to analyze the function signature to see that decorator_factory is not generic, even though it has a PEP-695 binding context.)

Closes astral-sh/ty#1136

@dcreager dcreager added the ty Multi-file analysis & type inference label Jan 29, 2026
Comment on lines +7001 to +7003

/// Updates any `Callable` types in a function signature return type to be generic if possible.
RescopeReturnCallables(&'a FxHashMap<CallableType<'db>, CallableType<'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.

Breaking up TypeMapping is a new windmill I want to tilt at...

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 29, 2026

Typing conformance results

The percentage of diagnostics emitted that were expected errors decreased from 82.37% to 82.22%. The percentage of expected errors that received a diagnostic increased from 72.62% to 72.71%.

Summary

Metric Old New Diff Outcome
True Positives 785 786 +1 ⏫ (✅)
False Positives 168 170 +2 ⏫ (❌)
False Negatives 296 295 -1 ⏬ (✅)
Total Diagnostics 953 956 +3
Precision 82.37% 82.22% -0.15% ⏬ (❌)
Recall 72.62% 72.71% +0.09% ⏫ (✅)

True positives added

Details
Location Name Message
generics_paramspec_semantics.py:108:1 missing-argument No argument provided for required parameter **kwargs

False positives added

Details
Location Name Message
generics_paramspec_semantics.py:106:13 missing-argument No argument provided for required parameter **kwargs
generics_paramspec_semantics.py:107:13 missing-argument No arguments provided for required parameters *args, **kwargs

@dcreager dcreager force-pushed the dcreager/callable-genctx branch from 2544dc0 to b7b8516 Compare January 30, 2026 20:38
@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 30, 2026

mypy_primer results

Changes were detected when running on open source projects
attrs (https://github.com/python-attrs/attrs)
- tests/test_validators.py:787:21: error[invalid-argument-type] Argument to function `and_` is incorrect: Expected `(Any, Attribute[int], int, /) -> Any`, found `(Any, Attribute[Literal[10]], Literal[10], /) -> Any`
+ tests/test_validators.py:787:21: error[invalid-argument-type] Argument to function `and_` is incorrect: Expected `(Any, Attribute[int], int, /) -> Any`, found `[_T'return](Any, Attribute[Literal[10]], Literal[10], /) -> Any`

anyio (https://github.com/agronholm/anyio)
- src/anyio/functools.py:230:82: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- Found 91 diagnostics
+ Found 90 diagnostics

pytest-robotframework (https://github.com/detachhead/pytest-robotframework)
+ pytest_robotframework/_internal/utils.py:51:16: error[invalid-return-type] Return type does not match returned value: expected `[**P'return](**P'return@decorator) -> T`, found `_Wrapped[(...), T@decorator, P@new_fn, T@decorator]`
- Found 173 diagnostics
+ Found 174 diagnostics

spack (https://github.com/spack/spack)
+ lib/spack/spack/vendor/jsonschema/_format.py:172:9: error[missing-argument] No argument provided for required parameter `**kwargs`
- Found 4340 diagnostics
+ Found 4341 diagnostics

pip (https://github.com/pypa/pip)
+ src/pip/_vendor/distlib/compat.py:1036:25: error[missing-argument] No argument provided for required parameter `**kwargs`
+ src/pip/_vendor/distlib/compat.py:1042:25: error[missing-argument] No argument provided for required parameter `**kwargs`
+ src/pip/_vendor/distlib/resources.py:159:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ src/pip/_vendor/distlib/resources.py:183:16: error[missing-argument] No argument provided for required parameter `**kwargs`
- Found 630 diagnostics
+ Found 634 diagnostics

async-utils (https://github.com/mikeshardmind/async-utils)
- src/async_utils/corofunc_cache.py:50:58: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `CoroFunc[P@f__call__, R@f__call__]`
+ src/async_utils/corofunc_cache.py:50:58: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `[_YieldT_co'return, _SendT_nd_contra'return, _ReturnT_nd_co'return](**P@f__call__) -> Coroutine[Any, Any, R@f__call__]`

jinja (https://github.com/pallets/jinja)
- src/jinja2/nativetypes.py:108:52: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- src/jinja2/nativetypes.py:123:52: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- Found 181 diagnostics
+ Found 179 diagnostics

werkzeug (https://github.com/pallets/werkzeug)
+ src/werkzeug/test.py:370:20: error[missing-argument] No argument provided for required parameter `**kwargs`
- Found 412 diagnostics
+ Found 413 diagnostics

pytest (https://github.com/pytest-dev/pytest)
+ testing/test_capture.py:1111:15: error[missing-argument] No argument provided for required parameter `*args`
- Found 398 diagnostics
+ Found 399 diagnostics

paasta (https://github.com/yelp/paasta)
+ paasta_tools/cli/cmds/validate.py:913:33: error[unresolved-attribute] Object of type `InstanceConfig` has no attribute `get_min_instances`
+ paasta_tools/cli/cmds/validate.py:914:33: error[unresolved-attribute] Object of type `InstanceConfig` has no attribute `get_max_instances`
+ paasta_tools/mesos_tools.py:498:9: error[invalid-argument-type] Argument is incorrect: Expected `list[str]`, found `Sequence[str] | None`
+ paasta_tools/mesos_tools.py:499:9: error[invalid-argument-type] Argument is incorrect: Expected `list[str]`, found `Sequence[str] | None`
+ paasta_tools/mesos_tools.py:500:9: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `Sequence[str] | None`
- Found 1070 diagnostics
+ Found 1075 diagnostics

scrapy (https://github.com/scrapy/scrapy)
- scrapy/utils/decorators.py:31:54: error[unresolved-attribute] Object of type `(**_P@deprecated) -> _T@deprecated` has no attribute `__name__`
+ scrapy/utils/decorators.py:31:54: error[unresolved-attribute] Object of type `(**_P@deco) -> _T@deco` has no attribute `__name__`
- scrapy/utils/decorators.py:40:16: error[invalid-assignment] Object of type `(...) -> _T@deprecated` is not assignable to `def deco[**_P](func: (**_P@deprecated) -> _T) -> (**_P@deprecated) -> _T`
+ scrapy/utils/decorators.py:40:16: error[invalid-assignment] Object of type `(...) -> Unknown` is not assignable to `def deco[**_P, _T](func: (**_P@deco) -> _T) -> (**_P@deco) -> _T`
+ tests/test_utils_request.py:146:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:146:37: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:147:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:147:37: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:152:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:152:37: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:156:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:162:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:162:37: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:172:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:172:37: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:172:58: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:174:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:178:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:189:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:189:37: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:190:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:191:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:192:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:199:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:199:37: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:200:16: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:200:37: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:205:15: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:207:15: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:214:15: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_utils_request.py:216:15: error[missing-argument] No argument provided for required parameter `**kwargs`
- Found 1759 diagnostics
+ Found 1786 diagnostics

pylint (https://github.com/pycqa/pylint)
+ pylint/checkers/async_checker.py:92:63: warning[possibly-missing-attribute] Attribute `name` may be missing on object of type `Unknown | None`
+ pylint/checkers/typecheck.py:729:46: warning[possibly-missing-attribute] Attribute `parent` may be missing on object of type `Unknown | None`
+ pylint/checkers/typecheck.py:732:34: warning[possibly-missing-attribute] Attribute `parent` may be missing on object of type `Unknown | None`
+ pylint/checkers/typecheck.py:734:34: warning[possibly-missing-attribute] Attribute `statement` may be missing on object of type `Unknown | None`
- pylint/checkers/unicode.py:414:17: error[invalid-argument-type] Argument to function `_map_positions_to_result` is incorrect: Expected `dict[bytes | str, _BadChar]`, found `dict[bytes, _BadChar]`
- Found 215 diagnostics
+ Found 218 diagnostics

schemathesis (https://github.com/schemathesis/schemathesis)
+ src/schemathesis/generation/coverage.py:142:12: error[no-matching-overload] No overload of function `one_of` matches arguments
+ src/schemathesis/generation/hypothesis/builder.py:124:16: error[no-matching-overload] No overload of function `one_of` matches arguments
+ src/schemathesis/specs/graphql/scalars.py:77:27: error[invalid-argument-type] Argument to bound method `map` is incorrect: Expected `(str, /) -> Unknown`, found `Unknown | None`
+ src/schemathesis/specs/graphql/scalars.py:78:27: error[invalid-argument-type] Argument to bound method `map` is incorrect: Expected `(str, /) -> Unknown`, found `Unknown | None`
+ src/schemathesis/specs/graphql/scalars.py:79:63: error[invalid-argument-type] Argument to bound method `map` is incorrect: Expected `(str, /) -> Unknown`, found `Unknown | None`
+ src/schemathesis/specs/graphql/scalars.py:80:46: error[invalid-argument-type] Argument to bound method `map` is incorrect: Expected `(str, /) -> Unknown`, found `Unknown | None`
+ src/schemathesis/specs/graphql/scalars.py:81:51: error[invalid-argument-type] Argument to bound method `map` is incorrect: Expected `(str, /) -> Unknown`, found `Unknown | None`
+ src/schemathesis/specs/graphql/scalars.py:82:51: error[invalid-argument-type] Argument to bound method `map` is incorrect: Expected `(str, /) -> Unknown`, found `Unknown | None`
+ src/schemathesis/specs/graphql/scalars.py:83:37: error[invalid-argument-type] Argument to bound method `map` is incorrect: Expected `(int, /) -> Unknown`, found `Unknown | None`
+ src/schemathesis/specs/graphql/scalars.py:84:74: error[invalid-argument-type] Argument to bound method `map` is incorrect: Expected `(int, /) -> Unknown`, found `Unknown | None`
+ src/schemathesis/specs/graphql/scalars.py:85:41: error[invalid-argument-type] Argument to bound method `map` is incorrect: Expected `(str, /) -> Unknown`, found `Unknown | None`
+ src/schemathesis/specs/graphql/schemas.py:246:16: error[missing-argument] No argument provided for required parameter `*args`
+ src/schemathesis/specs/openapi/_hypothesis.py:547:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ src/schemathesis/specs/openapi/_hypothesis.py:795:45: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ src/schemathesis/specs/openapi/adapter/parameters.py:118:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ src/schemathesis/specs/openapi/adapter/parameters.py:162:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ src/schemathesis/specs/openapi/adapter/parameters.py:190:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ src/schemathesis/specs/openapi/adapter/parameters.py:226:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ src/schemathesis/specs/openapi/adapter/parameters.py:579:16: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ src/schemathesis/specs/openapi/adapter/parameters.py:1069:16: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ src/schemathesis/specs/openapi/examples.py:96:9: error[missing-argument] No argument provided for required parameter `*args`
+ src/schemathesis/specs/openapi/negative/__init__.py:199:24: error[missing-argument] No argument provided for required parameter `*args`
+ src/schemathesis/specs/openapi/negative/__init__.py:221:16: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ src/schemathesis/specs/openapi/schemas.py:533:16: error[missing-argument] No argument provided for required parameter `*args`
+ src/schemathesis/specs/openapi/stateful/__init__.py:200:37: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ src/schemathesis/specs/openapi/stateful/__init__.py:342:16: error[missing-argument] No argument provided for required parameter `*args`
- Found 290 diagnostics
+ Found 316 diagnostics

vision (https://github.com/pytorch/vision)
- torchvision/models/_api.py:198:45: error[unresolved-attribute] Object of type `(...) -> M@register_model` has no attribute `__name__`
+ torchvision/models/_api.py:198:45: error[unresolved-attribute] Object of type `(...) -> M@wrapper` has no attribute `__name__`

mitmproxy (https://github.com/mitmproxy/mitmproxy)
- test/mitmproxy/tools/console/test_flowview.py:92:5: error[invalid-assignment] Object of type `MagicMock` is not assignable to attribute `_get_content_view` of type `_lru_cache_wrapper[Unknown]`
+ test/mitmproxy/tools/console/test_flowview.py:92:5: error[invalid-assignment] Object of type `MagicMock` is not assignable to attribute `_get_content_view` of type `_lru_cache_wrapper[tuple[str, list[Unknown]]]`

tornado (https://github.com/tornadoweb/tornado)
- tornado/test/gen_test.py:300:26: error[unresolved-attribute] Object of type `(...) -> Future[Unknown]` has no attribute `__name__`
+ tornado/test/gen_test.py:300:26: error[unresolved-attribute] Object of type `[_T'return](...) -> Future[Unknown]` has no attribute `__name__`

pydantic (https://github.com/pydantic/pydantic)
- pydantic/config.py:1285:9: error[unresolved-attribute] Unresolved attribute `__pydantic_config__` on type `_TypeT@with_config`
+ pydantic/config.py:1285:9: error[unresolved-attribute] Unresolved attribute `__pydantic_config__` on type `_TypeT@inner`
+ pydantic/deprecated/class_validators.py:155:17: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- pydantic/functional_serializers.py:315:12: error[invalid-return-type] Return type does not match returned value: expected `((_FieldWrapSerializerT@field_serializer, /) -> _FieldWrapSerializerT@field_serializer) | ((_FieldPlainSerializerT@field_serializer, /) -> _FieldPlainSerializerT@field_serializer)`, found `def dec(f: ((Any, /) -> Any) | ((Any, SerializationInfo[Any], /) -> Any) | ((Any, Any, /) -> Any) | ... omitted 7 union elements) -> PydanticDescriptorProxy[Any]`
+ pydantic/functional_serializers.py:315:12: error[invalid-return-type] Return type does not match returned value: expected `[_FieldWrapSerializerT'return](_FieldWrapSerializerT'return, /) -> _FieldWrapSerializerT'return`, found `def dec(f: ((Any, /) -> Any) | ((Any, SerializationInfo[Any], /) -> Any) | ((Any, Any, /) -> Any) | ... omitted 7 union elements) -> PydanticDescriptorProxy[Any]`
- Found 3154 diagnostics
+ Found 3155 diagnostics

optuna (https://github.com/optuna/optuna)
- optuna/_convert_positional_args.py:98:24: error[unresolved-attribute] Object of type `(**_P@convert_positional_args) -> _T@convert_positional_args` has no attribute `__name__`
+ optuna/_convert_positional_args.py:98:24: error[unresolved-attribute] Object of type `(**_P@converter_decorator) -> _T@converter_decorator` has no attribute `__name__`
- optuna/_convert_positional_args.py:106:39: error[unresolved-attribute] Object of type `(**_P@convert_positional_args) -> _T@convert_positional_args` has no attribute `__name__`
+ optuna/_convert_positional_args.py:106:39: error[unresolved-attribute] Object of type `(**_P@converter_decorator) -> _T@converter_decorator` has no attribute `__name__`
- optuna/_convert_positional_args.py:119:24: error[unresolved-attribute] Object of type `(**_P@convert_positional_args) -> _T@convert_positional_args` has no attribute `__name__`
+ optuna/_convert_positional_args.py:119:24: error[unresolved-attribute] Object of type `(**_P@converter_decorator) -> _T@converter_decorator` has no attribute `__name__`
- optuna/_convert_positional_args.py:129:24: error[unresolved-attribute] Object of type `(**_P@convert_positional_args) -> _T@convert_positional_args` has no attribute `__name__`
+ optuna/_convert_positional_args.py:129:24: error[unresolved-attribute] Object of type `(**_P@converter_decorator) -> _T@converter_decorator` has no attribute `__name__`
- optuna/_deprecated.py:107:53: error[unresolved-attribute] Object of type `(**FP@deprecated_func) -> FT@deprecated_func` has no attribute `__name__`
+ optuna/_deprecated.py:107:53: error[unresolved-attribute] Object of type `(**FP@decorator) -> FT@decorator` has no attribute `__name__`
- optuna/_experimental.py:73:46: error[unresolved-attribute] Object of type `(**FP@experimental_func) -> FT@experimental_func` has no attribute `__qualname__`
+ optuna/_experimental.py:73:46: error[unresolved-attribute] Object of type `(**FP@decorator) -> FT@decorator` has no attribute `__qualname__`
+ optuna/cli.py:733:17: error[invalid-argument-type] Argument is incorrect: Expected `BaseSampler | None`, found `Unknown | BaseStorage | bool | None`
+ optuna/storages/_rdb/alembic/versions/v1.3.0.a.py:63:59: error[invalid-argument-type] Argument to function `loads` is incorrect: Expected `str | bytes | bytearray`, found `Unknown | Column[str]`
+ optuna/storages/_rdb/alembic/versions/v3.0.0.c.py:128:25: error[invalid-assignment] Object of type `(Unknown & ~None) | Column[int | float]` is not assignable to `int | float`
+ optuna/storages/_rdb/alembic/versions/v3.0.0.d.py:132:25: error[invalid-assignment] Object of type `Unknown | Column[int | float]` is not assignable to `int | float`
+ optuna/storages/_rdb/models.py:105:16: error[invalid-return-type] Return type does not match returned value: expected `list[StudyDirectionModel]`, found `list[Self@where_study_id]`
+ optuna/storages/_rdb/models.py:137:16: error[invalid-return-type] Return type does not match returned value: expected `list[StudyUserAttributeModel]`, found `list[Self@where_study_id]`
+ optuna/storages/_rdb/models.py:169:16: error[invalid-return-type] Return type does not match returned value: expected `list[StudySystemAttributeModel]`, found `list[Self@where_study_id]`
+ optuna/storages/_rdb/models.py:323:16: error[invalid-return-type] Return type does not match returned value: expected `list[TrialUserAttributeModel]`, found `list[Self@where_trial_id]`
+ optuna/storages/_rdb/models.py:355:16: error[invalid-return-type] Return type does not match returned value: expected `list[TrialSystemAttributeModel]`, found `list[Self@where_trial_id]`
+ optuna/storages/_rdb/models.py:399:16: error[invalid-return-type] Return type does not match returned value: expected `list[TrialParamModel]`, found `list[Self@where_trial_id]`
+ optuna/storages/_rdb/models.py:461:16: error[invalid-return-type] Return type does not match returned value: expected `list[TrialValueModel]`, found `list[Self@where_trial_id]`
+ optuna/storages/_rdb/models.py:533:16: error[invalid-return-type] Return type does not match returned value: expected `list[TrialIntermediateValueModel]`, found `list[Self@where_trial_id]`
+ optuna/storages/_rdb/storage.py:628:21: error[invalid-argument-type] Argument to function `json_to_distribution` is incorrect: Expected `str`, found `Unknown | Column[Unknown]`
+ tests/artifacts_tests/test_upload_artifact.py:126:23: error[missing-argument] No arguments provided for required parameters `file_path`, `study_or_trial`
+ tests/artifacts_tests/test_upload_artifact.py:133:23: error[missing-argument] No argument provided for required parameter `study_or_trial`
- tests/artifacts_tests/test_upload_artifact.py:123:74: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/artifacts_tests/test_upload_artifact.py:127:21: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/artifacts_tests/test_upload_artifact.py:134:21: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ tests/storages_tests/rdb_tests/test_storage.py:297:30: error[not-subscriptable] Cannot subscript object of type `None` with no `__getitem__` method
+ tests/storages_tests/rdb_tests/test_storage.py:298:29: error[not-subscriptable] Cannot subscript object of type `None` with no `__getitem__` method
- tests/study_tests/test_study.py:174:59: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/study_tests/test_study.py:699:51: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ tests/study_tests/test_study.py:1156:36: error[invalid-argument-type] Argument to bound method `_log_completed_trial` is incorrect: Expected `list[int | float]`, found `Unknown | list[int | float] | None`
+ tests/study_tests/test_study.py:1161:36: error[invalid-argument-type] Argument to bound method `_log_completed_trial` is incorrect: Expected `list[int | float]`, found `Unknown | list[int | float] | None`
+ tests/study_tests/test_study.py:1166:36: error[invalid-argument-type] Argument to bound method `_log_completed_trial` is incorrect: Expected `list[int | float]`, found `Unknown | list[int | float] | None`
+ tests/study_tests/test_study.py:1252:19: error[invalid-argument-type] Argument to class `tuple` is incorrect: Expected `Iterable[Unknown]`, found `Unknown | list[int | float] | None`
- tests/study_tests/test_study.py:1450:39: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/study_tests/test_study.py:1520:47: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/study_tests/test_study.py:1526:48: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/study_tests/test_study.py:1547:66: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/study_tests/test_study.py:1588:31: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/study_tests/test_study.py:1705:69: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/test_convert_positional_args.py:33:12: error[unresolved-attribute] Object of type `(...) -> Unknown` has no attribute `__name__`
+ tests/test_convert_positional_args.py:33:12: error[unresolved-attribute] Object of type `(*, a: int, b: int, c: int) -> int` has no attribute `__name__`
- tests/test_convert_positional_args.py:39:48: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/test_convert_positional_args.py:60:36: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/test_convert_positional_args.py:61:38: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/test_convert_positional_args.py:137:38: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/test_convert_positional_args.py:141:40: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/test_deprecated.py:56:12: error[unresolved-attribute] Object of type `(...) -> Unknown` has no attribute `__name__`
+ tests/test_deprecated.py:56:12: error[unresolved-attribute] Object of type `() -> int` has no attribute `__name__`
- tests/test_deprecated.py:72:12: error[unresolved-attribute] Object of type `(...) -> Unknown` has no attribute `__name__`
+ tests/test_deprecated.py:72:12: error[unresolved-attribute] Object of type `(self) -> None` has no attribute `__name__`
- tests/test_deprecated.py:76:33: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/test_deprecated.py:137:12: error[unresolved-attribute] Object of type `(...) -> Unknown` has no attribute `__name__`
+ tests/test_deprecated.py:137:12: error[unresolved-attribute] Object of type `() -> int` has no attribute `__name__`
- tests/test_deprecated.py:192:12: error[unresolved-attribute] Object of type `(...) -> Unknown` has no attribute `__name__`
+ tests/test_deprecated.py:192:12: error[unresolved-attribute] Object of type `() -> int` has no attribute `__name__`
- tests/test_experimental.py:55:12: error[unresolved-attribute] Object of type `(...) -> Unknown` has no attribute `__name__`
+ tests/test_experimental.py:55:12: error[unresolved-attribute] Object of type `() -> int` has no attribute `__name__`
- tests/test_experimental.py:68:12: error[unresolved-attribute] Object of type `(...) -> Unknown` has no attribute `__name__`
+ tests/test_experimental.py:68:12: error[unresolved-attribute] Object of type `() -> None` has no attribute `__name__`
- tests/test_experimental.py:81:12: error[unresolved-attribute] Object of type `(...) -> Unknown` has no attribute `__name__`
+ tests/test_experimental.py:81:12: error[unresolved-attribute] Object of type `(self) -> None` has no attribute `__name__`
- tests/test_experimental.py:85:33: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:459:60: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:593:30: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:594:29: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:600:32: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:603:33: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:606:37: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:609:34: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:619:31: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:620:39: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:624:36: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:627:37: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/trial_tests/test_trial.py:630:41: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- Found 578 diagnostics
+ Found 569 diagnostics

pandera (https://github.com/pandera-dev/pandera)
+ pandera/api/dataframe/model.py:246:16: warning[redundant-cast] Value is already of type `DataFrameBase[Self@__new__]`
+ pandera/api/pyspark/model.py:124:9: error[invalid-method-override] Invalid override of method `validate`: Definition is incompatible with `pandera.api.dataframe.model.DataFrameModel.validate`
- tests/dask/test_dask.py:31:55: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/dask/test_dask.py:36:24: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/dask/test_dask.py:41:24: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ tests/pandas/test_decorators.py:363:25: error[invalid-argument-type] Argument to function `fn_with_check_input` is incorrect: Expected `pandera.typing.pandas.DataFrame[DfModel]`, found `pandas.core.frame.DataFrame`
- tests/pandas/test_decorators.py:824:65: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/pandas/test_decorators.py:1410:69: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/pandas/test_decorators.py:1412:64: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ tests/pyspark/test_pyspark_config.py:139:32: error[unresolved-attribute] Object of type `DataFrameBase[TestSchema]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_config.py:142:18: error[unresolved-attribute] Object of type `DataFrameBase[TestSchema]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_config.py:219:25: error[unresolved-attribute] Object of type `DataFrameBase[TestSchema]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_config.py:222:18: error[unresolved-attribute] Object of type `DataFrameBase[TestSchema]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_config.py:328:18: error[unresolved-attribute] Object of type `DataFrameBase[TestSchema]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_config.py:332:18: error[unresolved-attribute] Object of type `DataFrameBase[TestSchema]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_container.py:267:20: error[unresolved-attribute] Object of type `DataFrameBase[PanderaSchema]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_container.py:304:16: error[unresolved-attribute] Object of type `DataFrameBase[PanderaSchema]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_error.py:207:24: error[unresolved-attribute] Object of type `DataFrameBase[PanderaSchema]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_error.py:208:26: error[unresolved-attribute] Object of type `DataFrameBase[PanderaSchema]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_model.py:116:12: error[unresolved-attribute] Object of type `DataFrameBase[Model]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_model.py:144:12: error[unresolved-attribute] Object of type `DataFrameBase[Model]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_model.py:194:12: error[unresolved-attribute] Object of type `DataFrameBase[PanderaSchema]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_model.py:280:12: error[unresolved-attribute] Object of type `DataFrameBase[UniqueSingleColumn]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_model.py:281:22: error[unresolved-attribute] Object of type `DataFrameBase[UniqueSingleColumn]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_model.py:300:12: error[unresolved-attribute] Object of type `DataFrameBase[UniqueMultipleColumns]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_model.py:301:22: error[unresolved-attribute] Object of type `DataFrameBase[UniqueMultipleColumns]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_model.py:337:12: error[unresolved-attribute] Object of type `DataFrameBase[UniqueMultipleColumns]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_model.py:340:22: error[unresolved-attribute] Object of type `DataFrameBase[UniqueMultipleColumns]` has no attribute `pandera`
+ tests/pyspark/test_pyspark_model.py:525:16: error[unresolved-attribute] Object of type `DataFrameBase[ExampleDFModel]` has no attribute `pandera`
- tests/strategies/test_strategies.py:993:35: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- Found 1618 diagnostics
+ Found 1634 diagnostics

Expression (https://github.com/cognitedata/Expression)
- tests/test_curried.py:51:20: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- Found 202 diagnostics
+ Found 201 diagnostics

antidote (https://github.com/Finistere/antidote)
- src/antidote/lib/interface_ext/__init__.py:1023:14: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `(C@when, /) -> C@when`
+ src/antidote/lib/interface_ext/__init__.py:1023:14: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `[C'return](C'return, /) -> C'return`
- src/antidote/lib/interface_ext/__init__.py:1026:64: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `(C@overriding, /) -> C@overriding`
+ src/antidote/lib/interface_ext/__init__.py:1026:64: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `[C'return](C'return, /) -> C'return`
- src/antidote/lib/interface_ext/__init__.py:1275:10: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `(C@when, /) -> C@when`
+ src/antidote/lib/interface_ext/__init__.py:1275:10: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `[C'return](C'return, /) -> C'return`
- src/antidote/lib/interface_ext/__init__.py:1278:60: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `(C@overriding, /) -> C@overriding`
+ src/antidote/lib/interface_ext/__init__.py:1278:60: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `[C'return](C'return, /) -> C'return`
- src/antidote/lib/interface_ext/__init__.py:1381:10: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `(T@FunctionImplements, /) -> T@FunctionImplements`
+ src/antidote/lib/interface_ext/__init__.py:1381:10: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `[T'return](T'return, /) -> T'return`
- src/antidote/lib/interface_ext/_function.py:76:66: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ src/antidote/lib/interface_ext/_function.py:53:16: error[invalid-return-type] Return type does not match returned value: expected `[**P'return, Out'return](**P'return@FunctionInterfaceImpl) -> Out'return`, found `(**P@FunctionInterfaceImpl) -> Out@FunctionInterfaceImpl`
+ src/antidote/lib/interface_ext/_function.py:61:16: error[invalid-return-type] Return type does not match returned value: expected `Dependency[[**P'return, Out'return](**P'return@FunctionInterfaceImpl) -> Out'return]`, found `ImplementationQuery[(**P@FunctionInterfaceImpl) -> Out@FunctionInterfaceImpl]`
+ src/antidote/lib/lazy_ext/_lazy.py:354:16: error[invalid-return-type] Return type does not match returned value: expected `Dependency[Out@LazyMethodImpl]`, found `LazyCall[T'return@InjectedMethod | Out@LazyMethodImpl]`
- tests/core/test_inject.py:113:15: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/core/test_inject.py:121:22: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/core/test_inject.py:123:14: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ tests/core/test_inject.py:162:48: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/core/test_inject.py:154:31: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ tests/core/test_inject.py:165:30: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/core/test_inject.py:156:23: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/core/test_inject.py:209:29: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ tests/core/test_inject.py:517:16: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/core/test_inject.py:522:16: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
- tests/core/test_inject_wrapper.py:14:45: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/core/test_inject_wrapper.py:443:31: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/core/test_inject_wrapper.py:445:23: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/core/test_inject_wrapper.py:446:31: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/core/test_inject_wrapper.py:448:41: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/core/test_wiring.py:294:28: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/lib/injectable/test_injectable.py:176:33: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ tests/lib/interface/test_function.py:97:12: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_function.py:227:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_function.py:228:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_function.py:229:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:45:18: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:46:18: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:46:50: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:47:18: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:48:18: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:48:51: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:53:12: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:63:33: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:67:43: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:76:25: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:77:25: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:85:12: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:91:18: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:92:18: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:93:43: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:110:12: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:155:18: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:156:18: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:174:12: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:193:12: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:224:12: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:242:12: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:269:12: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:288:12: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/lib/interface/test_lazy.py:334:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:335:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:336:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:337:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:365:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:366:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:367:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:368:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:396:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:397:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:398:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:399:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:427:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:428:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:429:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:430:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:501:20: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:672:24: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:680:24: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:700:24: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:708:24: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:753:24: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/interface/test_lazy.py:769:24: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/lazy/test_lazy.py:62:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/lazy/test_lazy.py:625:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/lazy/test_lazy.py:629:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
+ tests/lib/lazy/test_lazy.py:630:12: error[missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
- tests/lib/lazy/test_lazy.py:1143:42: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ tests/test_examples.py:37:24: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_examples.py:41:20: error[missing-argument] No argument provided for required parameter `**kwargs`
+ tests/test_examples.py:41:37: error[missing-argument] No argument provided for required parameter `**kwargs`
- Found 248 diagnostics
+ Found 298 diagnostics

Tanjun (https://github.com/FasterSpeeding/Tanjun)
+ tanjun/checks.py:1051:23: error[invalid-type-arguments] Type `TypeVar` is not assignable to upper bound `Context` of type variable `_ContextT@_AllChecks`
- tanjun/clients.py:2801:16: error[invalid-return-type] Return type does not match returned value: expected `((...) -> Coroutine[Any, Any, _T@get_callback_override] | _T@get_callback_override) | None`, found `Unknown | ((...) -> Coroutine[Any, Any, _T@get_callback_override | Coroutine[Any, Any, _T@get_callback_override]] | _T@get_callback_override) | None`
- tanjun/dependencies/data.py:171:32: error[invalid-argument-type] Argument to bound method `set_value` is incorrect: Expected `_T@make_lc_resolver`, found `_T@make_lc_resolver | Coroutine[Any, Any, _T@make_lc_resolver]`
- tanjun/dependencies/data.py:172:20: error[invalid-return-type] Return type does not match returned value: expected `_T@make_lc_resolver`, found `_T@make_lc_resolver | Coroutine[Any, Any, _T@make_lc_resolver]`
- tanjun/dependencies/data.py:220:12: error[invalid-return-type] Return type does not match returned value: expected `_T@inject_lc`, found `_T@inject_lc | Coroutine[Any, Any, _T@inject_lc]`
+ tanjun/dependencies/data.py:347:12: error[invalid-return-type] Return type does not match returned value: expected `_T@cached_inject`, found `Unknown | Coroutine[Any, Any, Unknown]`
- tanjun/dependencies/data.py:265:13: error[invalid-assignment] Object of type `_T@_CacheCallback | Coroutine[Any, Any, _T@_CacheCallback]` is not assignable to attribute `_result` of type `_T@_CacheCallback | Literal[_DefaultFlag.NO_DEFAULT]`
- tanjun/dependencies/data.py:269:20: error[invalid-return-type] Return type does not match returned value: expected `_T@_CacheCallback`, found `_T@_CacheCallback | Coroutine[Any, Any, _T@_CacheCallback]`
- tanjun/dependencies/data.py:301:12: error[invalid-return-type] Return type does not match returned value: expected `(...) -> Coroutine[Any, Any, _T@cache_callback]`, found `_CacheCallback[_T@cache_callback | Coroutine[Any, Any, _T@cache_callback]]`
- tanjun/dependencies/data.py:347:12: error[invalid-return-type] Return type does not match returned value: expected `_T@cached_inject`, found `_T@cached_inject | Coroutine[Any, Any, _T@cached_inject | Coroutine[Any, Any, _T@cached_inject]]`
- Found 141 diagnostics
+ Found 135 diagnostics

trio (https://github.com/python-trio/trio)
- src/trio/_channel.py:610:12: error[invalid-return-type] Return type does not match returned value: expected `(**P@as_safe_channel) -> AbstractAsyncContextManager[ReceiveChannel[T@as_safe_channel], bool | None]`, found `(self, *args: P@as_safe_channel.args, **kwargs: P@as_safe_channel.kwargs) -> _AsyncGeneratorContextManager[RecvChanWrapper[T@as_safe_channel], None]`
+ src/trio/_channel.py:610:12: error[invalid-return-type] Return type does not match returned value: expected `[_T_co'return, _ExitT_co'return, ReceiveType'return](**P@as_safe_channel) -> AbstractAsyncContextManager[ReceiveChannel[T@as_safe_channel], bool | None]`, found `(self, *args: P@as_safe_channel.args, **kwargs: P@as_safe_channel.kwargs) -> _AsyncGeneratorContextManager[RecvChanWrapper[T@as_safe_channel], None]`
- src/trio/_tests/test_fakenet.py:136:72: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- src/trio/_tests/test_fakenet.py:193:32: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ src/trio/_tests/test_path.py:41:16: error[invalid-context-manager] Object of type `CoroutineType[Any, Any, AsyncIOWrapper[TextIOWrapper[_WrappedBuffer]]] | CoroutineType[Any, Any, AsyncIOWrapper[BinaryIO]] | CoroutineType[Any, Any, AsyncIOWrapper[IO[Any]]]` cannot be used with `async with` because it does not implement `__aenter__` and `__aexit__`
- src/trio/_tests/test_path.py:124:12: warning[possibly-missing-attribute] Attribute `__name__` may be missing on object of type `Unknown | ((...) -> Awaitable[Unknown])`
+ src/trio/_tests/test_path.py:124:12: warning[possibly-missing-attribute] Attribute `__name__` may be missing on object of type `Unknown | ([_T_co'return, PathT'return](...) -> Awaitable[PathT'return])`
- src/trio/_tests/test_path.py:125:12: warning[possibly-missing-attribute] Attribute `__qualname__` may be missing on object of type `Unknown | ((...) -> Awaitable[Unknown])`
+ src/trio/_tests/test_path.py:125:12: warning[possibly-missing-attribute] Attribute `__qualname__` may be missing on object of type `Unknown | ([_T_co'return, PathT'return](...) -> Awaitable[PathT'return])`
- src/trio/_tests/test_path.py:128:12: warning[possibly-missing-attribute] Attribute `__qualname__` may be missing on object of type `Unknown | ((...) -> Awaitable[Unknown])`
+ src/trio/_tests/test_path.py:128:12: warning[possibly-missing-attribute] Attribute `__qualname__` may be missing on object of type `Unknown | ([_T_co'return, PathT'return](...) -> Awaitable[PathT'return])`
- src/trio/_tests/test_socket.py:446:20: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- src/trio/_tests/test_socket.py:942:65: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- src/trio/_tests/type_tests/path.py:64:5: error[type-assertion-failure] Type `Path` does not match asserted type `Unknown`
- src/trio/_tests/type_tests/path.py:65:5: error[type-assertion-failure] Type `Path` does not match asserted type `Unknown`
- src/trio/_tests/type_tests/path.py:119:5: error[type-assertion-failure] Type `AsyncIOWrapper[TextIOWrapper[_WrappedBuffer]]` does not match asserted type `Unknown`
- src/trio/_tests/type_tests/path.py:120:5: error[type-assertion-failure] Type `AsyncIOWrapper[TextIOWrapper[_WrappedBuffer]]` does not match asserted type `Unknown`
- src/trio/_tests/type_tests/path.py:121:5: error[type-assertion-failure] Type `AsyncIOWrapper[TextIOWrapper[_WrappedBuffer]]` does not match asserted type `Unknown`
- src/trio/_tests/type_tests/path.py:122:5: error[type-assertion-failure] Type `AsyncIOWrapper[TextIOWrapper[_WrappedBuffer]]` does not match asserted type `Unknown`
- src/trio/_tests/type_tests/path.py:123:5: error[type-assertion-failure] Type `AsyncIOWrapper[FileIO]` does not match asserted type `Unknown`
- src/trio/_tests/type_tests/path.py:124:5: error[type-assertion

... (truncated 2909 lines) ...
Memory usage changes were detected when running on open source projects
trio (https://github.com/python-trio/trio)
-     struct metadata = ~10MB
+     struct metadata = ~11MB

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 30, 2026

ecosystem-analyzer results

Lint rule Added Removed Changed
missing-argument 831 0 0
invalid-argument-type 461 4 7
unresolved-attribute 332 0 72
unused-type-ignore-comment 10 241 0
possibly-missing-attribute 173 6 24
unsupported-operator 198 0 5
no-matching-overload 123 1 0
invalid-return-type 57 6 8
not-subscriptable 61 0 0
unknown-argument 38 0 0
invalid-assignment 23 2 7
type-assertion-failure 0 9 12
invalid-method-override 15 0 2
call-non-callable 10 5 0
too-many-positional-arguments 13 0 0
invalid-context-manager 11 0 0
not-iterable 8 0 0
empty-body 0 0 6
redundant-cast 4 2 0
invalid-await 4 0 0
invalid-type-arguments 1 0 0
invalid-type-form 0 1 0
parameter-already-assigned 1 0 0
Total 2,374 277 143

Full report with detailed diff (timing results)

@carljm
Copy link
Contributor

carljm commented Jan 30, 2026

Looks like we need to bump the expected diagnostics on static-frame benchmark.

@carljm
Copy link
Contributor

carljm commented Jan 30, 2026

The conformance suite false positives all look like Concatenate usage.

@carljm
Copy link
Contributor

carljm commented Jan 30, 2026

The PyGithub diagnostic at https://github.com/PyGithub/PyGithub/blob/f2540db50423aa124beaeb8c7bfba7098a549c82/github/GithubObject.py#L663 looks like it might deserve investigation? Seems like a false positive.

Other new diagnostics I'm seeing in the first few projects look like true positives, or at least unrelated issues that are exposed because we now understand e.g. lru_cache() decorator.

@dcreager
Copy link
Member Author

dcreager commented Feb 2, 2026

The PyGithub diagnostic at https://github.com/PyGithub/PyGithub/blob/f2540db50423aa124beaeb8c7bfba7098a549c82/github/GithubObject.py#L663 looks like it might deserve investigation? Seems like a false positive.

This was a TODO in the new mdtests as well. The cause was that in our invalid-return-type checks, we were grabbing the inferred type of the return type annotation node directly, instead of getting the inferred type of the overall function definition, and getting the return type from its signature. I presume we were doing that to make sure we were getting the unmodified return type for async functions. But our raw_signature vs signature distinction takes care of this. We now grab the raw signature of the function definition, which includes e.g. the new generic callable transformation, but does not include the CoroutineType transformation for async functions.

@dcreager
Copy link
Member Author

dcreager commented Feb 2, 2026

This was a TODO in the new mdtests as well.

This was a new false positive in the typing conformance suite, too, which has also been fixed with this latest change. The remaining two new false positives are Concatenate, as @carljm mentioned.

@carljm
Copy link
Contributor

carljm commented Feb 3, 2026

We now see even more diagnostics on static-frame, so that needs bumping again so we can get benchmark results here. (Usually we bump it to a nearby whole number, not the exact number -- the goal is just to catch any massive unexpected increase. So let's bump it to maybe 1800.)

It would be great if we could avoid the conformance suite false positives with Concatenate; we have Todo handling for Concatenate that generally aims to avoid false positives. It's not actually totally clear to me why this PR is causing those false positives.

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 excellent! Clear code, thorough tests. Thank you!


# revealed: [T](T, /) -> T
reveal_type(decorator_factory())
# revealed: ty_extensions.GenericContext[T@decorator_factory]
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it a problem that we still call this T@decorator_factory? It seems to suggest a binding of the typevar that is not correct. (Though I'm not sure what I'd expect to see displayed there -- it's bound to an anonymous Callable type.)

Copy link
Member

@AlexWaygood AlexWaygood Feb 3, 2026

Choose a reason for hiding this comment

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

T@decorator_factory'return? T@decorator_factory:return?T@<return of decorator_factory>?

Copy link
Member Author

@dcreager dcreager Feb 3, 2026

Choose a reason for hiding this comment

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

T'return@decorator_factory is probably the easiest modification I could make. The @whatever part comes from the BindingContext, which currently can only come from an actual Definition, which we don't have for the Callable in the return type. But I could synthesize a new TypeVar with the 'return suffix in its name...let me give that a shot

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

Comment on lines +2675 to +2680
let enclosing_function =
nearest_enclosing_function(self.db(), self.index, self.scope())
.expect("should be in a function body scope");
let declared_ty = enclosing_function
.last_definition_raw_signature(self.db())
.return_ty;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we actually infer and store the "adjusted" type as the type of the return-annotation node? That would imply a) that we don't need to do this extra dance here, and b) that I think we'd get more accurate LSP hover types for the return annotation, in this generic-callable special case.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added astral-sh/ty#2709 to track this

Comment on lines 1834 to 1838
// If the constraint set is cyclic, we'll hit an infinite expansion when trying to add type
// mappings for it.
if constraints.is_cyclic(self.db) {
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume this was added because you ran into it somewhere -- should we capture that in a test? Or is it already in an existing test?

Copy link
Member Author

Choose a reason for hiding this comment

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

The paramspec tests exercise this (and stack overflow without it)

Comment on lines +654 to +656
fn visit_type(&self, db: &'db dyn Db, ty: Type<'db>) {
walk_type_with_recursion_guard(db, ty, self, &self.recursion_guard);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

A lot of TypeVisitor implementations have this boilerplate -- seems like it should be the default implementation of visit_type maybe?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think the issue with that is that recursion_guard can only come from the concrete struct that implements Visitor. A default implementation would not know whether the implementing type has such a field.

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'd have to be a trait method to return an (optional?) recursion guard, and the default visit would call that. But this can also be a separate change, it's not that important.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not totally sure that that would really be less boilerplate overall, so I agree looking at that separately seems best

Copy link
Contributor

@carljm carljm Feb 3, 2026

Choose a reason for hiding this comment

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

I think it would be strictly less, but not by much. For the common case (which is now up to 4 or 5 visitors) instead of implementing visit you'd implement the method to return your recursion guard. Same number of methods, but a smaller method body. Mainly I see the win as not repeating everywhere "yes, for every type I want to... visit the type". But yeah happy to look at it separately.

Copy link
Member

@AlexWaygood AlexWaygood Feb 3, 2026

Choose a reason for hiding this comment

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

Right, but that's still at least one method that you have to implement every time for the common case, and for the uncommon case you still have to implement visit_type, e.g.

fn visit_type(&self, db: &'db dyn Db, ty: Type<'db>) {

Personally, while I agree the amount of boilerplate is annoying, I like the way the current design gives us symmetry between the common case and the uncommon case — the same method is required in both cases

@AlexWaygood
Copy link
Member

(Looks like there's another benchmark assertion failing, this time on the pandas benchmark. You can run them locally with cargo bench -p ruff_benchmark --bench=ty_walltime IIRC)

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 4, 2026

CodSpeed Performance Report

Merging this PR will degrade performance by 5.25%

Comparing dcreager/callable-genctx (b47338e) with main (e95e09c)

Summary

❌ 1 (👁 1) regressed benchmark
✅ 53 untouched benchmarks

Performance Changes

Mode Benchmark BASE HEAD Efficiency
👁 WallTime static_frame 21.3 s 22.5 s -5.25%

@dcreager dcreager merged commit 4f684db into main Feb 4, 2026
49 checks passed
@dcreager dcreager deleted the dcreager/callable-genctx branch February 4, 2026 01:41
carljm pushed a commit that referenced this pull request Feb 10, 2026
…ParamSpec+Concatenate

Bisected the issue to commit 4f684db ([ty] Detect generic `Callable`s
in function signatures #22954). The heuristic for detecting generic
Callables in return position incorrectly interacts with ParamSpec +
Concatenate patterns used in decorators like hypothesis.composite.

https://claude.ai/code/session_01MiAwMHE7cSZFmdRugzFrE2
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.

understand implicit generic context of a Callable annotation

3 participants