Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: BUG: "return 0 && x=abc" does not skip parameter assignment
- X-seq: zsh-workers 55207
- From: Philippe Altherr <philippe.altherr@xxxxxxxxx>
- To: Takaaki Konno <re_c25@xxxxxxxxxxx>
- Cc: "zsh-workers@xxxxxxx" <zsh-workers@xxxxxxx>
- Subject: Re: BUG: "return 0 && x=abc" does not skip parameter assignment
- Date: Sun, 11 Oct 2026 10:16:27 +0200
- Arc-authentication-results: i=1; mx.google.com; arc=none
- Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=HWq7BkxMKoK7pHeIqr8RrI7ikcPHqncTQisYETtiiqo=; fh=k9YcWrIDB1OrLvUpzXUk4bC2u1koGEt+pFMadN1cDRU=; b=C+TYFdwTTFNo0G+bFE1qnV+yay276IEdL9frCur1wgePYPzizU6WD4gp4io7ThDBqe 3us6LoD1k/ovkQU8FicNyc8iKytybNJZvJdQPiq981LBj4unwUq1i0D8hTV247WtTMgp 89GQRDbiSYWWH71wx6EnWhh7La4Jtigf/VcHooXq7QWZq91/6aKR1ykjx6+B0yRof5tL ona5JzZa2zKc94Yq+HE5pl0pV+NPC7zdOXOe83pEOHSMznR3MIHg93o6Uc+EhDh6ciT3 mFkVq8+XuoNkViqKlaC1SsqBEiK1mezVIz+elZAEz1pndAGnOmS3aIbtFIUm4fAS78zU p+HQ==; darn=zsh.org
- Arc-seal: i=1; a=rsa-sha256; t=1791706599; cv=none; d=google.com; s=arc-20260327; b=MI8aXYF0oa88gc9n+o+DLCFm1rniA/DYCuyD7axxU2ad3bXF3XhrubW9laljsEJh7m RFQNkGginSA7RdL3G/k/v5SP9oev0iBjiKXfu2Nww7KCjbZh9EpSn/lnNRFVFR5AH1aY 2YwpXpD4nhMBl8sAYDFKSjBstiJ+oXqf+nKhX5HIogzd2GKgFewmdZOocAH7odW4j+Rg DrEarFGod6lBV4cNKvD4FpNnVK9UgvOf6kGCwdpHN5YcnGxPZbClf/sJ42J/qfOHde6u 2P3uKnxT5YiXWx0ox6V98v8oSfWnlm3mgiUTDltdQntGoVskm+bUTPOCda47ez9kJ10n rMpg==
- Archived-at: <https://zsh.org/workers/55207>
- In-reply-to: <656667907.914322.1791693706363@mail.yahoo.co.jp>
- List-id: <zsh-workers.zsh.org>
- References: <423185588.916905.1791638837238.ref@mail.yahoo.co.jp> <423185588.916905.1791638837238@mail.yahoo.co.jp> <CAGdYchs2uvUDMYaQcuaY89=vzBATGTfKs6jiMdC0nCXN2pbq0w@mail.gmail.com> <656667907.914322.1791693706363@mail.yahoo.co.jp>
This is because the implementation of return (and exit) pretends to perform a break, which in my opinion is bogus.
One reason I found this to be bogus was because I thought that in the following code, return would behave like break and stop the loop.
setopt +o LOCAL_LOOPS
while true; do
() { return }
done
However, it doesn't because of
this code. Furthermore, there are
other places where both reflag and breaks are set. I still think that code should either set one or the other, depending on whether a function/script return or a loop break is desired. Fixing just one of these places in this patch doesn't make much sense. Here is an updated patch that reverts this change.
Philippe
diff --git a/Src/exec.c b/Src/exec.c
index b0794abab..b1a0652da 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1558,12 +1558,14 @@ execlist(Estate state, int dont_change_job, int exiting)
* we find a sublist followed by ORNEXT. */
if (((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) ?
execsimple(state) :
- execpline(state, code, Z_SYNC, 0)) || breaks) {
+ execpline(state, code, Z_SYNC, 0)) ||
+ breaks || retflag) {
state->pc = next;
code = *state->pc++;
next = state->pc + WC_SUBLIST_SKIP(code);
while (wc_code(code) == WC_SUBLIST &&
- WC_SUBLIST_TYPE(code) == WC_SUBLIST_AND) {
+ (breaks || retflag ||
+ WC_SUBLIST_TYPE(code) == WC_SUBLIST_AND)) {
state->pc = next;
code = *state->pc++;
next = state->pc + WC_SUBLIST_SKIP(code);
@@ -1591,12 +1593,14 @@ execlist(Estate state, int dont_change_job, int exiting)
* we find a sublist followed by ANDNEXT. */
if (!(((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) ?
execsimple(state) :
- execpline(state, code, Z_SYNC, 0))) || breaks) {
+ execpline(state, code, Z_SYNC, 0))) ||
+ breaks || retflag) {
state->pc = next;
code = *state->pc++;
next = state->pc + WC_SUBLIST_SKIP(code);
while (wc_code(code) == WC_SUBLIST &&
- WC_SUBLIST_TYPE(code) == WC_SUBLIST_OR) {
+ (breaks || retflag ||
+ WC_SUBLIST_TYPE(code) == WC_SUBLIST_OR)) {
state->pc = next;
code = *state->pc++;
next = state->pc + WC_SUBLIST_SKIP(code);
@@ -2036,7 +2040,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
}
else
unqueue_signals();
- if ((slflags & WC_SUBLIST_NOT) && !errflag && !retflag)
+ if ((slflags & WC_SUBLIST_NOT) && !errflag && !retflag && !breaks)
lastval = !lastval;
}
if (!pline_level)
diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst
index eea6ede2b..db48de8a9 100644
--- a/Test/A01grammar.ztst
+++ b/Test/A01grammar.ztst
@@ -982,38 +982,72 @@ F:its expectations.
fn
1:! does not affect return status of explicit return
+ for x in 1; do
+ ! continue
+ done
+0:! does not affect status of explicit continue
+
msg=unset
- for x in 1 2 3 4 5; do
+ for x in 1; do
continue && msg=set && print Not executed
print Not executed, neither.
done
- print $msg
-0:continue causes immediate continuation
->unset
+ print $?-$msg
+0:continue causes immediate continuation (immediate assign)
+>0-unset
+
+ msg=unset
+ for x in 1; do
+ continue && false || msg=set && print Not executed
+ print Not executed, neither.
+ done
+ print $?-$msg
+0:continue causes immediate continuation (assign after operator change)
+>0-unset
msg=unset
() {
- return && msg=set && print Not executed
- print Not executed, not nor neither.
+ return 7 || msg=set && print Not executed
+ print Not executed, neither.
}
- print $msg
-0:return causes immediate return
->unset
+ print $?-$msg
+0:return causes immediate return (immediate assign)
+>7-unset
msg=unset
- for x in 1 2 3 4 5; do
+ () {
+ return 7 || true && msg=set && print Not executed
+ print Not executed, neither.
+ }
+ print $?-$msg
+0:return causes immediate return (assign after operator change)
+>7-unset
+
+ $ZTST_testdir/../Src/zsh -fc '
+ msg=unset
+ () {
+ return 7 || msg=set && print Not executed
+ print Not executed, neither.
+ }
+ print $?-$msg
+ '
+0:return causes immediate return (no enclosing loops)
+>7-unset
+
+ msg=unset
+ for x in 1; do
! continue || msg=set && print Not executed
print Not executed, neither.
done
- print $msg
+ print $?-$msg
0:! continue causes immediate continuation
->unset
+>0-unset
msg=unset
() {
- ! return || msg=set && print Not executed
- print Not executed, not nor neither.
+ ! return 7 && msg=set && print Not executed
+ print Not executed, neither.
}
- print $msg
+ print $?-$msg
0:! return causes immediate return
->unset
+>7-unset
Messages sorted by:
Reverse Date,
Date,
Thread,
Author