Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-unknown-linux-gnu' -DCONF_VENDOR='unknown' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -D_FORTIFY_SOURCE=2 -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fno-plt -DDEFAULT_PATH_VALUE='/usr/local/sbin:/usr/local/bin:/usr/bin' -DSTANDARD_UTILS_PATH='/usr/bin' -DSYS_BASHRC='/etc/bash.bashrc' -DSYS_BASH_LOGOUT='/etc/bash.bash_logout' -DNON_INTERACTIVE_LOGIN_SHELLS -Wno-parentheses -Wno-format-security uname output: Linux ArchBox0 4.19.2-arch1-1-ARCH #1 SMP PREEMPT Tue Nov 13 21:16:19 UTC 2018 x86_64 GNU/Linux Machine Type: x86_64-unknown-linux-gnu
Bash Version: 4.4 Patch Level: 23 Release Status: release Description: The manual's section on `declare` (aka `typeset`) states that you can negate any attribute except for "-r" and "-a" by replacing "-" with "+". Aside from the fact that this appears to mistakenly leave out associative arrays ("-A"), this leaves one to wonder what happens if you try to negate the function attribute. At first glance, this seems impossible, since a (non-option) argument to `declare` is assumed to be a variable, and only gets considered a function if you include the "-f" (or "-F") option. But, if you include *both* "-f" and "+f", something unusual happens. First the setup and demonstration of `declare`'s usual behavior: $ func () { echo 'hello world'; } $ declare -p -- func bash: declare: func: not found $ declare -pF -- func declare -f func $ declare -pf -- func func () { echo 'hello world' } If we try to remove func's function attribute by just saying "declare +f -- func", `declare` (as usual) assumes we mean the *variable *"func", and nothing of interest happens. It's equivalent to "declare -- func". But what if we include "-f" to state we're talking about functions and not variables, yet include "+f" to try to turn it off? $ declare -f +f -- func # Expectation: Error message or no-op. $ func # hello world # So nothing changed, right? Wrong. $ declare -p -- func # bash: declare: func: not found # Again as expected. But... $ declare -pF -- func # declare -- func # The "-f" attribute is missing. Weird... $ declare -pf -- func # declare -- func=" " # A tab character? What the heck?? Where did that come from? Make no mistake, the function is still a function. Executing it works the same as before, and attempting to expand it as a parameter fails just as before. In almost all respects, the line `declare -f +f -- func` does nothing. Yet `declare` has been tricked into an inconsistent view of the world! Namely, it appears to believe the following things simultaneously: *1.* There is no variable named "func". *2.* There is a function named "func". *3.* This function does NOT have the "-f" attribute. (???) *4.* This function has a variable definition, not a function definition. (???) *5.* The value of this variable definition is a single tab character. (???????) Again, `declare`'s vision of the world appears to have no basis in reality. In particular, expanding "$func" does not yield a tab. Neither the order nor the case of the "f"-options on the problematic line appear to have any affect. Few more random observations: $ declare -F -- func # func # Same as normal. $ declare -f -- func # func () # } { # } Same as normal again. echo 'hello world' # } Has `declare` regained sanity? (Spoiler: no) } # } # (In the below, irrelevant lines have been removed.) $ declare # func # I'm not sure if this is ever a legitimate output line for a bare `declare`. $ declare -f # Nothing. In particular, different from `declare -f -- func`. $ declare -F # Again nothing, again different from `declare -F -- func`. $ declare -fp # declare -- func=" " # Identical wrong answer as `declare -fp -- func`. $ declare -Fp # declare -- func # Ditto. So, we can add these two to the list of things `declare` believes about `func`. *6.* The function `func` has a function definition. *7.* The function (possibly variable?) named "func" exists, but has no definition. (???) *8.* There is no function named "func". (???) What is going on here? Repeat-By: $ func () { echo 'hello, world'; } # Setup. $ declare -f +f -- func # The problem. $ declare -pf -- func # declare -- func=" " # Now `declare` believes nonsensical things like this. Fix: N/A. This is just an edge case that would never actually be used. If anything, this is the expected behavior: expected () { printf -- 'bash: declare: %s: inconsistent flags or something.' "$1" 1>&2; return 1; } So, just replace any occurrences of the problematic command with calls to the above, and you're all set! ;)