fix(expansion): don't trip nounset on a whole-word quoted ${var:-default} (#416)
* fix(expansion): don't trip nounset on a whole-word quoted ${var:-default}
Under `set -u`, a word that is exactly one double-quoted part holding
exactly one `${var<op>word}` is routed through `handleArrayDefaultValue()`,
which read the variable with nounset still armed. Every operator that is
supposed to suppress nounset was affected: `:-`, `-`, `:=`, `=`, `:+`, `+`.
Adjacent literal text ("${U:-d}b", "a${U:-d}") takes the general path,
which already computes `skipNounset`, so the failure looked arbitrary.
`"${#var}"` and a bare `"${var}"` still report an unbound variable, as
in GNU bash.
Reported downstream as ai-ecoverse/slicc#2978.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Lars Trieloff <lars@trieloff.net>
* test(expansion): lock the platform-dependent nounset fixtures
The comparison-tests CI job re-records fixtures on Linux and fails on any
diff. The two "must still error" fixtures were recorded against macOS bash
3.2, whose unbound-variable diagnostic omits the "line 1: " prefix that
bash 5 emits, so re-recording drifted them.
Adjust both to the Linux form and mark them locked, as CLAUDE.md
prescribes for fixtures adjusted to Linux behaviour. Record mode is now
idempotent. The recorded stderr is never compared -- compareOutputs only
checks stdout and (here, disabled) exit code -- so this only stops drift.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test(expansion): focus whole-word nounset regression coverage
---------
Signed-off-by: Lars Trieloff <lars@trieloff.net>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Hiroki Osame <hiroki.osame@gmail.com> L
Lars Trieloff committed
4af0dc0ff06b2985f19f692067af115b4ab4669d
Parent: 52a5617
Committed by GitHub <noreply@github.com>
on 9/30/2026, 12:25:22 PM