Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[ty] Track literal iterable emptiness for reachability - #25222

#25222
Merged
charliermarsh merged 7 commits into
mainastral-sh/ruff:mainfrom
charlie/non-empty-literalastral-sh/ruff:charlie/non-empty-literalCopy head branch name to clipboard
Jun 25, 2026
Merged

[ty] Track literal iterable emptiness for reachability#25222
charliermarsh merged 7 commits into
mainastral-sh/ruff:mainfrom
charlie/non-empty-literalastral-sh/ruff:charlie/non-empty-literalCopy head branch name to clipboard

Conversation

@charliermarsh

@charliermarsh charliermarsh commented May 18, 2026

Copy link
Copy Markdown
Member

Summary

This extends the static reachability analysis for synchronous for loops from #25220 to tuple, list, set, dictionary, string, and bytes literals whose emptiness is known syntactically. We record their static truthiness: a non-empty literal proves that the body executes at least once, while an empty literal marks the body unreachable and prevents its definitions from flowing past the loop.

for item in [1]:
    pass

reveal_type(item)  # Literal[1]

value = 1
for _ in []:
    value = "unreachable"

reveal_type(value)  # Literal[1]

Starred elements and dictionary unpacking remain ambiguous when they are the only elements, while an explicit element still proves non-emptiness. Other iterables continue on the existing ambiguous path. Synchronous literals used in async for do not use this shortcut because they do not satisfy async iteration.

@astral-sh-bot astral-sh-bot Bot added the ty Multi-file analysis & type inference label May 18, 2026
@astral-sh-bot

astral-sh-bot Bot commented May 18, 2026

Copy link
Copy Markdown

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 94.47%. The percentage of expected errors that received a diagnostic held steady at 89.19%. The number of fully passing files held steady at 95/134.

@astral-sh-bot

astral-sh-bot Bot commented May 18, 2026

Copy link
Copy Markdown

Memory usage report

Summary

Project Old New Diff Outcome
prefect 448.12MB 448.27MB +0.03% (154.61kB)
trio 70.26MB 70.29MB +0.05% (35.18kB)
flake8 28.94MB 28.95MB +0.02% (5.91kB)
sphinx 166.58MB 166.58MB -0.00% (1.49kB) ⬇️

Significant changes

Click to expand detailed breakdown

prefect

Name Old New Diff Outcome
infer_expression_types_impl 37.77MB 37.83MB +0.15% (56.50kB)
infer_definition_types 49.92MB 49.96MB +0.07% (36.88kB)
infer_scope_types_impl 30.11MB 30.14MB +0.10% (30.23kB)
all_narrowing_constraints_for_expression 5.19MB 5.21MB +0.51% (27.00kB)
semantic_index 113.89MB 113.89MB +0.00% (1.09kB)
analyze_non_terminal_call::interned_arguments 1.80MB 1.80MB +0.05% (936.00B)
infer_unpack_types 631.55kB 632.34kB +0.13% (816.00B)
analyze_non_terminal_call 1.77MB 1.77MB +0.04% (736.00B)
Type<'db>::apply_specialization_inner_::interned_arguments 2.95MB 2.95MB +0.01% (160.00B)
UnionType 1.07MB 1.07MB +0.01% (112.00B)
Type<'db>::apply_specialization_inner_ 2.03MB 2.03MB +0.00% (96.00B)
loop_header_reachability 251.37kB 251.45kB +0.03% (80.00B)
function_known_decorators 3.04MB 3.04MB +0.00% (32.00B)
infer_statement_types_impl 812.33kB 812.34kB +0.00% (16.00B)

trio

Name Old New Diff Outcome
infer_expression_types_impl 4.37MB 4.39MB +0.38% (16.81kB)
analyze_non_terminal_call 376.73kB 382.63kB +1.57% (5.90kB)
semantic_index 17.69MB 17.69MB +0.03% (4.84kB)
all_narrowing_constraints_for_expression 457.70kB 461.26kB +0.78% (3.55kB)
infer_definition_types 3.96MB 3.97MB +0.04% (1.73kB)
CallableType 665.85kB 666.44kB +0.09% (608.00B)
analyze_non_terminal_call::interned_arguments 302.20kB 302.77kB +0.19% (576.00B)
infer_scope_types_impl 2.40MB 2.40MB +0.02% (528.00B)
infer_deferred_types 1.20MB 1.20MB +0.04% (480.00B)
FunctionType<'db>::signature_ 626.03kB 625.84kB -0.03% (192.00B)
infer_statement_types_impl 34.34kB 34.47kB +0.36% (128.00B)
member_lookup_with_policy_inner::interned_arguments 765.70kB 765.82kB +0.02% (120.00B)
loop_header_reachability 71.16kB 71.24kB +0.11% (80.00B)
member_lookup_with_policy_inner 1.03MB 1.03MB +0.01% (72.00B)

