# HG changeset patch # User Bram Moolenaar # Date 1627928103 -7200 # Node ID fbdfa533001c9933d07ac8630725d08b02bbf054 # Parent 66a64f21b5494117c093808713a969bc97b16210 patch 8.2.3276: Vim9: exists() can only be evaluated at runtime Commit: https://github.com/vim/vim/commit/bb7ee7abe1ea1e60b8a5dadd2bed8cdbe4f3e8fb Author: Bram Moolenaar Date: Mon Aug 2 20:06:50 2021 +0200 patch 8.2.3276: Vim9: exists() can only be evaluated at runtime Problem: Vim9: exists() can only be evaluated at runtime. Solution: Evaluate at compile time for option name literals. (closes https://github.com/vim/vim/issues/8437) diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -49,7 +49,6 @@ static void f_escape(typval_T *argvars, static void f_eval(typval_T *argvars, typval_T *rettv); static void f_eventhandler(typval_T *argvars, typval_T *rettv); static void f_execute(typval_T *argvars, typval_T *rettv); -static void f_exists(typval_T *argvars, typval_T *rettv); static void f_expand(typval_T *argvars, typval_T *rettv); static void f_expandcmd(typval_T *argvars, typval_T *rettv); static void f_feedkeys(typval_T *argvars, typval_T *rettv); @@ -3521,7 +3520,7 @@ f_execute(typval_T *argvars, typval_T *r /* * "exists()" function */ - static void + void f_exists(typval_T *argvars, typval_T *rettv) { char_u *p; diff --git a/src/proto/evalfunc.pro b/src/proto/evalfunc.pro --- a/src/proto/evalfunc.pro +++ b/src/proto/evalfunc.pro @@ -18,6 +18,7 @@ buf_T *get_buf_arg(typval_T *arg); win_T *get_optional_window(typval_T *argvars, int idx); void execute_redir_str(char_u *value, int value_len); void execute_common(typval_T *argvars, typval_T *rettv, int arg_off); +void f_exists(typval_T *argvars, typval_T *rettv); void f_has(typval_T *argvars, typval_T *rettv); int dynamic_feature(char_u *feature); void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv); diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -790,6 +790,25 @@ enddef def Test_exists() CheckDefAndScriptFailure2(['exists(10)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') call assert_equal(1, exists('&tabstop')) + + if exists('+newoption') + if &newoption == 'ok' + endif + endif + if exists('&newoption') + if &newoption == 'ok' + endif + endif + if exists('+tabstop') + assert_equal(8, &tabstop) + else + assert_report('tabstop option not existing?') + endif + if exists('&tabstop') + assert_equal(8, &tabstop) + else + assert_report('tabstop option not existing?') + endif enddef def Test_expand() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3276, +/**/ 3275, /**/ 3274, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3395,8 +3395,10 @@ compile_call( int is_autoload; int is_searchpair; - // we can evaluate "has('name')" at compile time - if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0) + // We can evaluate "has('name')" at compile time. + // We can evaluate some "exists()" values at compile time. + if ((varlen == 3 && STRNCMP(*arg, "has", 3) == 0) + || (varlen == 6 && STRNCMP(*arg, "exists", 6) == 0)) { char_u *s = skipwhite(*arg + varlen + 1); typval_T argvars[2]; @@ -3408,7 +3410,9 @@ compile_call( (void)eval_lit_string(&s, &argvars[0], TRUE); s = skipwhite(s); if (*s == ')' && argvars[0].v_type == VAR_STRING - && !dynamic_feature(argvars[0].vval.v_string)) + && ((**arg == 'h' && !dynamic_feature(argvars[0].vval.v_string)) + || (**arg == 'e' && (*argvars[0].vval.v_string == '+' + || *argvars[0].vval.v_string == '&')))) { typval_T *tv = &ppconst->pp_tv[ppconst->pp_used]; @@ -3416,7 +3420,10 @@ compile_call( argvars[1].v_type = VAR_UNKNOWN; tv->v_type = VAR_NUMBER; tv->vval.v_number = 0; - f_has(argvars, tv); + if (**arg == 'h') + f_has(argvars, tv); + else + f_exists(argvars, tv); clear_tv(&argvars[0]); ++ppconst->pp_used; return OK;