Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Bug or Feature? Always block triggered by return in subshell within function



Return and exit behave the same way inside a try block at the top-level but not inside a try block nested in a subshell itself nested in a function. Is that expected or a bug?

Test script:
if [[ -v ZSH_EXEPATH ]]; then alias zsh=$ZSH_EXEPATH; fi;
zsh --version;

zsh <<EOF
{
  exit;
} always {
  echo "Global exit";
}
EOF

zsh <<EOF
{
  return;
} always {
  echo "Global return";
}
EOF

zsh <<EOF
({
  exit;
} always {
  echo "Global subshell exit";
})
EOF

zsh <<EOF
({
  return;
} always {
  echo "Global subshell return";
})
EOF

zsh <<EOF
() {
  {
    exit;
  } always {
    echo "Function exit";
  }
}
EOF

zsh <<EOF
() {
  {
    return;
  } always {
    echo "Function return";
  }
}
EOF

zsh <<EOF
() {
  ({
    exit;
  } always {
    echo "Function subshell exit";
  })
}
EOF

zsh <<EOF
() {
  ({
    return;
  } always {
    echo "Function subshell return";
  })
}
EOF


Output:
zsh 5.9.0.2-test (x86_64-apple-darwin24.4.0)
Function exit
Function return
Function subshell return

Section 6.3 of the manual contains the following 3 sentences:

When a try block occurs outside of any function, a return or a exit encountered in try-list does not cause the execution of always-list. Instead, the shell exits immediately after any EXIT trap has been executed. Otherwise, a return command encountered in try-list will cause the execution of always-list, just like break and continue.

The first sentence explains why the first 4 examples don't trigger the try-block and why the next two do trigger it. It's less clear to me why the last two don't behave the same. It is my impression that for most aspects return statements directly in a subshell behave like exit statements but not here. Is this difference implied by the third sentence from the manual? If not, should return statements not trigger the try-block or should exit statements trigger it?

I find the manual a little confusing because the first sentence mentions an exceptional behavior of return and exit statements. Then the last sentence states that otherwise return statements work as expected but so do exit statements, except if they are directly within a subshell. There is actually no explanation of why such exit statements don't trigger the always block.

Note that if functions are replaced with external source files, the result is the same (i.e., a "source <script-path>" is equivalent to a function call, in these examples).

Philippe

Attachment: always.zsh
Description: Binary data



Messages sorted by: Reverse Date, Date, Thread, Author