Skip to content

executor: a per-element operator joins on IFS[0], not a space (#752) - #753

Merged
berrym merged 1 commit into
masterfrom
fix/749-vector-operator-fields
Aug 16, 2026
Merged

executor: a per-element operator joins on IFS[0], not a space (#752)#753
berrym merged 1 commit into
masterfrom
fix/749-vector-operator-fields

Conversation

@berrym

@berrym berrym commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Closes #752.

The defect

"${arr[*]}" joins on the first character of IFS. With a per-element operator applied it joined on a hardcoded space, so the two forms disagreed side by side:

$ lush -c 'IFS=,; arr=(ab xy); printf "<%s>" "${arr[*]}"'
<ab,xy>
$ lush -c 'IFS=,; arr=(ab xy); printf "<%s>" "${arr[*]#a}"'
<b xy>                          # bash: <b,xy>

An empty IFS was wrong in the other direction — it must concatenate with no separator, and produced spaces.

The primitive already existed

ifs_join_separator and join_strings_with_sep are used at five other join sites, introduced by #518 to retire exactly these hardcoded-space joins. This site was missed because it lives in the operator dispatch rather than in the plain vector path.

ifs_join_separator carries the load-bearing unset-vs-empty distinction (unset → space, empty → no separator), which is why the append is guarded on the separator's length rather than assuming one byte.

Field count deliberately untouched

"${arr[@]}" with an operator should contribute N fields rather than being joined at all — that is #749, and it is a different question in a different place. This join is what a [*] form legitimately wants; the code comment says so explicitly, so a later reader does not mistake it for a decision about [@].

Verification

  • 9 new checks: a custom IFS across the operator families (#, ^^, //), positionals, the empty-IFS concatenation and the unset-IFS space, the operator-free form that must not change, a single element needing no separator, and an empty array.
  • 5 of the file's 26 checks fail against the parent build, with a control proving the binaries differ.
  • Full suite 197/197. ASan 65/65; the test 1/1 under ASan.

`"${arr[*]}"` joins its elements on the first character of IFS. Applying a
per-element operator made it join on a hardcoded space instead, so the two
forms disagreed side by side:

    IFS=,; arr=(ab xy)
    ${arr[*]}      -> ab,xy
    ${arr[*]#a}    -> b xy          bash: b,xy

An empty IFS was wrong in the other direction: it must concatenate with no
separator at all, and produced spaces.

The right primitives already existed and are used at five other join sites.
ifs_join_separator carries the load-bearing unset-vs-empty distinction --
unset IFS means a space, an EMPTY IFS means no separator -- which is why the
append is guarded on the separator's LENGTH rather than assuming one byte.
They were introduced by #518 to retire exactly these hardcoded-space joins;
this site was missed because it lives in the operator dispatch rather than in
the plain vector path.

The FIELD COUNT is a separate defect and is deliberately untouched:
`"${arr[@]}"` with an operator should contribute N fields rather than being
joined at all (#749). This join is what a `[*]` form legitimately wants, and
the comment says so, so a later reader does not mistake it for a decision
about `[@]`.

tests/integration/test_vector_substitution_spec.c gains 9 checks: a custom IFS
across the operator families, positionals, the EMPTY-IFS concatenation and the
UNSET-IFS space, the operator-free form that must not change, a single element
needing no separator, and an empty array. 5 of the file's 26 checks fail
against the parent build.
@codecov

codecov Bot commented Aug 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@berrym
berrym merged commit 535a591 into master Aug 16, 2026
7 checks passed
@berrym
berrym deleted the fix/749-vector-operator-fields branch August 16, 2026 12:54
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.

"${arr[*]}" with a per-element operator joins on a space instead of IFS[0]

1 participant