flake8

Name Old New Diff Outcome
infer_expression_types_impl 642.10kB 645.48kB +0.53% (3.38kB)
all_narrowing_constraints_for_expression 71.97kB 73.80kB +2.55% (1.84kB)
infer_definition_types 1000.73kB 1001.23kB +0.05% (504.00B)
loop_header_reachability 9.14kB 9.28kB +1.54% (144.00B)
analyze_non_terminal_call 28.90kB 28.97kB +0.24% (72.00B)
semantic_index 7.85MB 7.85MB -0.00% (32.00B)
infer_scope_types_impl 512.04kB 512.05kB +0.00% (16.00B)

sphinx

Name Old New Diff Outcome
semantic_index 37.29MB 37.29MB -0.01% (4.07kB) ⬇️
infer_expression_types_impl 14.77MB 14.77MB +0.01% (1.29kB) ⬇️
analyze_non_terminal_call::interned_arguments 611.23kB 611.58kB +0.06% (360.00B) ⬇️
infer_definition_types 13.67MB 13.67MB +0.00% (320.00B) ⬇️
analyze_non_terminal_call 662.77kB 663.08kB +0.05% (312.00B) ⬇️
infer_scope_types_impl 8.10MB 8.10MB +0.00% (232.00B) ⬇️
all_narrowing_constraints_for_expression 1.93MB 1.93MB +0.00% (96.00B) ⬇️

@astral-sh-bot

astral-sh-bot Bot commented May 18, 2026

Copy link
Copy Markdown

ecosystem-analyzer results

Lint rule Added Removed Changed
possibly-unresolved-reference 0 124 0
unresolved-attribute 0 3 0
not-iterable 0 2 0
invalid-assignment 0 1 0
possibly-missing-import 0 1 0
Total 0 131 0

Flaky changes detected. This PR summary excludes flaky changes; see the HTML report for details.

