Skip to content

lint: the general outer-mutation-without-local fence has no open tracker — lint.c:1844 points at #396 and #404, both closed #870

Description

@InauguralPhysicist

Finding

src/lint.c:1836-1845 explains why W015 is scoped to function-name clobbering only, and hands the general case off:

The general local-discipline lint belongs to the scope-aware name-resolution pass (#404), which can do the dataflow to tell benign reuse from a real clobber; #396 tracks that.

Both referenced issues are closed (#404 "Lint/LSP: scope-aware name-resolution pass", #396 "Lint: fence the two load-bearing traps"). Nothing open tracks the general fence, so the comment reads as "covered elsewhere" while pointing at nothing.

The gap that remains open

llms.txt:63-64 calls missing local "the single most common scope bug". Neither shape is currently flagged at v0.38.0 / 078e759:

total is 100
define helper as:
    total is 0            # no `local` -> clobbers the module binding
    for i in range of n:
        total is total + i
    return total
print of (str of (helper of 4))
print of ("caller total is now " + (str of total))
6
caller total is now 6
define f(flag) as:
    if flag == 1:
        local t is 1
    else:
        t is 2           # sibling branch, no `local` -> writes outward
    return t
print of (str of (f of 0))
2

Both: no issues found.

The second is the more interesting one, because it is the trap llms.txt:66-68 documents explicitly ("each sibling if/elif/else branch needs its own local for a first assignment") and it has a statically decidable signature: a name is local-declared on one branch of an if/elif/else and bare-assigned on a sibling. That does not need full dataflow, and it does not have W015's noise problem — the presence of the local on the sibling branch is direct evidence the author intended a local.

Not arguing with W015's scoping

The rationale at lint.c:1836-1845 is evidence-backed (155 benign firings for the broad reading) and I think it is right — a blanket outer-mutation warning would be noise. This is only about the tracker being dangling and about the narrower, higher-precision subcase above being available without the full pass.

Suggested scope

  1. Reopen or supersede the tracking issue so lint.c:1844's reference resolves.
  2. Land the sibling-branch check as its own W-code — high precision, no dataflow required.
  3. Leave the general case where it is until the scope-aware pass exists.

Related: #396, #404, #373, W015/W016 in src/lint.c.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions