Description
Feature
Using del
on a variable (on all possible control paths, of course) removes all type info from the variable, allowing it to assume a new type when reused.
Pitch
After running into #1174, my first reaction was to use del
to erase the variable's type. Nothing survives past a del
so I think it's probably typesafe to erase the type info for that variable.
The main issue with variable reuse within a function body is that the variable is function-scoped, so its value (and therefore its type) last until the end of the function. When re-assigning something to that variable it's generally ambiguous whether it's a type error or whether the user is just re-using an existing name. With the del
statement, that ambiguity disappears; the user is explicitly treating the value as undefined, and accessing it is a runtime error.
I wrote this code in a larger project:
if VERBOSITY >= 2:
logDebug("DEBUG: Patch mapping:")
for patch, jars in patchMapping.items():
logDebug("\tPatch:",patch.name)
# `jar` here has type `pathlib.Path`
for jar in jars:
logDebug("\t\t" + jar.name)
# This is the fix I tried to use to satisfy mypy's type error
del jar
openedJars: Dict[Path, PartiallyPatchedZipFile] = {}
for patch, jarPaths in patchMapping.items():
for jarPath in jarPaths:
if jarPath in openedJars:
jar = openedJars[jarPath]
else:
jar = PartiallyPatchedZipFile(jarPath)
openedJars[jarPath] = jar
logInfo("Applying patch", patch.name, "to", jarPath.name)
filesMatched = applyPatch(jar, patch)
if filesMatched == 0:
logInfo("Warnging: Patch", patch.name, "doesn't apply to any class files in", jar.path.name)
# `jar` here has type `PartiallyPatchedZipFile`
for jar in changedJars:
stagingJarPath = stagingDir.joinpath(jar.path.name)
jar.writeChangesToFile(stagingJarPath)
jar.closeZip()
In this example, mypy is technically right; if the debug code is executed, jar
will be a pathlib.Path
. With the del
statement, the for
loop's variable is cleaned up for later reuse, and jar
will not contain a pathlib.Path
when the second for
loop begins.
Limitations
- Statements like
del myDict[key]
don't apply to the above logic. - I don't know how easy/hard the control flow part is with mypy's codebase. It's not a critical part of the feature, though.
- I don't know if it applies to global values; I only reasoned about function scope.