Skip to content

lint: no warning when a question-word "assignment" (why is x) silently parses as a discarded interrogative #583

Description

@InauguralPhysicist

What happened (real downstream hit, Tidepool)

While hardening Tidepool's audio_game_init (Tidepool #23), this catch handler silently printed the wrong message:

define f(e) as:
    local why is "init failed"
    if e == 1:
        why is "no builtins"      # <- silent no-op
    return why

print of (f of 1)                 # prints "init failed"

why is a question word, so the bare statement why is "no builtins" is the interrogative form (what/who/when/where/why/how is x) — an expression evaluated and discarded, not an assignment. The function returns the stale value. This is documented semantics, but it produced silently-wrong output in real consumer code and took a debugging round (module-scope suspicion, catch-scope suspicion) before the question-word rule surfaced.

The gap

--lint reports no issues found on the program above:

$ eigenscript --lint repro.eigs
repro.eigs: no issues found

An interrogative used as a bare expression statement has no effect at all — its result is always discarded. There is no legitimate reason to write one (an interrogative is only useful inside an expression, e.g. print of (why is x)). And when a same-named binding already exists in scope (here the local why two lines up), the statement is almost certainly a mistaken assignment.

Ask

A lint W-rule: warn on an interrogative expression used as a bare statement (result discarded). Suggested message shape:

W0xx: why is ... is an interrogative (question words cannot be assigned with is); as a statement its result is discarded. Rename the variable or use local.

The warning is strongest (arguably error-grade) when an identifier binding for that question word exists in scope — that's the "meant it as an assignment" signature. Flagging all statement-level interrogatives is probably fine too, since the discarded form is dead code either way.

Environment

EigenScript v0.29.0, found from Tidepool (runs --lint over every source in CI).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions