Skip to content

Feature: Del erases types #10005

Open
Open
@Phlosioneer

Description

@Phlosioneer

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.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions