Subject: Re: [PATCH] typeset: set $? on incidental error
From: Daniel Shahaf <[email-masked]>
To: Bart Schaefer <[email-masked]>
Cc: [email-masked]
Date: Fri, 29 Jan 2016 09:18:34 +0000
List-Id: Zsh Workers List <zsh-workers.zsh.org>

Bart Schaefer wrote on Tue, Jan 26, 2016 at 20:17:24 -0800:
> On Jan 26, 10:50pm, Daniel Shahaf wrote:
> }
> } If existing typesets always exit zero in the circumstance that the patch
> } proposes to change, no code would be broken by this change (no existing
> } code, no new zsh-targeted code, no new ksh-targeted code), except for
> } new ksh-targeted code written by zsh users who won't be aware of this
> } difference.
> 
> This is not true.  Scripts using "setopt errexit" or "setopt errreturn"
> or "set -e" will fail in ways they did not fail before.

Scripts using errexit would have a new early-out failure mode.  I think
taking the new early-out would, at least in some cases, be the right
thing to do: it may be better to abort than to process invalid or
incomplete data.  I agree that it might be a bug in other cases.

All that said, I suppose we may as well stop here: it's clear the
original patch isn't on the verge of being applied.  How about a docs
patch instead, to point out the difference in behaviour? —

diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index fb630a7..6e3d146 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -1826,6 +1826,23 @@ reserved word interface for tt(typeset) may cause problems with the
 output of `tt(typeset -p)', which assumes the reserved word interface is
 available in order to restore array and associative array values.
 
+Unlike parameter assignment statements, tt(typeset)'s exit status on an
+assignment that involves a command substitution does not reflect the exit
+status of the command substitution.  Therefore, to test for an error in
+a command substitution, separate the declaration of the parameter from its
+initialization:
+
+example(# WRONG
+typeset var1=$(exit 1) || echo "Trouble with var1"
+
+# RIGHT
+typeset var1 && var1=$(exit 1) || echo "Trouble with var1"
+)
+
+To initialize a parameter var(param) to a command output and mark it readonly,
+use tt(typeset -r )var(param) or tt(readonly )var(param) after the parameter
+assignment statement.
+
 If the shell option tt(TYPESET_SILENT) is not set, for each remaining
 var(name) that refers to a parameter that is already set, the name and
 value of the parameter are printed in the form of an assignment.

Cheers,

Daniel