zsh-workers
 help / color / mirror / code / Atom feed
* [PATCH 1/2] zshmisc(1): Clarify the documentation of 'return' and 'exit' in conjunction with try/always
@ 2019-12-21 12:41 Daniel Shahaf
  2019-12-21 12:41 ` [PATCH 2/2] zshmisc(1): Fix markup of "try-list" and "always-list" Daniel Shahaf
  2019-12-21 17:58 ` [PATCH 1/2] zshmisc(1): Clarify the documentation of 'return' and 'exit' in conjunction with try/always Peter Stephenson
  0 siblings, 2 replies; 4+ messages in thread
From: Daniel Shahaf @ 2019-12-21 12:41 UTC (permalink / raw)
  To: zsh-workers

Having reviewed 20076, 20084, 21734, and 21735, my understanding is that
the original intention was:

- A 'return' in a function does run always-list
- An 'exit' outside a function does not run always-list
- A 'return' outside a function is treated as an 'exit'

All of which are the case today.  The remaining case, of 'exit' used
inside a function, was not specified by the referenced -workers@ posts;
does, as implemented, run the always-list; and furthermore, based in
21734 it's fair to assume that the original documentation was assuming
that 'exit' would be used outside of any function, just like it assumed
'return' would be used inside a function.

Therefore, have the documentation specify only the behaviour of 'exit'
outside any function, and leave the behaviour of 'exit' inside
a function unspecified.  Anyone who relied on the documentation of 'exit'
as documented until this commit would have run into the
documentation/implementation discrepancy described in 45075.
---
 Doc/Zsh/grammar.yo   | 16 +++++++++++-----
 Etc/BUGS             |  3 ---
 NEWS                 | 10 ++++++++++
 Test/A01grammar.ztst |  2 ++
 4 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo
index d30c9d2d7..a66358ed6 100644
--- a/Doc/Zsh/grammar.yo
+++ b/Doc/Zsh/grammar.yo
@@ -297,11 +297,11 @@ findex(always)
 cindex(always blocks)
 cindex(try blocks)
 item(tt({) var(try-list) tt(} always {) var(always-list) tt(}))(
-First execute var(try-list).  Regardless of errors, or tt(break),
-tt(continue), or tt(return) commands encountered within var(try-list),
+First execute var(try-list).  Regardless of errors, or tt(break) or
+tt(continue) commands encountered within var(try-list),
 execute var(always-list).  Execution then continues from the
 result of the execution of var(try-list); in other words, any error,
-or tt(break), tt(continue), or tt(return) command is treated in the
+or tt(break) or tt(continue) command is treated in the
 normal way, as if var(always-list) were not present.  The two
 chunks of code are referred to as the `try block' and the `always block'.
 
@@ -345,10 +345,16 @@ example({
 }
 # The error condition has been reset.)
 
-An tt(exit) command (or a tt(return) command executed at the outermost
-function level of a script) encountered in tt(try-list) does em(not) cause
+When a tt(try) block occurs outside of any function, 
+a tt(return) or a tt(exit) encountered in var(try-list) does em(not) cause
 the execution of var(always-list).  Instead, the shell exits immediately
 after any tt(EXIT) trap has been executed.
+Otherwise, a tt(return) command encountered in var(try-list) will cause the
+execution of var(always-list), just like tt(break) and tt(continue).
+
+COMMENT(The semantics of calling 'exit' in try-list inside a function are
+deliberately left unspecified, because historically there was a mismatch between
+the documented and implemented behaviours.  Cf. 20076, 21734/21735, 45075.)
 )
 findex(function)
 xitem(tt(function) var(word) ... [ tt(()) ] [ var(term) ] tt({) var(list) tt(}))
diff --git a/Etc/BUGS b/Etc/BUGS
index 8244677f6..3fbe81831 100644
--- a/Etc/BUGS
+++ b/Etc/BUGS
@@ -39,6 +39,3 @@ fn trap1 trap2
 echo out2
 ]]]
 ------------------------------------------------------------------------
-45075 - Daniel Shahaf - '{ exit } always { foo }' - docs/code mismatch
-and return/exit differences
-------------------------------------------------------------------------
diff --git a/NEWS b/NEWS
index c1322ed0f..af59cb4e6 100644
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,16 @@ path the leading '/' counts as one component.
 
 The functions builtin gained a -c option to efficiently copy functions.
 
+The zshmisc(1) manual page incorrectly stated that when 'exit' is used
+in a `try' block inside a function, the corresponding `always' block will
+be executed.  The manual page has been corrected.  The shell's behaviour
+has not changed, but code such as the following:
+.
+    f() { { exit } always { echo Hello world } }
+.
+should be changed either to use 'return' instead of 'exit', or to have
+the try/always block outside of any function.
+
 Changes from 5.6.2 to 5.7.1
 ---------------------------
 
diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst
index 2649c29c8..d3a591761 100644
--- a/Test/A01grammar.ztst
+++ b/Test/A01grammar.ztst
@@ -729,6 +729,7 @@
 3:Exit and always block with functions: simple
 >BEGIN
 >END
+F:Note that the behaviour of 'exit' inside try-list inside a function is unspecified.
 
   (
   mytrue() { echo mytrue; return 0 }
@@ -741,6 +742,7 @@
 >BEGIN
 >mytrue
 >END
+F:Note that the behaviour of 'exit' inside try-list inside a function is unspecified.
 
   (emulate sh -c '
    fn() {

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/2] zshmisc(1): Fix markup of "try-list" and "always-list".
  2019-12-21 12:41 [PATCH 1/2] zshmisc(1): Clarify the documentation of 'return' and 'exit' in conjunction with try/always Daniel Shahaf
@ 2019-12-21 12:41 ` Daniel Shahaf
  2019-12-21 17:58 ` [PATCH 1/2] zshmisc(1): Clarify the documentation of 'return' and 'exit' in conjunction with try/always Peter Stephenson
  1 sibling, 0 replies; 4+ messages in thread
From: Daniel Shahaf @ 2019-12-21 12:41 UTC (permalink / raw)
  To: zsh-workers

---
 Doc/Zsh/grammar.yo | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo
index a66358ed6..e028c8512 100644
--- a/Doc/Zsh/grammar.yo
+++ b/Doc/Zsh/grammar.yo
@@ -313,23 +313,23 @@ An `error' in this context is a condition such as a syntax error which
 causes the shell to abort execution of the current function, script, or
 list.  Syntax errors encountered while the shell is parsing the
 code do not cause the var(always-list) to be executed.  For example,
-an erroneously constructed tt(if) block in tt(try-list) would cause the
-shell to abort during parsing, so that tt(always-list) would not be
+an erroneously constructed tt(if) block in var(try-list) would cause the
+shell to abort during parsing, so that var(always-list) would not be
 executed, while an erroneous substitution such as tt(${*foo*}) would
-cause a run-time error, after which tt(always-list) would be executed.
+cause a run-time error, after which var(always-list) would be executed.
 
 An error condition can be tested and reset with the special integer
-variable tt(TRY_BLOCK_ERROR).  Outside an tt(always-list) the value is
-irrelevant, but it is initialised to tt(-1).  Inside tt(always-list), the
-value is 1 if an error occurred in the tt(try-list), else 0.  If
-tt(TRY_BLOCK_ERROR) is set to 0 during the tt(always-list), the error
-condition caused by the tt(try-list) is reset, and shell execution
-continues normally after the end of tt(always-list).  Altering the value
-during the tt(try-list) is not useful (unless this forms part of an
+variable tt(TRY_BLOCK_ERROR).  Outside an var(always-list) the value is
+irrelevant, but it is initialised to tt(-1).  Inside var(always-list), the
+value is 1 if an error occurred in the var(try-list), else 0.  If
+tt(TRY_BLOCK_ERROR) is set to 0 during the var(always-list), the error
+condition caused by the var(try-list) is reset, and shell execution
+continues normally after the end of var(always-list).  Altering the value
+during the var(try-list) is not useful (unless this forms part of an
 enclosing tt(always) block).
 
-Regardless of tt(TRY_BLOCK_ERROR), after the end of tt(always-list) the
-normal shell status tt($?) is the value returned from tt(try-list).
+Regardless of tt(TRY_BLOCK_ERROR), after the end of var(always-list) the
+normal shell status tt($?) is the value returned from var(try-list).
 This will be non-zero if there was an error, even if tt(TRY_BLOCK_ERROR)
 was set to zero.
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] zshmisc(1): Clarify the documentation of 'return' and 'exit' in conjunction with try/always
  2019-12-21 12:41 [PATCH 1/2] zshmisc(1): Clarify the documentation of 'return' and 'exit' in conjunction with try/always Daniel Shahaf
  2019-12-21 12:41 ` [PATCH 2/2] zshmisc(1): Fix markup of "try-list" and "always-list" Daniel Shahaf
@ 2019-12-21 17:58 ` Peter Stephenson
  2019-12-22  3:10   ` Daniel Shahaf
  1 sibling, 1 reply; 4+ messages in thread
From: Peter Stephenson @ 2019-12-21 17:58 UTC (permalink / raw)
  To: zsh-workers

On Sat, 2019-12-21 at 12:41 +0000, Daniel Shahaf wrote:
> Having reviewed 20076, 20084, 21734, and 21735, my understanding is that
> the original intention was:
> 
> - A 'return' in a function does run always-list
> - An 'exit' outside a function does not run always-list
> - A 'return' outside a function is treated as an 'exit'
> 
> All of which are the case today.  The remaining case, of 'exit' used
> inside a function, was not specified by the referenced -workers@ posts;
> does, as implemented, run the always-list; and furthermore, based in
> 21734 it's fair to assume that the original documentation was assuming
> that 'exit' would be used outside of any function, just like it assumed
> 'return' would be used inside a function.
> 
> Therefore, have the documentation specify only the behaviour of 'exit'
> outside any function, and leave the behaviour of 'exit' inside
> a function unspecified.  Anyone who relied on the documentation of 'exit'
> as documented until this commit would have run into the
> documentation/implementation discrepancy described in 45075.

That seems fine.

I don't think it would be problematic to document the current behaviour
of exit in a functoin, actually, with the implication it won't suddenly
change as I can't see why it would, but leaving the implicit assumption
that return is the standard way to get out of a function and otherwise
you're in uncharted territory seems fine, too.

pws


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] zshmisc(1): Clarify the documentation of 'return' and 'exit' in conjunction with try/always
  2019-12-21 17:58 ` [PATCH 1/2] zshmisc(1): Clarify the documentation of 'return' and 'exit' in conjunction with try/always Peter Stephenson
@ 2019-12-22  3:10   ` Daniel Shahaf
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Shahaf @ 2019-12-22  3:10 UTC (permalink / raw)
  To: zsh-workers

Peter Stephenson wrote on Sat, Dec 21, 2019 at 17:58:35 +0000:
> On Sat, 2019-12-21 at 12:41 +0000, Daniel Shahaf wrote:
> > Having reviewed 20076, 20084, 21734, and 21735, my understanding is that
> > the original intention was:
> > 
> > - A 'return' in a function does run always-list
> > - An 'exit' outside a function does not run always-list
> > - A 'return' outside a function is treated as an 'exit'
> > 
> > All of which are the case today.  The remaining case, of 'exit' used
> > inside a function, was not specified by the referenced -workers@ posts;
> > does, as implemented, run the always-list; and furthermore, based in
> > 21734 it's fair to assume that the original documentation was assuming
> > that 'exit' would be used outside of any function, just like it assumed
> > 'return' would be used inside a function.
> > 
> > Therefore, have the documentation specify only the behaviour of 'exit'
> > outside any function, and leave the behaviour of 'exit' inside
> > a function unspecified.  Anyone who relied on the documentation of 'exit'
> > as documented until this commit would have run into the
> > documentation/implementation discrepancy described in 45075.
> 
> That seems fine.
> 
> I don't think it would be problematic to document the current behaviour
> of exit in a functoin, actually, with the implication it won't suddenly
> change as I can't see why it would,

The documentation promised one thing and the implementation did another thing.
We can't _both_ deliver compatibility and deliver on the API promise, and
I didn't want to choose one over the other.

I certainly don't intend to change the implementation just because the
documentation said so — there's no reason to break people's code.  On the other
hand, I also want to reinforce the notion that API promises can be relied on.

> but leaving the implicit assumption that return is the standard way to get
> out of a function and otherwise you're in uncharted territory seems fine,
> too.

Yeah, it's not ideal, but using exit in a try block in a function _already is_
uncharted territory, so it seems like the lesser of three evils.

Thanks for the review,

Daniel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-12-22  3:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-21 12:41 [PATCH 1/2] zshmisc(1): Clarify the documentation of 'return' and 'exit' in conjunction with try/always Daniel Shahaf
2019-12-21 12:41 ` [PATCH 2/2] zshmisc(1): Fix markup of "try-list" and "always-list" Daniel Shahaf
2019-12-21 17:58 ` [PATCH 1/2] zshmisc(1): Clarify the documentation of 'return' and 'exit' in conjunction with try/always Peter Stephenson
2019-12-22  3:10   ` Daniel Shahaf

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).