Raw diff (131 changes)
black (https://github.com/psf/black)
- src/black/linegen.py:943:12 warning[possibly-unresolved-reference] Name `matching_bracket` used when possibly not defined
- src/black/linegen.py:943:36 warning[possibly-unresolved-reference] Name `tail_leaves` used when possibly not defined
- src/black/linegen.py:947:9 warning[possibly-unresolved-reference] Name `head_leaves` used when possibly not defined
- src/black/linegen.py:947:28 warning[possibly-unresolved-reference] Name `matching_bracket` used when possibly not defined
- src/black/linegen.py:950:9 warning[possibly-unresolved-reference] Name `body_leaves` used when possibly not defined
- src/black/linegen.py:950:28 warning[possibly-unresolved-reference] Name `matching_bracket` used when possibly not defined
- src/black/linegen.py:953:9 warning[possibly-unresolved-reference] Name `tail_leaves` used when possibly not defined
- src/black/linegen.py:953:28 warning[possibly-unresolved-reference] Name `matching_bracket` used when possibly not defined
- src/black/files.py:104:12 warning[possibly-unresolved-reference] Name `directory` used when possibly not defined

cloud-init (https://github.com/canonical/cloud-init)
- tests/unittests/sources/test_init.py:737:26 warning[possibly-unresolved-reference] Name `filename` used when possibly not defined

colour (https://github.com/colour-science/colour)
- colour/io/tm2714.py:1698:44 warning[possibly-unresolved-reference] Name `mapping` used when possibly not defined
- colour/io/tm2714.py:1700:38 warning[possibly-unresolved-reference] Name `mapping` used when possibly not defined
- colour/io/tm2714.py:1702:21 warning[possibly-unresolved-reference] Name `mapping` used when possibly not defined
- colour/io/tm2714.py:1702:45 warning[possibly-unresolved-reference] Name `mapping` used when possibly not defined

core (https://github.com/home-assistant/core)
- homeassistant/components/opower/coordinator.py:299:24 warning[possibly-unresolved-reference] Name `stats` used when possibly not defined
- homeassistant/components/opower/coordinator.py:306:42 warning[possibly-unresolved-reference] Name `stats` used when possibly not defined
- homeassistant/components/opower/coordinator.py:308:21 warning[possibly-unresolved-reference] Name `stats` used when possibly not defined
- homeassistant/components/opower/coordinator.py:310:49 warning[possibly-unresolved-reference] Name `stats` used when possibly not defined
- homeassistant/components/opower/coordinator.py:311:44 warning[possibly-unresolved-reference] Name `stats` used when possibly not defined
- homeassistant/components/opower/coordinator.py:312:35 warning[possibly-unresolved-reference] Name `stats` used when possibly not defined

cryptography (https://github.com/pyca/cryptography)
- tests/hazmat/primitives/test_ssh.py:225:30 warning[possibly-unresolved-reference] Name `private_key` used when possibly not defined
- tests/hazmat/primitives/test_ssh.py:242:26 warning[possibly-unresolved-reference] Name `private_key` used when possibly not defined

ibis (https://github.com/ibis-project/ibis)
- ibis/backends/sql/datatypes.py:80:5 warning[possibly-unresolved-reference] Name `_attr` used when possibly not defined
- ibis/backends/sql/datatypes.py:80:12 warning[possibly-unresolved-reference] Name `_ibis_type` used when possibly not defined
- ibis/backends/sql/datatypes.py:80:24 warning[possibly-unresolved-reference] Name `_sg_type` used when possibly not defined

jax (https://github.com/google/jax)
- jax/_src/internal_test_util/test_harnesses.py:1840:11 warning[possibly-unresolved-reference] Name `shape` used when possibly not defined
- jax/_src/internal_test_util/test_harnesses.py:1841:11 warning[possibly-unresolved-reference] Name `shape` used when possibly not defined
- jax/_src/internal_test_util/test_harnesses.py:1841:31 warning[possibly-unresolved-reference] Name `shape` used when possibly not defined
- jax/_src/internal_test_util/test_harnesses.py:1845:19 warning[possibly-unresolved-reference] Name `shape` used when possibly not defined

mypy (https://github.com/python/mypy)
- mypyc/irbuild/format_str_tokenizer.py:28:55 warning[possibly-missing-import] Member `int_to_str_op` of module `mypyc.primitives.int_ops` may be missing

pandas (https://github.com/pandas-dev/pandas)
- pandas/tests/frame/indexing/test_take.py:48:13 warning[possibly-unresolved-reference] Name `df` used when possibly not defined
- pandas/tests/frame/indexing/test_take.py:50:13 warning[possibly-unresolved-reference] Name `df` used when possibly not defined
- pandas/tests/frame/indexing/test_take.py:52:13 warning[possibly-unresolved-reference] Name `df` used when possibly not defined
- pandas/tests/frame/indexing/test_take.py:54:13 warning[possibly-unresolved-reference] Name `df` used when possibly not defined
- pandas/tests/indexes/timedeltas/test_scalar_compat.py:134:35 warning[possibly-unresolved-reference] Name `r1` used when possibly not defined
- pandas/tests/indexes/timedeltas/test_scalar_compat.py:134:39 warning[possibly-unresolved-reference] Name `s1` used when possibly not defined
- pandas/tests/indexes/timedeltas/test_scalar_compat.py:135:35 warning[possibly-unresolved-reference] Name `r2` used when possibly not defined
- pandas/tests/indexes/timedeltas/test_scalar_compat.py:135:39 warning[possibly-unresolved-reference] Name `s2` used when possibly not defined

pandera (https://github.com/pandera-dev/pandera)
- tests/io/test_pandas_io.py:1545:35 warning[possibly-unresolved-reference] Name `local_dict` used when possibly not defined
- tests/io/test_pandas_io.py:1546:18 warning[possibly-unresolved-reference] Name `local_dict` used when possibly not defined

poetry (https://github.com/python-poetry/poetry)
- src/poetry/repositories/link_sources/html.py:63:77 warning[possibly-unresolved-reference] Name `metadata` used when possibly not defined

psycopg (https://github.com/psycopg/psycopg)
- tools/update_error_prefixes.py:75:22 warning[possibly-unresolved-reference] Name `default_pgroot` used when possibly not defined

pycryptodome (https://github.com/Legrandin/pycryptodome)
- lib/Crypto/SelfTest/Cipher/test_CFB.py:275:44 warning[possibly-unresolved-reference] Name `file_name` used when possibly not defined
- lib/Crypto/SelfTest/Cipher/test_CFB.py:275:55 warning[possibly-unresolved-reference] Name `new_func` used when possibly not defined

pydantic (https://github.com/pydantic/pydantic)
- pydantic/v1/networks.py:350:12 warning[possibly-unresolved-reference] Name `host` used when possibly not defined
- pydantic/v1/networks.py:355:48 warning[possibly-unresolved-reference] Name `host` used when possibly not defined
- pydantic/v1/networks.py:357:50 warning[possibly-unresolved-reference] Name `host` used when possibly not defined
- pydantic/v1/networks.py:364:50 warning[possibly-unresolved-reference] Name `host` used when possibly not defined
- pydantic/v1/networks.py:377:24 warning[possibly-unresolved-reference] Name `host` used when possibly not defined

pywin32 (https://github.com/mhammond/pywin32)
- pythonwin/pywin/idle/PyParse.py:124:5 warning[possibly-unresolved-reference] Name `ch` used when possibly not defined

rotki (https://github.com/rotki/rotki)
- rotkehlchen/tests/api/test_bitcoin_transactions.py:102:12 warning[possibly-unresolved-reference] Name `events` used when possibly not defined
- rotkehlchen/tests/api/test_bitcoin_transactions.py:131:12 warning[possibly-unresolved-reference] Name `events` used when possibly not defined
- rotkehlchen/tests/api/test_bitcoin_transactions.py:149:18 warning[possibly-unresolved-reference] Name `json` used when possibly not defined
- rotkehlchen/tests/api/test_bitcoin_transactions.py:197:12 warning[possibly-unresolved-reference] Name `events` used when possibly not defined
- rotkehlchen/tests/api/test_bitcoin_transactions.py:256:12 warning[possibly-unresolved-reference] Name `events` used when possibly not defined
- rotkehlchen/tests/api/test_solana_transactions.py:288:15 warning[possibly-unresolved-reference] Name `user_address` used when possibly not defined
- rotkehlchen/tests/api/test_solana_transactions.py:298:24 warning[possibly-unresolved-reference] Name `user_address` used when possibly not defined
- rotkehlchen/tests/integration/test_zksynclite.py:84:25 warning[possibly-unresolved-reference] Name `idx` used when possibly not defined
- rotkehlchen/tests/integration/test_zksynclite.py:101:25 warning[possibly-unresolved-reference] Name `idx` used when possibly not defined
- rotkehlchen/tests/unit/test_protocol_balances.py:541:20 warning[possibly-unresolved-reference] Name `tx_decoder` used when possibly not defined
- rotkehlchen/tests/unit/test_protocol_balances.py:990:20 warning[possibly-unresolved-reference] Name `tx_decoder` used when possibly not defined

scikit-learn (https://github.com/scikit-learn/scikit-learn)
- sklearn/covariance/tests/test_graphical_lasso.py:66:40 warning[possibly-unresolved-reference] Name `covs` used when possibly not defined
- sklearn/datasets/_twenty_newsgroups.py:341:9 warning[possibly-unresolved-reference] Name `data` used when possibly not defined
- sklearn/datasets/_twenty_newsgroups.py:342:9 warning[possibly-unresolved-reference] Name `data` used when possibly not defined
- sklearn/datasets/_twenty_newsgroups.py:343:9 warning[possibly-unresolved-reference] Name `data` used when possibly not defined
- sklearn/decomposition/tests/test_factor_analysis.py:75:9 warning[possibly-unresolved-reference] Name `fa` used when possibly not defined
- sklearn/decomposition/tests/test_factor_analysis.py:76:9 warning[possibly-unresolved-reference] Name `fa` used when possibly not defined
- sklearn/decomposition/tests/test_factor_analysis.py:77:15 warning[possibly-unresolved-reference] Name `fa` used when possibly not defined
- sklearn/decomposition/tests/test_factor_analysis.py:78:21 warning[possibly-unresolved-reference] Name `fa` used when possibly not defined
- sklearn/ensemble/tests/test_bagging.py:632:47 error[not-iterable] Object of type `None | BaggingClassifier` may not be iterable
- sklearn/ensemble/tests/test_forest.py:1326:47 error[not-iterable] Object of type `None | Any` may not be iterable
- sklearn/ensemble/tests/test_forest.py:1331:9 error[unresolved-attribute] Attribute `apply` is not defined on `None` in union `None | Any`
- sklearn/feature_extraction/tests/test_text.py:564:31 warning[possibly-unresolved-reference] Name `counts_test` used when possibly not defined
- sklearn/svm/tests/test_svm.py:80:24 warning[possibly-unresolved-reference] Name `clf` used when possibly not defined
- sklearn/svm/tests/test_svm.py:80:46 warning[possibly-unresolved-reference] Name `clf` used when possibly not defined
- sklearn/tests/test_discriminant_analysis.py:400:45 warning[possibly-unresolved-reference] Name `solver` used when possibly not defined

scipy (https://github.com/scipy/scipy)
- scipy/optimize/tests/test__numdiff.py:42:30 warning[possibly-unresolved-reference] Name `A` used when possibly not defined
- scipy/optimize/tests/test__numdiff.py:43:30 warning[possibly-unresolved-reference] Name `A` used when possibly not defined
- scipy/interpolate/tests/test_fitpack2.py:170:13 warning[possibly-unresolved-reference] Name `spl` used when possibly not defined
- scipy/interpolate/tests/test_interpolate.py:1229:62 warning[possibly-unresolved-reference] Name `x` used when possibly not defined
- scipy/io/arff/_arffread.py:449:12 warning[possibly-unresolved-reference] Name `restr` used when possibly not defined
- scipy/io/arff/_arffread.py:452:22 warning[possibly-unresolved-reference] Name `regexp` used when possibly not defined
- scipy/io/arff/_arffread.py:455:20 warning[possibly-unresolved-reference] Name `matches` used when possibly not defined
- scipy/io/arff/_arffread.py:456:13 warning[possibly-unresolved-reference] Name `matches` used when possibly not defined
- scipy/sparse/tests/test_base.py:1531:25 warning[possibly-unresolved-reference] Name `S_casted` used when possibly not defined
- scipy/sparse/tests/test_base.py:1531:59 warning[possibly-unresolved-reference] Name `S_casted` used when possibly not defined
- scipy/sparse/tests/test_base.py:1532:28 warning[possibly-unresolved-reference] Name `S_casted` used when possibly not defined
- scipy/sparse/tests/test_base.py:1533:41 warning[possibly-unresolved-reference] Name `S_casted` used when possibly not defined
- scipy/sparse/tests/test_base.py:1546:20 warning[possibly-unresolved-reference] Name `S_casted` used when possibly not defined
- scipy/sparse/tests/test_base.py:1549:22 warning[possibly-unresolved-reference] Name `S_casted` used when possibly not defined
- scipy/sparse/tests/test_base.py:1552:22 warning[possibly-unresolved-reference] Name `S_casted` used when possibly not defined
- scipy/spatial/transform/tests/test_rigid_transform.py:853:24 warning[possibly-unresolved-reference] Name `n` used when possibly not defined

spack (https://github.com/spack/spack)
- lib/spack/spack/package_prefs.py:149:27 warning[possibly-unresolved-reference] Name `variants` used when possibly not defined
- lib/spack/spack/package_prefs.py:150:33 warning[possibly-unresolved-reference] Name `variants` used when possibly not defined
- lib/spack/spack/package_prefs.py:154:46 warning[possibly-unresolved-reference] Name `variants` used when possibly not defined
- lib/spack/spack/package_prefs.py:225:8 warning[possibly-unresolved-reference] Name `readable` used when possibly not defined
- lib/spack/spack/package_prefs.py:227:8 warning[possibly-unresolved-reference] Name `readable` used when possibly not defined
- lib/spack/spack/package_prefs.py:230:8 warning[possibly-unresolved-reference] Name `writable` used when possibly not defined
- lib/spack/spack/package_prefs.py:231:12 warning[possibly-unresolved-reference] Name `readable` used when possibly not defined
- lib/spack/spack/package_prefs.py:238:8 warning[possibly-unresolved-reference] Name `writable` used when possibly not defined
- lib/spack/spack/package_prefs.py:239:12 warning[possibly-unresolved-reference] Name `readable` used when possibly not defined
- lib/spack/spack/package_prefs.py:261:12 warning[possibly-unresolved-reference] Name `group` used when possibly not defined
- lib/spack/spack/vendor/markupsafe/__init__.py:191:9 warning[possibly-unresolved-reference] Name `method` used when possibly not defined
- lib/spack/spack/vendor/ruamel/yaml/emitter.py:1512:20 warning[possibly-unresolved-reference] Name `pos` used when possibly not defined

spark (https://github.com/apache/spark)
- python/pyspark/ml/tests/connect/test_legacy_mode_evaluation.py:133:13 warning[possibly-unresolved-reference] Name `auprc_evaluator` used when possibly not defined
- python/pyspark/mllib/tests/test_feature.py:153:26 warning[possibly-unresolved-reference] Name `mat` used when possibly not defined
- python/pyspark/pandas/tests/frame/test_reindexing.py:550:42 warning[possibly-unresolved-reference] Name `keep` used when possibly not defined
- python/pyspark/pandas/tests/frame/test_reindexing.py:554:48 warning[possibly-unresolved-reference] Name `keep` used when possibly not defined
- python/pyspark/pandas/tests/frame/test_reindexing.py:551:43 warning[possibly-unresolved-reference] Name `keep` used when possibly not defined
- python/pyspark/pandas/tests/frame/test_reindexing.py:555:49 warning[possibly-unresolved-reference] Name `keep` used when possibly not defined
- python/pyspark/pandas/tests/groupby/test_aggregate.py:109:40 warning[possibly-unresolved-reference] Name `as_index` used when possibly not defined
- python/pyspark/sql/tests/test_functions.py:1586:59 warning[possibly-unresolved-reference] Name `aq` used when possibly not defined

static-frame (https://github.com/static-frame/static-frame)
- static_frame/test/property/test_util.py:259:25 warning[possibly-unresolved-reference] Name `post` used when possibly not defined

sympy (https://github.com/sympy/sympy)
- sympy/combinatorics/tests/test_perm_groups.py:195:5 warning[possibly-unresolved-reference] Name `G` used when possibly not defined
- sympy/combinatorics/tests/test_perm_groups.py:196:32 warning[possibly-unresolved-reference] Name `G` used when possibly not defined
- sympy/combinatorics/tests/test_perm_groups.py:196:35 warning[possibly-unresolved-reference] Name `G` used when possibly not defined
- sympy/concrete/tests/test_sums_products.py:792:12 warning[possibly-unresolved-reference] Name `func` used when possibly not defined
- sympy/concrete/tests/test_sums_products.py:793:12 warning[possibly-unresolved-reference] Name `func` used when possibly not defined
- sympy/concrete/tests/test_sums_products.py:794:12 warning[possibly-unresolved-reference] Name `func` used when possibly not defined
- sympy/concrete/tests/test_sums_products.py:795:12 warning[possibly-unresolved-reference] Name `func` used when possibly not defined
- sympy/series/residues.py:69:17 warning[possibly-unresolved-reference] Name `s` used when possibly not defined
- sympy/printing/pretty/pretty.py:1498:9 error[invalid-assignment] Object of type `Unknown` is not assignable to attribute `baseline` on type `None | Unknown | prettyForm`
- sympy/printing/pretty/pretty.py:1498:22 error[unresolved-attribute] Attribute `height` is not defined on `None` in union `None | Unknown | prettyForm`
- sympy/printing/pretty/pretty.py:1502:25 error[unresolved-attribute] Attribute `right` is not defined on `None` in union `None | Unknown | prettyForm`
- sympy/utilities/tests/test_iterables.py:416:39 warning[possibly-unresolved-reference] Name `nul` used when possibly not defined
- sympy/utilities/tests/test_iterables.py:418:39 warning[possibly-unresolved-reference] Name `nul` used when possibly not defined
- sympy/utilities/tests/test_iterables.py:419:39 warning[possibly-unresolved-reference] Name `nul` used when possibly not defined

tornado (https://github.com/tornadoweb/tornado)
- tornado/test/httpclient_test.py:682:34 warning[possibly-unresolved-reference] Name `resp` used when possibly not defined

vision (https://github.com/pytorch/vision)
- test/test_transforms.py:1949:26 warning[possibly-unresolved-reference] Name `mean` used when possibly not defined
- test/test_transforms.py:1949:32 warning[possibly-unresolved-reference] Name `std` used when possibly not defined
- torchvision/models/feature_extraction.py:601:87 warning[possibly-unresolved-reference] Name `name` used when possibly not defined

Full report with detailed diff (timing results)

@charliermarsh
charliermarsh force-pushed the charlie/range branch 10 times, most recently from 9d3860e to 667a3fb Compare May 19, 2026 12:20
@charliermarsh
charliermarsh force-pushed the charlie/range branch 3 times, most recently from 5b9c09e to 53006b1 Compare May 30, 2026 13:49
@charliermarsh
charliermarsh force-pushed the charlie/range branch 2 times, most recently from 2ae6e9f to 1b3dc8e Compare June 12, 2026 17:10
@charliermarsh
charliermarsh force-pushed the charlie/range branch 2 times, most recently from add7d4b to 96af416 Compare June 25, 2026 01:39
@charliermarsh
charliermarsh force-pushed the charlie/non-empty-literal branch from 1c906d8 to 61346dc Compare June 25, 2026 01:52
@charliermarsh charliermarsh changed the title [ty] View ecosystem report for non-empty literals [ty] Treat non-empty literal iterables as non-empty for reachability Jun 25, 2026
Base automatically changed from charlie/range to main June 25, 2026 01:56
@charliermarsh
charliermarsh force-pushed the charlie/non-empty-literal branch from 61346dc to 7d2f48c Compare June 25, 2026 01:58
@charliermarsh charliermarsh changed the title [ty] Treat non-empty literal iterables as non-empty for reachability [ty] Track literal iterable emptiness for reachability Jun 25, 2026
@charliermarsh
charliermarsh requested a review from carljm June 25, 2026 02:09
@charliermarsh
charliermarsh marked this pull request as ready for review June 25, 2026 02:09
@charliermarsh
charliermarsh requested a review from a team as a code owner June 25, 2026 02:09
@charliermarsh
charliermarsh requested a review from a team as a code owner June 25, 2026 02:09
Comment thread crates/ty_python_semantic/resources/mdtest/loops/for.md
Comment thread crates/ty_python_core/src/builder.rs Outdated
{
let after_iter = self.flow_snapshot();
let constraint = self
.record_reachability_constraint(PredicateOrLiteral::Literal(is_non_empty));

@carljm carljm Jun 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this PR can be significantly simpler. There's no need to create a node in the reachability TDD for a reachability decision that we can make with full confidence immediately in semantic indexing. For these cases we can instead just merge or not-merge control flow snapshots directly here. I think the pattern here should be: "what is the known emptiness of the iterator? if empty, mark loop body unreachable and restore post-iterator snapshot before visiting else. if non-empty, visit body normally and do not merge zero-iteration path back in. if unknown, then we check for possibly adding a range constraint node, and proceed as main currently does."

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good call, thank you!

@charliermarsh
charliermarsh force-pushed the charlie/non-empty-literal branch from cbd8135 to 5798505 Compare June 25, 2026 11:11
@charliermarsh
charliermarsh requested a review from carljm June 25, 2026 11:12
@charliermarsh
charliermarsh force-pushed the charlie/non-empty-literal branch from 5798505 to 4c6cc9b Compare June 25, 2026 11:26

@carljm carljm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice, thanks!


```py
def _(items: list[int], mapping: dict[str, int]):
for item in [*items]:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It looks like we are smart about the fact that [*items, 1] is known non-empty (and similar for e.g. {*mapping, "c": 2}), but this is currently not tested.

@charliermarsh
charliermarsh force-pushed the charlie/non-empty-literal branch from 4c6cc9b to b9864b6 Compare June 25, 2026 17:32
@charliermarsh
charliermarsh enabled auto-merge (squash) June 25, 2026 17:32
@charliermarsh
charliermarsh merged commit 6a2e694 into main Jun 25, 2026
62 checks passed
@charliermarsh
charliermarsh deleted the charlie/non-empty-literal branch June 25, 2026 17:37
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.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.