# HG changeset patch # User Bram Moolenaar # Date 1674573307 -3600 # Node ID 64f03e860c91c5b4b2c89f642bc15f51df5d4107 # Parent 19d470f5723f36177eaf671ba703bbd2a3a5487b patch 9.0.1240: cannot access a private object member in a lambda Commit: https://github.com/vim/vim/commit/62a6923470827acbf124df41134ae6df52f334e6 Author: Bram Moolenaar Date: Tue Jan 24 15:07:04 2023 +0000 patch 9.0.1240: cannot access a private object member in a lambda Problem: Cannot access a private object member in a lambda defined inside the class. Solution: Go up the context stack to find the class. (closes #11866) diff --git a/src/proto/vim9class.pro b/src/proto/vim9class.pro --- a/src/proto/vim9class.pro +++ b/src/proto/vim9class.pro @@ -7,6 +7,7 @@ void ex_type(exarg_T *eap); int class_object_index(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose); ufunc_T *find_class_func(char_u **arg); int class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx); +int inside_class(cctx_T *cctx_arg, class_T *cl); void copy_object(typval_T *from, typval_T *to); void object_unref(object_T *obj); void copy_class(typval_T *from, typval_T *to); diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -645,6 +645,24 @@ def Test_class_member() END v9.CheckScriptSuccess(lines) + # access private member in lambda + lines =<< trim END + vim9script + + class Foo + this._x: number = 0 + + def Add(n: number): number + const F = (): number => this._x + n + return F() + enddef + endclass + + var foo = Foo.new() + assert_equal(5, foo.Add(5)) + END + v9.CheckScriptSuccess(lines) + # check shadowing lines =<< trim END vim9script diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1240, +/**/ 1239, /**/ 1238, diff --git a/src/vim9class.c b/src/vim9class.c --- a/src/vim9class.c +++ b/src/vim9class.c @@ -1388,6 +1388,19 @@ class_member_index(char_u *name, size_t } /* + * Return TRUE if current context "cctx_arg" is inside class "cl". + * Return FALSE if not. + */ + int +inside_class(cctx_T *cctx_arg, class_T *cl) +{ + for (cctx_T *cctx = cctx_arg; cctx != NULL; cctx = cctx->ctx_outer) + if (cctx->ctx_ufunc != NULL && cctx->ctx_ufunc->uf_class == cl) + return TRUE; + return FALSE; +} + +/* * Make a copy of an object. */ void diff --git a/src/vim9expr.c b/src/vim9expr.c --- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -357,7 +357,7 @@ compile_class_object_index(cctx_T *cctx, ocmember_T *m = &cl->class_obj_members[i]; if (STRNCMP(name, m->ocm_name, len) == 0 && m->ocm_name[len] == NUL) { - if (*name == '_' && cctx->ctx_ufunc->uf_class != cl) + if (*name == '_' && !inside_class(cctx, cl)) { semsg(_(e_cannot_access_private_member_str), m->ocm_name); return FAIL;