Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: `return` does not behave properly under `!`
- X-seq: zsh-workers 51112
- From: Michael Greenberg <michael@greenberg.science>
- To: Stephane Chazelas <stephane@xxxxxxxxxxxx>, Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx>
- Cc: zsh-workers@xxxxxxx
- Subject: Re: `return` does not behave properly under `!`
- Date: Wed, 07 Dec 2022 10:05:34 -0500
- Archived-at: <https://zsh.org/workers/51112>
- Feedback-id: ib2794684:Fastmail
- In-reply-to: <20221207084255.ykkg6cgzn4nqc73f@chazelas.org>
- List-id: <zsh-workers.zsh.org>
- References: <m2a640qtt8.fsf@greenberg.science> <20221207084255.ykkg6cgzn4nqc73f@chazelas.org>
Hi Stephane and Bart (reply inline below, as it's relevant to Stephane),
On 2022-12-07 at 08:42:55 AM, Stephane Chazelas wrote:
> 2022-12-06 13:18:59 -0500, Michael Greenberg:
> [...]
>> i() {
>> ! return 9
>> echo fail not
>> }
>> i
>> echo $?
>> ```
> [...]
>> 0
> [...]
>
> That:
>
> ! return n
>
> Behaves like return !n (and ! return behave like return !$? (or
> return "$(( ! $? ))" in POSIX syntax) doesn't sound totally off
> to me. As written, I would say the POSIX spec may even be
> requiring it.
Here's what the POSIX spec says about `return`:
The return utility shall cause the shell to stop executing the
current function or dot script. If the shell is not currently
executing a function or dot script, the results are unspecified.
...
EXIT STATUS
The value of the special parameter '?' shall be set to n, an unsigned
decimal integer, or to the exit status of the last command executed if
n is not specified. If n is not an unsigned decimal integer, or is
greater than 255, the results are unspecified. When return is executed
in a trap action, the last command is considered to be the command
that executed immediately preceding the trap action.
And here's what it says about `!` on pipelines:
If the pipeline does not begin with the ! reserved word, the exit
status shall be the exit status of the last command specified in the
pipeline. Otherwise, the exit status shall be the logical NOT of the
exit status of the last command. That is, if the last command returns
zero, the exit status shall be 1; if the last command returns greater
than zero, the exit status shall be zero.
So my reading is the opposite: `return` doesn't have an exit status,
because it causes the currently executing function (or sourced script)
to terminate; it does, however, set $?. So `!` shouldn't affect it.
But even without a close reading of the spec, it's just not how early
return works in any language. Having the evaluation context beyond
`return` affect the returned value subverts the early and immediate
return---and, in so doing, invites bugs.
So far, dash, yash, and zsh are the only shells I've found with this
behavior, and the dash folks seem to agree that it's an undesirable
bug. And also...
On 2022-12-06 at 08:53:25 PM, Bart Schaefer wrote:
> On Tue, Dec 6, 2022 at 10:19 AM Michael Greenberg
> <michael@greenberg.science> wrote:
>>
>> Following up an example from Harald van Dijk on the dash mailing list, I
>> discovered that zsh does not `return` properly under a `!`.
>
> This appears to have been fixed by Philippe Altherr's series of
> patches for ERR_EXIT et al, zsh-workers 51001, 51071, 51076.
Ah---thank you! I wish there were a straightforward fulltext search of
the archives (though I don't know I would have found this anyway, as it
doesn't explicitly mention `return`). I'll try to test these patches to
confirm.
> That's consistent with ! break causing the while/until loop it's
> in returning with failure which I've seen code rely upon (AFAIK,
> that's the only way to get those loops to return with failure;
> doesn't work in pdksh and derivatives though).
That seems hardly relevant here: a return explicitly sets $?, unlike
break/continue (which both have exit statuses, unlike return).
Cheers,
Michael
Messages sorted by:
Reverse Date,
Date,
Thread,
Author