Skip to content

Let --allow-redefinition-new widen global in function with None init#21285

Open
JukkaL wants to merge 10 commits intomasterfrom
redef-widen
Open

Let --allow-redefinition-new widen global in function with None init#21285
JukkaL wants to merge 10 commits intomasterfrom
redef-widen

Conversation

@JukkaL
Copy link
Copy Markdown
Collaborator

@JukkaL JukkaL commented Apr 21, 2026

Now this infers an optional type, for backward compat with --allow-redefinition-old:

# mypy: allow-redefinition-new
x = None

def foo() -> None:
    global x
    x = 1  # Ok
    
# Type of "x" is "int | None" here

There are a few non-trivial things. The implementation propagates the widened type to the global scope, since otherwise x would have type None at top level after the function. We also only allow widening if the original type is None, to make reasoning about this easier. Otherwise the type could be inferred from any number of functions. Also this is sufficient to maintain backward compatibility.

I used coding agent assist with small incremental changes and careful manual reviews.

See #21276 for additional context.

@github-actions
Copy link
Copy Markdown
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

@JukkaL JukkaL requested a review from ilevkivskyi April 21, 2026 17:20
@JukkaL JukkaL changed the title Let --allow-redefinition-new to widen global in function with None init Let --allow-redefinition-new widen global in function with None init Apr 21, 2026
Copy link
Copy Markdown
Member

@ilevkivskyi ilevkivskyi left a comment

Choose a reason for hiding this comment

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

Yeah, this is a bit ugly, but not too bad to maintain backwards compatibility for an important edge case.

I have just one suggestion.

Comment thread mypy/checker.py
"""Can a variable type be widened via assignment in the current scope?

Globals can only be widened from within a function if the original type
is None (backward compat with partial type handling of `x = None`).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe give some example relevant test cases here? Like e.g. testNewRedefineGlobalVariableNoneInit tests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants