Suppress unknown-name for global declarations the function itself defines - #4797
Open
nitishagar wants to merge 1 commit into
Open
Suppress unknown-name for global declarations the function itself defines#4797nitishagar wants to merge 1 commit into
nitishagar wants to merge 1 commit into
Conversation
…f defines A `global x` declaration inside a function errored with unknown-name whenever the module had no module-level `x`, even when the declaring function assigns `x` itself (`global x; x = value`) — a legal way to create the module-level name at runtime, and the exact pattern from issue facebook#4785. The name-resolution failure is expected there: a function's global-assign intentionally never publishes a module-scope static, so the mutable-capture lookup that only consults module statics cannot find what the function is about to define. The definitions phase already knows better — it merges every definition site in the scope — so this change records whether any site gives the name a value (assignment or import, not `del` or another capture declaration) on the scope's `Definition`, threads it through the `MutableCapture` static, and suppresses only the not-found error for `global` declarations in function/method scopes whose own body defines the name. Undefined reads (`global a; print(a)` with no definition anywhere), assignments before the declaration, and module/class-scope declarations keep erroring exactly as before. Fixes facebook#4785
Contributor
|
This pull request has been imported. If you are a Meta employee, you can view this in D118601767. (Because this pull request was imported automatically, there will not be any future comments.) |
|
Diff from mypy_primer, showing the effect of this PR on open source code: ============================================================
SUMMARY
============================================================
Total: +0 new errors, -41 fixed errors
By preset: +0/-41 (default), +0/-41 (strict)
Projects with changes (9):
mitmproxy: +0 -1
spark: +0 -2
pycryptodome: +0 -12
setuptools: +0 -2
asynq: +0 -1
stone: +0 -3
dd-trace-py: +0 -2
pandas: +0 -17
pyodide: +0 -1
============================================================
FULL DIFF DETAILS
------------------------------------------------------------
mitmproxy (https://github.com/mitmproxy/mitmproxy)
- ERROR test/helper_tools/memoryleak.py:32:18-21: Could not find name `ssl` [unknown-name]
spark (https://github.com/apache/spark)
- ERROR python/pyspark/serializers.py:369:16-31: Could not find name `_old_namedtuple` [unknown-name]
- ERROR python/pyspark/serializers.py:370:16-42: Could not find name `_old_namedtuple_kwdefaults` [unknown-name]
pycryptodome (https://github.com/Legrandin/pycryptodome)
- ERROR lib/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py:329:20-25: Could not find name `asked` [unknown-name]
- ERROR lib/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py:332:24-29: Could not find name `asked` [unknown-name]
- ERROR lib/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py:357:20-28: Could not find name `mgfcalls` [unknown-name]
- ERROR lib/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py:361:24-32: Could not find name `mgfcalls` [unknown-name]
- ERROR lib/Crypto/SelfTest/PublicKey/test_DSA.py:71:16-19: Could not find name `DSA` [unknown-name]
- ERROR lib/Crypto/SelfTest/PublicKey/test_DSA.py:71:21-27: Could not find name `Random` [unknown-name]
- ERROR lib/Crypto/SelfTest/PublicKey/test_DSA.py:71:29-42: Could not find name `bytes_to_long` [unknown-name]
- ERROR lib/Crypto/SelfTest/PublicKey/test_DSA.py:71:44-48: Could not find name `size` [unknown-name]
- ERROR lib/Crypto/SelfTest/PublicKey/test_RSA.py:90:16-19: Could not find name `RSA` [unknown-name]
- ERROR lib/Crypto/SelfTest/PublicKey/test_RSA.py:90:21-27: Could not find name `Random` [unknown-name]
- ERROR lib/Crypto/SelfTest/PublicKey/test_RSA.py:90:29-42: Could not find name `bytes_to_long` [unknown-name]
- ERROR lib/Crypto/SelfTest/Util/test_Counter.py:33:16-23: Could not find name `Counter` [unknown-name]
setuptools (https://github.com/pypa/setuptools)
- ERROR setuptools/tests/test_setuptools.py:54:20-21: Could not find name `x` [unknown-name]
- ERROR setuptools/tests/test_setuptools.py:54:23-24: Could not find name `y` [unknown-name]
asynq (https://github.com/quora/asynq)
- ERROR asynq/tests/test_contexts.py:104:12-39: Could not find name `expected_change_amount_base` [unknown-name]
stone (https://github.com/dropbox/stone)
- ERROR stone/_vendor/ply/lex.py:868:12-17: Could not find name `lexer` [unknown-name]
- ERROR stone/_vendor/ply/lex.py:874:12-17: Could not find name `token` [unknown-name]
- ERROR stone/_vendor/ply/yacc.py:3168:12-17: Could not find name `parse` [unknown-name]
dd-trace-py (https://github.com/DataDog/dd-trace-py)
- ERROR ddtrace/internal/process_tags/__init__.py:140:12-24: Could not find name `process_tags` [unknown-name]
- ERROR ddtrace/internal/process_tags/__init__.py:141:12-29: Could not find name `process_tags_list` [unknown-name]
pandas (https://github.com/pandas-dev/pandas)
- ERROR pandas/io/clipboard/__init__.py:140:12-24: Could not find name `QApplication` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:348:12-19: Could not find name `HGLOBAL` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:348:21-27: Could not find name `LPVOID` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:348:29-34: Could not find name `DWORD` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:348:36-42: Could not find name `LPCSTR` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:348:44-47: Could not find name `INT` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:349:12-16: Could not find name `HWND` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:349:18-27: Could not find name `HINSTANCE` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:349:29-34: Could not find name `HMENU` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:349:36-40: Could not find name `BOOL` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:349:42-46: Could not find name `UINT` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:349:48-54: Could not find name `HANDLE` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:540:12-22: Could not find name `Foundation` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:540:24-30: Could not find name `AppKit` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:540:32-36: Could not find name `qtpy` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:540:38-43: Could not find name `PyQt4` [unknown-name]
- ERROR pandas/io/clipboard/__init__.py:540:45-50: Could not find name `PyQt5` [unknown-name]
pyodide (https://github.com/pyodide/pyodide)
- ERROR src/tests/test_jsproxy.py:2956:12-13: Could not find name `A` [unknown-name] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4785
Problem
A
globaldeclaration inside a function errored withunknown-name("Could not find namex") whenever the module had no module-level definition ofx— even when the declaring function assignsxitself:global x; x = valueis a legal way to create the module-level name at runtime, so the declaration should not error.Why it happened
The mutable-capture lookup for
globalnames consults module-scope statics (plus a builtin fallback) only, and a function's global-assign intentionally never publishes a module-scope static — so the lookup cannot find the very name the function is about to define.Change
The definitions phase already merges every definition site in a scope, so it knows whether the scope gives the name a value beyond the capture declaration:
Definitionrecords whether any definition site is a value definition (assignment or import;deland other capture declarations do not count).MutableCapturestatic.declare_mutable_capturesuppresses only the not-found error forglobaldeclarations in function/method scopes whose own body defines the name.Everything else is unchanged: undefined reads (
global a; print(a)with no definition anywhere), assignments textually before the declaration (x = 1; global x), module top-level and class-body declarations, and allnonlocalbehavior keep erroring exactly as before.Test plan
testcase!s inpyrefly/lib/test/scope.rs: the issue repro, undefined-read still errors, nested-if assignments (both orders),deldoesn't define, assignment-before-declaration keeps its error, module top-level and class-body keep erroringcargo test -p pyrefly --libgreen (the two pre-existingmissing-sourceLSP interaction failures also fail on unmodifiedmain)