From 8f9348ee533229fe0b85aa23b1cf2fc94098b6f9 Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Wed, 18 May 2022 18:47:10 +0200 Subject: [PATCH] Make `eval` a reserved keyword Like `set` and `read` before it, `eval` can be used to set variables, and so it can't be shadowed by a function without loss of functionality. So this forbids it. Incidentally, this means we will no longer try to autoload an `eval.fish` file that's left over from an old version, which would have helped with #8963. --- src/parser_keywords.cpp | 2 +- tests/checks/eval.fish | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/parser_keywords.cpp b/src/parser_keywords.cpp index d3e3f6a93..810fa6b5f 100644 --- a/src/parser_keywords.cpp +++ b/src/parser_keywords.cpp @@ -24,7 +24,7 @@ static const string_set_t block_keywords = {L"for", L"while", L"if", static const wcstring reserved_keywords[] = { L"end", L"case", L"else", L"return", L"continue", L"break", L"argparse", - L"read", L"string", L"set", L"status", L"test", L"[", L"_"}; + L"read", L"string", L"set", L"status", L"test", L"[", L"_", L"eval"}; // The lists above are purposely implemented separately from the logic below, so that future // maintainers may assume the contents of the list based off their names, and not off what the diff --git a/tests/checks/eval.fish b/tests/checks/eval.fish index db43ebd18..86ec3c6c6 100644 --- a/tests/checks/eval.fish +++ b/tests/checks/eval.fish @@ -60,3 +60,25 @@ echo empty block eval: $status # 0 source /banana/\t/foo # CHECKERR: source: Error encountered while sourcing file '/banana/\t/foo': # CHECKERR: source: No such file or directory + +# See that eval can't be defined as a function +function eval + builtin eval $argv +end +# CHECKERR: checks/eval.fish (line {{\d+}}): function: eval: cannot use reserved keyword as function name +# CHECKERR: function eval +# CHECKERR: ^ + + +function evil --no-scope-shadowing + eval $argv +end + +# And this is why we do this: `eval` *can't* be cleanly shadowed with a function, +# because that would always introduce a new block or at the very least clobber $argv. +eval set -l argv this works +echo $argv +# CHECK: this works +evil set -l argv this does not +echo $argv +# CHECK: this works