Commit: patch 9.2.0507: Vim9 class: public/protected member name clash uses same error

2 views
Skip to first unread message

Christian Brabandt

unread,
May 21, 2026, 4:00:14 PMMay 21
to vim...@googlegroups.com
patch 9.2.0507: Vim9 class: public/protected member name clash uses same error

Commit: https://github.com/vim/vim/commit/06a2c7105c3d678cd0c04b934d26810af15b7470
Author: Hirohito Higashi <h.eas...@gmail.com>
Date: Thu May 21 19:45:59 2026 +0000

patch 9.2.0507: Vim9 class: public/protected member name clash uses same error

Problem: When a public member and a protected member in a Vim9
class have the same name (differing only in the leading '_'),
Vim reports E1369 "Duplicate variable", which is also used for
plain duplicate definitions. Users cannot tell from the
message whether the conflict is the public/protected naming
rule or a real duplicate.
Solution: Add a dedicated error E1406 "Public and protected member
have the same name" and emit it only when the name clash is
between a public and a protected member. Keep E1369 for
genuine duplicate variable definitions (Hirohito Higashi).

fixes: #20240
closes: #20277

Signed-off-by: Hirohito Higashi <h.eas...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/tags b/runtime/doc/tags
index 6cac191f3..7a4c09031 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -4650,6 +4650,7 @@ E140 message.txt /*E140*
E1403 vim9class.txt /*E1403*
E1404 vim9class.txt /*E1404*
E1405 vim9class.txt /*E1405*
+E1406 vim9class.txt /*E1406*
E1407 vim9class.txt /*E1407*
E1408 vim9class.txt /*E1408*
E1409 vim9class.txt /*E1409*
diff --git a/runtime/doc/vim9class.txt b/runtime/doc/vim9class.txt
index 7c92c455c..58458b627 100644
--- a/runtime/doc/vim9class.txt
+++ b/runtime/doc/vim9class.txt
@@ -635,7 +635,7 @@ once. They can appear in any order, although this order is recommended: >
<
The "specifies" feature is currently not implemented.

- *E1355* *E1369*
+ *E1355* *E1369* *E1406*
Each variable and method name can be used only once. It is not possible to
define a method with the same name and different type of arguments. It is not
possible to use a public and protected member variable with the same name. An
diff --git a/src/errors.h b/src/errors.h
index 3ba7eca8f..4e261c923 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3564,7 +3564,8 @@ EXTERN char e_abstract_cannot_be_used_in_interface[]
INIT(= N_("E1404: Abstract cannot be used in an interface"));
EXTERN char e_using_class_as_value_str[]
INIT(= N_("E1405: Class \"%s\" cannot be used as a value"));
-// E1406 unused
+EXTERN char e_public_and_protected_member_have_same_name_str_str[]
+ INIT(= N_("E1406: Public and protected member have the same name: %s and _%s"));
EXTERN char e_using_typealias_as_var_val[]
INIT(= N_("E1407: Cannot use a Typealias as a variable or value"));
EXTERN char e_final_variable_not_supported_in_interface[]
diff --git a/src/po/vim.pot b/src/po/vim.pot
index e5cf8c102..ad805b30b 100644
--- a/src/po/vim.pot
+++ b/src/po/vim.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Vim
"
"Report-Msgid-Bugs-To: vim...@vim.org
"
-"POT-Creation-Date: 2026-05-20 18:41+0000
"
+"POT-Creation-Date: 2026-05-21 19:38+0000
"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>
"
"Language-Team: LANGUAGE <L...@li.org>
"
@@ -8488,6 +8488,10 @@ msgstr ""
msgid "E1405: Class \"%s\" cannot be used as a value"
msgstr ""

+#, c-format
+msgid "E1406: Public and protected member have the same name: %s and _%s"
+msgstr ""
+
msgid "E1407: Cannot use a Typealias as a variable or value"
msgstr ""

diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index 5db6c65d1..35b87b208 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -5143,7 +5143,7 @@ def Test_dup_member_variable()
var _val = 20
endclass
END
- v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
+ v9.CheckSourceFailure(lines, 'E1406: Public and protected member have the same name: val and _val', 4)

# Duplicate public and protected member variable
lines =<< trim END
@@ -5153,7 +5153,7 @@ def Test_dup_member_variable()
public var val = 10
endclass
END
- v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
+ v9.CheckSourceFailure(lines, 'E1406: Public and protected member have the same name: val and _val', 4)

# Duplicate class member variable
lines =<< trim END
@@ -5163,7 +5163,7 @@ def Test_dup_member_variable()
static var _s: string = "def"
endclass
END
- v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
+ v9.CheckSourceFailure(lines, 'E1406: Public and protected member have the same name: s and _s', 4)

# Duplicate public and protected class member variable
lines =<< trim END
@@ -5173,7 +5173,7 @@ def Test_dup_member_variable()
static var _s: string = "def"
endclass
END
- v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
+ v9.CheckSourceFailure(lines, 'E1406: Public and protected member have the same name: s and _s', 4)

# Duplicate class and object member variable
lines =<< trim END
@@ -5230,7 +5230,7 @@ def Test_dup_member_variable()
var _val = 20
endclass
END
- v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
+ v9.CheckSourceFailure(lines, 'E1406: Public and protected member have the same name: val and _val', 9)

# Duplicate object member variable in a derived class
lines =<< trim END
@@ -5244,7 +5244,7 @@ def Test_dup_member_variable()
var val = 20
endclass
END
- v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
+ v9.CheckSourceFailure(lines, 'E1406: Public and protected member have the same name: val and _val', 9)

# Two member variables with a common prefix
lines =<< trim END
diff --git a/src/version.c b/src/version.c
index dc31e54a7..863043dab 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 507,
/**/
506,
/**/
diff --git a/src/vim9class.c b/src/vim9class.c
index 8edd022bd..bc10ce8b0 100644
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -461,13 +461,14 @@ extends_check_dup_members(
{
class_T *p_cl = extends_cl;
ocmember_T *c_m = members + c_i;
- char_u *pstr = (*c_m->ocm_name.string == '_')
- ? c_m->ocm_name.string + 1 : c_m->ocm_name.string;
+ bool c_protected = (*c_m->ocm_name.string == '_');
+ char_u *pstr = c_m->ocm_name.string + c_protected;

// Check in all the parent classes in the lineage
while (p_cl != NULL)
{
int p_member_count = p_cl->class_obj_member_count;
+
if (p_member_count == 0)
{
p_cl = p_cl->class_extends;
@@ -478,12 +479,17 @@ extends_check_dup_members(
// Compare against all the members in the parent class
for (int p_i = 0; p_i < p_member_count; p_i++)
{
- ocmember_T *p_m = p_members + p_i;
- char_u *qstr = (*p_m->ocm_name.string == '_')
- ? p_m->ocm_name.string + 1 : p_m->ocm_name.string;
+ ocmember_T *p_m = p_members + p_i;
+ bool p_protected = (*p_m->ocm_name.string == '_');
+ char_u *qstr = p_m->ocm_name.string + p_protected;
if (STRCMP(pstr, qstr) == 0)
{
- semsg(_(e_duplicate_variable_str), c_m->ocm_name.string);
+ if (c_protected != p_protected)
+ semsg(_(e_public_and_protected_member_have_same_name_str_str),
+ pstr, pstr);
+ else
+ semsg(_(e_duplicate_variable_str),
+ c_m->ocm_name.string);
return FALSE;
}
}
@@ -1040,18 +1046,18 @@ is_duplicate_variable(
char_u *varname,
char_u *varname_end)
{
- string_T pstr = {varname, (size_t)(varname_end - varname)}; // Note: the .string field may
- // point to a string longer
- // than the .length field.
- // So we need to use STRNCMP()
- // to compare it.
+ // Note: the .string field may point to a string longer than the .length
+ // field. So we need to use STRNCMP() to compare it.
+ string_T pstr = {varname, (size_t)(varname_end - varname)};
int dup = FALSE;
+ bool p_protected = false;

// Step over a leading '_'.
if (*pstr.string == '_')
{
pstr.string++;
pstr.length--;
+ p_protected = true;
}

// loop == 1: class variables, loop == 2: object variables
@@ -1062,12 +1068,14 @@ is_duplicate_variable(
{
ocmember_T *m = ((ocmember_T *)vgap->ga_data) + i;
string_T qstr = {m->ocm_name.string, m->ocm_name.length};
+ bool q_protected = false;

// Step over a leading '_'.
if (*qstr.string == '_')
{
qstr.string++;
qstr.length--;
+ q_protected = true;
}

if (pstr.length == qstr.length
@@ -1076,7 +1084,11 @@ is_duplicate_variable(
char_u save_c = *varname_end;

*varname_end = NUL;
- semsg(_(e_duplicate_variable_str), varname);
+ if (p_protected != q_protected)
+ semsg(_(e_public_and_protected_member_have_same_name_str_str),
+ pstr.string, pstr.string);
+ else
+ semsg(_(e_duplicate_variable_str), varname);
*varname_end = save_c;
dup = TRUE;
break;
Reply all
Reply to author
Forward
0 new messages