From 62a6923470827acbf124df41134ae6df52f334e6 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 Jan 2023 15:07:04 +0000 Subject: 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) --- src/proto/vim9class.pro | 1 + src/testdir/test_vim9_class.vim | 18 ++++++++++++++++++ src/version.c | 2 ++ src/vim9class.c | 13 +++++++++++++ src/vim9expr.c | 2 +- 5 files changed, 35 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/proto/vim9class.pro b/src/proto/vim9class.pro index 74d33c00c..13a643dd5 100644 --- 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 index a3fdbdb9c..389213680 100644 --- 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 index f21a1887a..4a3355c0b 100644 --- a/src/version.c +++ b/src/version.c @@ -695,6 +695,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1240, /**/ 1239, /**/ diff --git a/src/vim9class.c b/src/vim9class.c index 0262e025d..484500576 100644 --- a/src/vim9class.c +++ b/src/vim9class.c @@ -1387,6 +1387,19 @@ class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx) return -1; } +/* + * 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. */ diff --git a/src/vim9expr.c b/src/vim9expr.c index 95c6d7db0..1034f64b0 100644 --- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -357,7 +357,7 @@ compile_class_object_index(cctx_T *cctx, char_u **arg, type_T *type) 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; -- cgit v1.2.1