Skip to content

[ty] Allow self-referential imports outside of the global scope#22963

Merged
charliermarsh merged 1 commit intomainfrom
charlie/same
Jan 30, 2026
Merged

[ty] Allow self-referential imports outside of the global scope#22963
charliermarsh merged 1 commit intomainfrom
charlie/same

Conversation

@charliermarsh
Copy link
Member

Summary

Closes astral-sh/ty#2596.

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 30, 2026

Typing conformance results

No changes detected ✅

@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
pip (https://github.com/pypa/pip)
+ src/pip/_internal/locations/__init__.py:433:19: warning[possibly-missing-import] Member `_distutils` of module `pip._internal.locations` may be missing
- Found 625 diagnostics
+ Found 626 diagnostics

xarray (https://github.com/pydata/xarray)
- xarray/core/indexing.py:1802:38: error[unresolved-import] Module `xarray.core.indexing` has no member `VectorizedIndexer`
- xarray/core/indexing.py:1802:57: error[unresolved-import] Module `xarray.core.indexing` has no member `apply_indexer`
- xarray/core/indexing.py:1802:72: error[unresolved-import] Module `xarray.core.indexing` has no member `as_indexable`
- Found 1770 diagnostics
+ Found 1767 diagnostics

zope.interface (https://github.com/zopefoundation/zope.interface)
- src/zope/interface/tests/test_declarations.py:673:60: error[unresolved-import] Module `zope.interface.tests.test_declarations` has no member `FooNoCall`
+ src/zope/interface/tests/test_declarations.py:676:9: error[unresolved-attribute] Unresolved attribute `__name__` on type `FooNoCall`
- src/zope/interface/tests/test_declarations.py:689:60: error[unresolved-import] Module `zope.interface.tests.test_declarations` has no member `FooImplementedNone`
+ src/zope/interface/tests/test_declarations.py:683:13: error[unresolved-attribute] Object of type `FooNoCall` has no attribute `__providedBy__`
+ src/zope/interface/tests/test_declarations.py:698:13: error[unresolved-attribute] Class `FooImplementedNone` has no attribute `__providedBy__`
+ src/zope/interface/tests/test_declarations.py:701:13: error[unresolved-attribute] Class `FooImplementedNone` has no attribute `__provides__`
+ src/zope/interface/tests/test_declarations.py:704:13: error[unresolved-attribute] Class `FooImplementedNone` has no attribute `__provides__`
+ src/zope/interface/tests/test_declarations.py:704:46: error[unresolved-attribute] Class `FooImplementedNone` has no attribute `__providedBy__`
- src/zope/interface/tests/test_declarations.py:1157:60: error[unresolved-import] Module `zope.interface.tests.test_declarations` has no member `Foo`
+ src/zope/interface/tests/test_declarations.py:1162:16: error[unresolved-attribute] Object of type `Foo` has no attribute `__implemented__`
+ src/zope/interface/tests/test_declarations.py:1167:23: error[unresolved-attribute] Object of type `Foo` has no attribute `__implemented__`
- src/zope/interface/tests/test_declarations.py:1377:60: error[unresolved-import] Module `zope.interface.tests.test_declarations` has no member `IBar`
- src/zope/interface/tests/test_declarations.py:1378:60: error[unresolved-import] Module `zope.interface.tests.test_declarations` has no member `IFoo`
- src/zope/interface/tests/test_exceptions.py:26:54: error[unresolved-import] Module `zope.interface.tests.test_exceptions` has no member `IDummy`
- src/zope/interface/tests/test_interface.py:1194:57: error[unresolved-import] Module `zope.interface.tests.test_interface` has no member `HashMe`
- src/zope/interface/tests/test_sorting.py:64:55: error[unresolved-import] Module `zope.interface.tests.test_sorting` has no member `I1`
- src/zope/interface/tests/test_sorting.py:66:9: error[invalid-argument-type] Argument to bound method `sort` is incorrect: Argument type `Unknown | <class 'I1'>` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ src/zope/interface/tests/test_sorting.py:66:9: error[invalid-argument-type] Argument to bound method `sort` is incorrect: Argument type `Unknown | <class 'zope.interface.tests.test_sorting.I1'> | <class 'zope.interface.tests.m1.I1'>` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`

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

prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/flow_engine.py:1818:37: error[unresolved-import] Module `prefect.flow_engine` has no member `run_flow`
- src/prefect/server/schemas/states.py:178:51: error[unresolved-import] Module `prefect.server.schemas.states` has no member `StateType`
- Found 5374 diagnostics
+ Found 5372 diagnostics

dd-trace-py (https://github.com/DataDog/dd-trace-py)
- tests/contrib/django/test_django_dbm.py:27:54: error[unresolved-import] Module `tests.contrib.django.test_django_dbm` has no member `get_cursor`
- tests/contrib/django/test_django_dbm.py:57:54: error[unresolved-import] Module `tests.contrib.django.test_django_dbm` has no member `get_cursor`
- tests/contrib/django/test_django_dbm.py:94:54: error[unresolved-import] Module `tests.contrib.django.test_django_dbm` has no member `get_cursor`
- tests/contrib/django/test_django_dbm.py:141:54: error[unresolved-import] Module `tests.contrib.django.test_django_dbm` has no member `get_cursor`
- tests/contrib/fastapi/test_fastapi.py:635:52: error[unresolved-import] Module `tests.contrib.fastapi.test_fastapi` has no member `_run_websocket_test`
- tests/contrib/fastapi/test_fastapi.py:647:52: error[unresolved-import] Module `tests.contrib.fastapi.test_fastapi` has no member `_run_websocket_send_only_test`
- tests/contrib/fastapi/test_fastapi.py:660:52: error[unresolved-import] Module `tests.contrib.fastapi.test_fastapi` has no member `_run_websocket_test`
- tests/contrib/fastapi/test_fastapi.py:673:52: error[unresolved-import] Module `tests.contrib.fastapi.test_fastapi` has no member `_run_websocket_test`
- tests/contrib/fastapi/test_fastapi.py:749:52: error[unresolved-import] Module `tests.contrib.fastapi.test_fastapi` has no member `_run_websocket_context_propagation_test`
- tests/contrib/graphene/test_graphene.py:123:54: error[unresolved-import] Module `tests.contrib.graphene.test_graphene` has no member `Query`
- tests/contrib/httpx/test_httpx.py:117:48: error[unresolved-import] Module `tests.contrib.httpx.test_httpx` has no member `get_url`
- tests/contrib/httpx/test_httpx.py:153:48: error[unresolved-import] Module `tests.contrib.httpx.test_httpx` has no member `get_url`
- tests/contrib/httpx/test_httpx.py:186:48: error[unresolved-import] Module `tests.contrib.httpx.test_httpx` has no member `get_url`
- tests/contrib/httpx/test_httpx.py:219:48: error[unresolved-import] Module `tests.contrib.httpx.test_httpx` has no member `get_url`
- tests/contrib/httpx/test_httpx.py:251:48: error[unresolved-import] Module `tests.contrib.httpx.test_httpx` has no member `get_url`
- tests/contrib/httpx/test_httpx.py:283:48: error[unresolved-import] Module `tests.contrib.httpx.test_httpx` has no member `get_url`
- tests/contrib/httpx/test_httpx.py:315:48: error[unresolved-import] Module `tests.contrib.httpx.test_httpx` has no member `get_url`
- tests/contrib/httpx/test_httpx.py:347:48: error[unresolved-import] Module `tests.contrib.httpx.test_httpx` has no member `get_url`
- tests/contrib/httpx/test_httpx.py:379:48: error[unresolved-import] Module `tests.contrib.httpx.test_httpx` has no member `get_url`
- tests/contrib/httpx/test_httpx.py:544:48: error[unresolved-import] Module `tests.contrib.httpx.test_httpx` has no member `get_url`
- tests/contrib/logbook/test_logbook_logging.py:61:60: error[unresolved-import] Module `tests.contrib.logbook.test_logbook_logging` has no member `_test_logging`
- tests/contrib/loguru/test_loguru_logging.py:60:58: error[unresolved-import] Module `tests.contrib.loguru.test_loguru_logging` has no member `_test_logging`
- tests/contrib/rediscluster/test.py:233:49: error[unresolved-import] Module `tests.contrib.rediscluster.test` has no member `_get_test_client`
- tests/contrib/rediscluster/test.py:245:49: error[unresolved-import] Module `tests.contrib.rediscluster.test` has no member `_get_test_client`
- tests/contrib/snowflake/test_snowflake.py:123:56: error[unresolved-import] Module `tests.contrib.snowflake.test_snowflake` has no member `_client`
- tests/contrib/snowflake/test_snowflake.py:124:56: error[unresolved-import] Module `tests.contrib.snowflake.test_snowflake` has no member `add_snowflake_query_response`
- tests/contrib/snowflake/test_snowflake.py:125:56: error[unresolved-import] Module `tests.contrib.snowflake.test_snowflake` has no member `req_mock`
- tests/contrib/structlog/test_structlog_logging.py:64:64: error[unresolved-import] Module `tests.contrib.structlog.test_structlog_logging` has no member `_test_logging`
- tests/datastreams/test_processor.py:57:50: error[unresolved-import] Module `tests.datastreams.test_processor` has no member `_decode_datastreams_payload`
- tests/integration/test_integration.py:132:52: error[unresolved-import] Module `tests.integration.test_integration` has no member `FOUR_KB`
- tests/integration/test_priority_sampling.py:62:58: error[unresolved-import] Module `tests.integration.test_priority_sampling` has no member `_prime_tracer_with_priority_sample_rate_from_agent`
- tests/integration/test_priority_sampling.py:63:58: error[unresolved-import] Module `tests.integration.test_priority_sampling` has no member `_turn_tracer_into_dummy`
- tests/integration/test_priority_sampling.py:104:58: error[unresolved-import] Module `tests.integration.test_priority_sampling` has no member `_prime_tracer_with_priority_sample_rate_from_agent`
- tests/integration/test_priority_sampling.py:148:58: error[unresolved-import] Module `tests.integration.test_priority_sampling` has no member `_prime_tracer_with_priority_sample_rate_from_agent`
- tests/integration/test_sampling.py:89:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `RESOURCE`
- tests/integration/test_sampling.py:99:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `TAGS`
- tests/integration/test_sampling.py:111:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `TAGS`
- tests/integration/test_sampling.py:123:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `TAGS`
- tests/integration/test_sampling.py:136:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `RESOURCE`
- tests/integration/test_sampling.py:137:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `TAGS`
- tests/integration/test_sampling.py:154:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `RESOURCE`
- tests/integration/test_sampling.py:171:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `RESOURCE`
- tests/integration/test_sampling.py:209:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `RESOURCE`
- tests/integration/test_sampling.py:210:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `TAGS`
- tests/integration/test_sampling.py:227:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `TAGS`
- tests/integration/test_sampling.py:244:49: error[unresolved-import] Module `tests.integration.test_sampling` has no member `TAGS`
- tests/integration/test_tracemethods.py:86:53: error[unresolved-import] Module `tests.integration.test_tracemethods` has no member `_Class`
- tests/integration/test_tracemethods.py:87:53: error[unresolved-import] Module `tests.integration.test_tracemethods` has no member `_test_method`
- tests/integration/test_tracemethods.py:88:53: error[unresolved-import] Module `tests.integration.test_tracemethods` has no member `_test_method2`
- tests/internal/test_settings.py:640:50: error[unresolved-import] Module `tests.internal.test_settings` has no member `_base_rc_config`
- tests/internal/test_settings.py:641:50: error[unresolved-import] Module `tests.internal.test_settings` has no member `call_apm_tracing_rc`
- tests/opentelemetry/test_config.py:46:49: error[unresolved-import] Module `tests.opentelemetry.test_config` has no member `_global_sampling_rule`
- tests/opentelemetry/test_config.py:80:49: error[unresolved-import] Module `tests.opentelemetry.test_config` has no member `_global_sampling_rule`
- tests/opentelemetry/test_config.py:154:49: error[unresolved-import] Module `tests.opentelemetry.test_config` has no member `_global_sampling_rule`
- tests/opentelemetry/test_config.py:165:49: error[unresolved-import] Module `tests.opentelemetry.test_config` has no member `_global_sampling_rule`
- tests/opentelemetry/test_config.py:176:49: error[unresolved-import] Module `tests.opentelemetry.test_config` has no member `_global_sampling_rule`
- tests/opentelemetry/test_config.py:190:49: error[unresolved-import] Module `tests.opentelemetry.test_config` has no member `_global_sampling_rule`
- tests/opentelemetry/test_context.py:108:50: error[unresolved-import] Module `tests.opentelemetry.test_context` has no member `_subprocess_task`
- tests/opentelemetry/test_context.py:138:50: error[unresolved-import] Module `tests.opentelemetry.test_context` has no member `_subprocess_task`
- tests/opentelemetry/test_logs.py:203:47: error[unresolved-import] Module `tests.opentelemetry.test_logs` has no member `decode_logs_request`
- tests/opentelemetry/test_logs.py:204:47: error[unresolved-import] Module `tests.opentelemetry.test_logs` has no member `extract_log_correlation_attributes`
- tests/opentelemetry/test_logs.py:283:47: error[unresolved-import] Module `tests.opentelemetry.test_logs` has no member `create_mock_grpc_server`
- tests/opentelemetry/test_logs.py:337:47: error[unresolved-import] Module `tests.opentelemetry.test_logs` has no member `create_mock_grpc_server`
- tests/opentelemetry/test_logs.py:338:47: error[unresolved-import] Module `tests.opentelemetry.test_logs` has no member `find_log_record_by_message`
- tests/opentelemetry/test_logs.py:396:47: error[unresolved-import] Module `tests.opentelemetry.test_logs` has no member `create_mock_grpc_server`
- tests/opentelemetry/test_logs.py:397:47: error[unresolved-import] Module `tests.opentelemetry.test_logs` has no member `extract_log_correlation_attributes`
- tests/opentelemetry/test_logs.py:461:47: error[unresolved-import] Module `tests.opentelemetry.test_logs` has no member `create_mock_grpc_server`
- tests/opentelemetry/test_logs.py:462:47: error[unresolved-import] Module `tests.opentelemetry.test_logs` has no member `extract_log_correlation_attributes`
- tests/opentelemetry/test_logs.py:523:47: error[unresolved-import] Module `tests.opentelemetry.test_logs` has no member `create_mock_grpc_server`
- tests/profiling/collector/test_memalloc.py:79:57: error[unresolved-import] Module `tests.profiling.collector.test_memalloc` has no member `_allocate_1k`
- tests/profiling/collector/test_memalloc.py:173:57: error[unresolved-import] Module `tests.profiling.collector.test_memalloc` has no member `one`
- tests/profiling/collector/test_stack.py:72:54: error[unresolved-import] Module `tests.profiling.collector.test_stack` has no member `func1`
- tests/profiling/collector/test_stack.py:581:54: error[unresolved-import] Module `tests.profiling.collector.test_stack` has no member `_fib`
- tests/profiling/test_accuracy.py:71:47: error[unresolved-import] Module `tests.profiling.test_accuracy` has no member `assert_almost_equal`
- tests/profiling/test_accuracy.py:72:47: error[unresolved-import] Module `tests.profiling.test_accuracy` has no member `spend_16`
- tests/tracer/test_encoders.py:636:44: error[unresolved-import] Module `tests.tracer.test_encoders` has no member `decode`
- tests/tracer/test_memory_leak.py:31:47: error[unresolved-import] Module `tests.tracer.test_memory_leak` has no member `trace`
- tests/tracer/test_memory_leak.py:57:47: error[unresolved-import] Module `tests.tracer.test_memory_leak` has no member `trace`
- tests/tracer/test_memory_leak.py:79:47: error[unresolved-import] Module `tests.tracer.test_memory_leak` has no member `trace`
- tests/tracer/test_memory_leak.py:105:47: error[unresolved-import] Module `tests.tracer.test_memory_leak` has no member `trace`
- tests/tracer/test_memory_leak.py:142:47: error[unresolved-import] Module `tests.tracer.test_memory_leak` has no member `trace`
- tests/tracer/test_rand.py:69:40: error[unresolved-import] Module `tests.tracer.test_rand` has no member `MPQueue`
- tests/tracer/test_rand.py:101:40: error[unresolved-import] Module `tests.tracer.test_rand` has no member `MPQueue`
- tests/tracer/test_rand.py:211:40: error[unresolved-import] Module `tests.tracer.test_rand` has no member `MPQueue`
- tests/tracer/test_rand.py:212:40: error[unresolved-import] Module `tests.tracer.test_rand` has no member `_get_ids`
- tests/tracer/test_rand.py:289:40: error[unresolved-import] Module `tests.tracer.test_rand` has no member `MPQueue`
- tests/tracer/test_tracer.py:1032:42: error[unresolved-import] Module `tests.tracer.test_tracer` has no member `_test_tracer_runtime_tags_fork_task`
- Found 8557 diagnostics
+ Found 8470 diagnostics

zulip (https://github.com/zulip/zulip)
- zerver/lib/display_recipient.py:222:46: error[unresolved-import] Module `zerver.lib.display_recipient` has no member `get_display_recipient_remote_cache`
- Found 3650 diagnostics
+ Found 3649 diagnostics

sympy (https://github.com/sympy/sympy)
- sympy/functions/elementary/complexes.py:1087:58: error[unresolved-import] Module `sympy.functions.elementary.complexes` has no member `arg`
- sympy/matrices/matrixbase.py:1101:47: error[unresolved-import] Module `sympy.matrices.matrixbase` has no member `MatrixBase`
- sympy/matrices/matrixbase.py:1111:29: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- sympy/matrices/matrixbase.py:1113:26: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- sympy/matrices/matrixbase.py:5603:43: error[unresolved-import] Module `sympy.matrices.matrixbase` has no member `MatrixBase`
- Found 15656 diagnostics
+ Found 15651 diagnostics

core (https://github.com/home-assistant/core)
- homeassistant/util/variance.py:47:12: error[invalid-return-type] Return type does not match returned value: expected `(**_P@ignore_variance) -> _R@ignore_variance`, found `_Wrapped[_P@ignore_variance, int | _R@ignore_variance | float | datetime, _P@ignore_variance, _R@ignore_variance | int | float | datetime]`
- Found 14515 diagnostics
+ Found 14514 diagnostics

scipy (https://github.com/scipy/scipy)
- scipy/ndimage/_interpolation.py:740:50: error[unresolved-import] Module `scipy.ndimage._interpolation` has no member `shift`
- scipy/ndimage/_interpolation.py:853:50: error[unresolved-import] Module `scipy.ndimage._interpolation` has no member `zoom`
- Found 8057 diagnostics
+ Found 8055 diagnostics

No memory usage changes detected ✅

@charliermarsh charliermarsh marked this pull request as ready for review January 30, 2026 01:43
@ntBre ntBre added the ty Multi-file analysis & type inference label Jan 30, 2026
Comment on lines 8778 to +8787
// Avoid looking up attributes on a module if a module imports from itself
// (e.g. `from parent import submodule` inside the `parent` module).
let import_is_self_referential = module_ty
// at the module-global scope, where the import definition itself is one of the
// bindings for the symbol being looked up, which would cause a query cycle.
//
// In nested scopes (e.g. function bodies), the module's global-scope definitions
// are resolved independently, so there is no cycle risk and the lookup is safe.
let skip_self_referential_member_lookup = module_ty
.as_module_literal()
.is_some_and(|module| Some(self.file()) == module.module(self.db()).file(self.db()));
.is_some_and(|module| Some(self.file()) == module.module(self.db()).file(self.db()))
&& self.scope().file_scope_id(self.db()).is_global();
Copy link
Member

Choose a reason for hiding this comment

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

we should see (separately) if we can lift this restriction altogether... this works fine at runtime; it's a shame we emit a false-positive error on it. (But not high-priority, because I don't know why you'd do this)

@charliermarsh charliermarsh merged commit e61912f into main Jan 30, 2026
50 checks passed
@charliermarsh charliermarsh deleted the charlie/same branch January 30, 2026 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inline importing function from same module causes unresolved-import error

3 participants