Skip to content

fix(rust): null is None and .? is unwrap; neither needs an idiom choice - #3261

Merged
gHashTag merged 1 commit into
masterfrom
null-and-optional-unwrap
Sep 5, 2026
Merged

gHashTag merged 1 commit into
masterfrom
null-and-optional-unwrap

Conversation

@gHashTag

@gHashTag gHashTag commented Sep 5, 2026

Copy link
Copy Markdown
Owner

The source language spells the empty optional null and its unwrap .?. Both reached
Rust verbatim:

let dir = if (base != null) { base.? } else { DEFAULT_CONFIG_DIR };
//             ^^^^ cannot find value `null`   ^^ unexpected token: `?`

The generated signature is already base: Option<Vec<u8>>, so the translation needs
no idiom choice: null is None, and .? is .unwrap(). Option<T> compares
fine, so base != None is the literal rendering of what the spec wrote, and every
occurrence measured sits behind an if x != null the spec itself put there.

let dir = if (base != None) { base.unwrap() } else { DEFAULT_CONFIG_DIR };

Measured: the class closes, the column does not move

accepts, before 329
accepts, after 329
first errors on ? or null 8 → 0
specs still emitting either 16 → 1
regressions 0

Predicted +2 to +6 and measured +0: the eight specs move to their next error
rather than to acceptance. Closure is the honest measure here, not yield.

The one remaining occurrence is null = 20, in specs/lsp/schema.t27 — an enum
variant named null, which is a legal Rust identifier. The arm is anchored on the
expression position and correctly leaves it alone.

Anchored where it belongs

Inside expr_to_rust. expr_to_string carries an identical ExprIdentifier arm and
is not a backend, so it must keep returning the name — the same trap this pass met
when escaping keyword field names, where an assertion on the occurrence count caught
that there were two.

What this corrects in my own reading

I priced this class two iterations ago as "needs an idiom decision (if let versus
unwrap)"
and set it aside. That was wrong: the decision only exists if you want
idiomatic Rust. The faithful rendering is mechanical, and checking the generated
signature — Option<Vec<u8>> — is what settled it in one command.

Refs #3249

Closes #3260

The source language spells the empty optional `null` and its unwrap `.?`, and both
reached Rust verbatim: `if (base != null) { base.? }` gives
`cannot find value `null`` and `unexpected token: `?``.

The generated signature is already `base: Option<Vec<u8>>`, so the translation is
direct: `null` is `None`, `.?` is `.unwrap()`. `Option<T>` compares fine, so
`base != None` is the literal rendering of what the spec wrote, and every
occurrence sits behind an `if x != null` the spec put there itself.

Measured: accepts 329 -> 329, zero regressions, but first errors on `?` or `null`
go 8 -> 0 and specs still emitting either go 16 -> 1. Predicted +2 to +6 and
measured +0: the eight move to their next error. Closure is the honest measure.

The one remaining occurrence is `null = 20,` in specs/lsp/schema.t27 -- an enum
variant NAMED null, a legal Rust identifier. The arm is anchored on expression
position and leaves it alone.

Corrects my own pricing: two iterations ago I set this class aside as "needs an
idiom decision, if-let versus unwrap". That decision only exists if you want
idiomatic Rust; the faithful rendering is mechanical, and reading the generated
signature settled it in one command. I had reasoned about the shape of the
expression instead of looking at the type.

Anchored inside expr_to_rust: expr_to_string carries an identical ExprIdentifier
arm, is not a backend, and must keep returning the name.

Closes #3260

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge (squash) September 5, 2026 09:09
@gHashTag
gHashTag merged commit 374b1a9 into master Sep 5, 2026
29 of 30 checks passed
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-09-05 09:10:06 UTC

Summary

Status Count
Total Open PRs 13
PRs with Failing Checks 12
PRs with All Checks Green 1
READY 0
FAILING 12
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=0db5123491c1 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

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.

null and .? reach Rust verbatim, and the faithful rendering needs no idiom choice

1 participant