]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1821: Vim9 constructors are always static v9.0.1821
authorGianmaria Bajo <mg1979.git@gmail.com>
Tue, 29 Aug 2023 20:26:30 +0000 (22:26 +0200)
committerChristian Brabandt <cb@256bit.org>
Tue, 29 Aug 2023 20:29:03 +0000 (22:29 +0200)
Problem:  Vim9 constructors are always static
Solution: make the "static" keyword an error

closes: #12945

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Gianmaria Bajo <mg1979.git@gmail.com>
runtime/doc/vim9class.txt
src/errors.h
src/testdir/test_vim9_class.vim
src/version.c
src/vim9class.c

index 926638bad5c81bd49e5bcdf0f1c34c4682c525e3..8a9e37e81230c9544628fd5b0182cfdb90439f72 100644 (file)
@@ -315,6 +315,10 @@ as the first character in the method name: >
            OtherThing._Foo()
        enddef
     endclass
+<
+                                                       *E1370*
+Note that constructors cannot be declared as "static", because they always
+are.
 
 ==============================================================================
 
index bf994333e8ba8d0d4818f3de89a0d7299f99cfcd..1ea24600b67ad8366fa1451d62d5a0a622bf7cd7 100644 (file)
@@ -3493,6 +3493,8 @@ EXTERN char e_static_cannot_be_followed_by_this[]
        INIT(= N_("E1368: Static cannot be followed by \"this\" in a member name"));
 EXTERN char e_duplicate_member_str[]
        INIT(= N_("E1369: Duplicate member: %s"));
+EXTERN char e_cannot_define_new_function_as_static[]
+       INIT(= N_("E1370: Cannot define a \"new\" function as static"));
 EXTERN char e_cannot_mix_positional_and_non_positional_str[]
        INIT(= N_("E1400: Cannot mix positional and non-positional arguments: %s"));
 EXTERN char e_fmt_arg_nr_unused_str[]
@@ -3510,4 +3512,4 @@ EXTERN char e_member_str_type_mismatch_expected_str_but_got_str[]
 EXTERN char e_method_str_type_mismatch_expected_str_but_got_str[]
        INIT(= N_("E1407: Member \"%s\": type mismatch, expected %s but got %s"));
 
-// E1368 - E1399 unused
+// E1371 - E1399 unused
index 319eb0546db5520967cf4aa12a72505f0fd6cec9..184e96de0cec15617a56bcda8fed71fe59cde60c 100644 (file)
@@ -1317,6 +1317,18 @@ def Test_class_defcompile()
   END
   v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
 
+  lines =<< trim END
+      vim9script
+
+      class C
+          static def new()
+          enddef
+      endclass
+
+      defcompile C.new
+  END
+  v9.CheckScriptFailure(lines, 'E1370: Cannot define a "new" function as static')
+
   # Trying to compile a function using a non-existing class variable
   lines =<< trim END
     vim9script
index c23c2575c00296c9ed8fe77729f35ca79990fa4f..8f978f92b118d740cf5e420a778528b59dc9aeef 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1821,
 /**/
     1820,
 /**/
index 955bd0cbcd6ddb3186616ccfc99e2ac30e453709..898dcbd4f2555743e3fb2bb2802ceaeb3c681dc9 100644 (file)
@@ -535,6 +535,34 @@ is_duplicate_method(garray_T *fgap, char_u *name)
     return FALSE;
 }
 
+/*
+ * Returns TRUE if the constructor is valid.
+ */
+    static int
+is_valid_constructor(ufunc_T *uf, int is_abstract, int has_static)
+{
+    // Constructors are not allowed in abstract classes.
+    if (is_abstract)
+    {
+       emsg(_(e_cannot_define_new_function_in_abstract_class));
+       return FALSE;
+    }
+    // A constructor is always static, no need to define it so.
+    if (has_static)
+    {
+       emsg(_(e_cannot_define_new_function_as_static));
+       return FALSE;
+    }
+    // A return type should not be specified for the new()
+    // constructor method.
+    if (uf->uf_ret_type->tt_type != VAR_VOID)
+    {
+       emsg(_(e_cannot_use_a_return_type_with_new));
+       return FALSE;
+    }
+    return TRUE;
+}
+
 /*
  * Update the interface class lookup table for the member index on the
  * interface to the member index in the class implementing the interface.
@@ -1188,25 +1216,13 @@ early_ret:
            {
                char_u *name = uf->uf_name;
                int is_new = STRNCMP(name, "new", 3) == 0;
-               if (is_new && is_abstract)
+
+               if (is_new && !is_valid_constructor(uf, is_abstract, has_static))
                {
-                   emsg(_(e_cannot_define_new_function_in_abstract_class));
-                   success = FALSE;
                    func_clear_free(uf, FALSE);
                    break;
                }
-               if (is_new)
-               {
-                   // A return type should not be specified for the new()
-                   // constructor method.
-                   if (uf->uf_ret_type->tt_type != VAR_VOID)
-                   {
-                       emsg(_(e_cannot_use_a_return_type_with_new));
-                       success = FALSE;
-                       func_clear_free(uf, FALSE);
-                       break;
-                   }
-               }
+
                garray_T *fgap = has_static || is_new
                                               ? &classfunctions : &objmethods;
                // Check the name isn't used already.