changeset 32005:ef644af2c330 v9.0.1334

patch 9.0.1334: using tt_member for the class leads to mistakes Commit: https://github.com/vim/vim/commit/b1e32ac0c998808705cfbd59e4b8510931875078 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Feb 21 12:38:51 2023 +0000 patch 9.0.1334: using tt_member for the class leads to mistakes Problem: Using tt_member for the class leads to mistakes. Solution: Add a separate tt_class field.
author Bram Moolenaar <Bram@vim.org>
date Tue, 21 Feb 2023 13:45:07 +0100
parents a9b5ffbc0428
children 379f9c5f647a
files src/evalfunc.c src/globals.h src/structs.h src/version.c src/vim9class.c src/vim9compile.c src/vim9expr.c src/vim9type.c
diffstat 8 files changed, 119 insertions(+), 118 deletions(-) [+]
line wrap: on
line diff
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -585,7 +585,7 @@ check_map_filter_arg2(type_T *type, argc
 {
     type_T *expected_member = NULL;
     type_T *(args[2]);
-    type_T t_func_exp = {VAR_FUNC, 2, 0, 0, NULL, args};
+    type_T t_func_exp = {VAR_FUNC, 2, 0, 0, NULL, NULL, args};
 
     if (context->arg_types[0].type_curr->tt_type == VAR_LIST
 	    || context->arg_types[0].type_curr->tt_type == VAR_DICT)
@@ -699,7 +699,7 @@ arg_sort_how(type_T *type, type_T *decl_
     if (type->tt_type == VAR_FUNC)
     {
 	type_T *(args[2]);
-	type_T t_func_exp = {VAR_FUNC, 2, 0, 0, &t_number, args};
+	type_T t_func_exp = {VAR_FUNC, 2, 0, 0, &t_number, NULL, args};
 
 	if (context->arg_types[0].type_curr->tt_type == VAR_LIST)
 	    args[0] = context->arg_types[0].type_curr->tt_member;
--- a/src/globals.h
+++ b/src/globals.h
@@ -538,168 +538,168 @@ EXTERN type_T static_types[82]
 #ifdef DO_INIT
 = {
     // 0: t_unknown
-    {VAR_UNKNOWN, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_UNKNOWN, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_UNKNOWN, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_UNKNOWN, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 2: t_any
-    {VAR_ANY, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_ANY, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_ANY, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_ANY, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 4: t_void
-    {VAR_VOID, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_VOID, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_VOID, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_VOID, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 6: t_bool
-    {VAR_BOOL, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_BOOL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_BOOL, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_BOOL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 8: t_null
-    {VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_SPECIAL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_SPECIAL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 10: t_none
-    {VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_SPECIAL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_SPECIAL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 12: t_number
-    {VAR_NUMBER, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_NUMBER, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 14: t_number_bool
-    {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_BOOL_OK, NULL, NULL},
-    {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_BOOL_OK|TTFLAG_CONST, NULL, NULL},
+    {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_BOOL_OK, NULL, NULL, NULL},
+    {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_BOOL_OK|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 16: t_number_float
-    {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_FLOAT_OK, NULL, NULL},
-    {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_FLOAT_OK|TTFLAG_CONST, NULL, NULL},
+    {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_FLOAT_OK, NULL, NULL, NULL},
+    {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_FLOAT_OK|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 18: t_float
-    {VAR_FLOAT, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_FLOAT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_FLOAT, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_FLOAT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 20: t_string
-    {VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_STRING, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_STRING, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 22: t_blob
-    {VAR_BLOB, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_BLOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_BLOB, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_BLOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 24: t_blob_null
-    {VAR_BLOB, 0, 0, TTFLAG_STATIC, &t_void, NULL},
-    {VAR_BLOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL},
+    {VAR_BLOB, 0, 0, TTFLAG_STATIC, &t_void, NULL, NULL},
+    {VAR_BLOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL, NULL},
 
     // 26: t_job
-    {VAR_JOB, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_JOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_JOB, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_JOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 28: t_channel
-    {VAR_CHANNEL, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_CHANNEL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_CHANNEL, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_CHANNEL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 30: t_number_or_string
-    {VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL},
-    {VAR_STRING, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL},
+    {VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
+    {VAR_STRING, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
 
     // 32: t_func_unknown
-    {VAR_FUNC, -1, -1, TTFLAG_STATIC, &t_unknown, NULL},
-    {VAR_FUNC, -1, -1, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL},
+    {VAR_FUNC, -1, -1, TTFLAG_STATIC, &t_unknown, NULL, NULL},
+    {VAR_FUNC, -1, -1, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL, NULL},
 
     // 34: t_func_void
-    {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_void, NULL},
-    {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL},
+    {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_void, NULL, NULL},
+    {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL, NULL},
 
     // 36: t_func_any
-    {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_any, NULL},
-    {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL},
+    {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_any, NULL, NULL},
+    {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL, NULL},
 
     // 38: t_func_number
-    {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_number, NULL},
-    {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL},
+    {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_number, NULL, NULL},
+    {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL, NULL},
 
     // 40: t_func_string
-    {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_string, NULL},
-    {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL},
+    {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_string, NULL, NULL},
+    {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL, NULL},
 
     // 42: t_func_bool
-    {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_bool, NULL},
-    {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL},
+    {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_bool, NULL, NULL},
+    {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL, NULL},
 
     // 44: t_func_0_void
-    {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_void, NULL},
-    {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL},
+    {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_void, NULL, NULL},
+    {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL, NULL},
 
     // 46: t_func_0_any
-    {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_any, NULL},
-    {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL},
+    {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_any, NULL, NULL},
+    {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL, NULL},
 
     // 48: t_func_0_number
-    {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_number, NULL},
-    {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL},
+    {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_number, NULL, NULL},
+    {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL, NULL},
 
     // 50: t_func_0_string
-    {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_string, NULL},
-    {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL},
+    {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_string, NULL, NULL},
+    {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL, NULL},
 
     // 52: t_list_any
-    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_any, NULL},
-    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_any, NULL, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL, NULL},
 
     // 54: t_dict_any
-    {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_any, NULL},
-    {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL},
+    {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_any, NULL, NULL},
+    {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL, NULL},
 
     // 56: t_list_empty
-    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_unknown, NULL},
-    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_unknown, NULL, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL, NULL},
 
     // 58: t_dict_empty
-    {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_unknown, NULL},
-    {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL},
+    {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_unknown, NULL, NULL},
+    {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL, NULL},
 
     // 60: t_list_bool
-    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_bool, NULL},
-    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_bool, NULL, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL, NULL},
 
     // 62: t_list_number
-    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_number, NULL},
-    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_number, NULL, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL, NULL},
 
     // 64: t_list_string
-    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_string, NULL},
-    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_string, NULL, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL, NULL},
 
     // 66: t_list_job
-    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_job, NULL},
-    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_job, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_job, NULL, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_job, NULL, NULL},
 
     // 68: t_list_dict_any
-    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_dict_any, NULL},
-    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_dict_any, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_dict_any, NULL, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_dict_any, NULL, NULL},
 
     // 70: t_list_list_any
-    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_list_any, NULL},
-    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_list_any, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_list_any, NULL, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_list_any, NULL, NULL},
 
     // 72: t_list_list_string
-    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_list_string, NULL},
-    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_list_string, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_list_string, NULL, NULL},
+    {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_list_string, NULL, NULL},
 
     // 74: t_dict_bool
-    {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_bool, NULL},
-    {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL},
+    {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_bool, NULL, NULL},
+    {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL, NULL},
 
     // 76: t_dict_number
-    {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_number, NULL},
-    {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL},
+    {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_number, NULL, NULL},
+    {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL, NULL},
 
     // 78: t_dict_string
-    {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_string, NULL},
-    {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL},
+    {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_string, NULL, NULL},
+    {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL, NULL},
 
     // 80: t_super (VAR_CLASS with tt_member set to &t_bool
-    {VAR_CLASS, 0, 0, TTFLAG_STATIC, &t_bool, NULL},
-    {VAR_CLASS, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL},
+    {VAR_CLASS, 0, 0, TTFLAG_STATIC, &t_bool, NULL, NULL},
+    {VAR_CLASS, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL, NULL},
 }
 #endif
 ;
--- a/src/structs.h
+++ b/src/structs.h
@@ -1451,7 +1451,7 @@ struct type_S {
     int8_T	    tt_min_argcount; // number of non-optional arguments
     char_u	    tt_flags;	    // TTFLAG_ values
     type_T	    *tt_member;	    // for list, dict, func return type
-				    // for class: class_T
+    class_T	    *tt_class;	    // for class and object
     type_T	    **tt_args;	    // func argument types, allocated
 };
 
--- 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 */
 /**/
+    1334,
+/**/
     1333,
 /**/
     1332,
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -990,7 +990,7 @@ early_ret:
 		if (nf->uf_ret_type != NULL)
 		{
 		    nf->uf_ret_type->tt_type = VAR_OBJECT;
-		    nf->uf_ret_type->tt_member = (type_T *)cl;
+		    nf->uf_ret_type->tt_class = cl;
 		    nf->uf_ret_type->tt_argcount = 0;
 		    nf->uf_ret_type->tt_args = NULL;
 		}
@@ -1083,9 +1083,9 @@ early_ret:
 	}
 
 	cl->class_type.tt_type = VAR_CLASS;
-	cl->class_type.tt_member = (type_T *)cl;
+	cl->class_type.tt_class = cl;
 	cl->class_object_type.tt_type = VAR_OBJECT;
-	cl->class_object_type.tt_member = (type_T *)cl;
+	cl->class_object_type.tt_class = cl;
 	cl->class_type_list = type_list;
 
 	// TODO:
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -333,7 +333,7 @@ script_var_exists(char_u *name, size_t l
 
 /*
  * Return TRUE if "name" is a local variable, argument, script variable or
- * imported.
+ * imported.  Also if "name" is "this" and in a class method.
  */
     static int
 variable_exists(char_u *name, size_t len, cctx_T *cctx)
@@ -1848,20 +1848,27 @@ compile_lhs(
 	    lhs->lhs_type = &t_any;
 	}
 
-	if (lhs->lhs_type == NULL || lhs->lhs_type->tt_member == NULL)
+	int use_class = lhs->lhs_type->tt_type == VAR_CLASS
+				       || lhs->lhs_type->tt_type == VAR_OBJECT;
+	if (lhs->lhs_type == NULL
+		|| (use_class ? lhs->lhs_type->tt_class == NULL
+					   : lhs->lhs_type->tt_member == NULL))
+	{
 	    lhs->lhs_member_type = &t_any;
-	else if (lhs->lhs_type->tt_type == VAR_CLASS
-		|| lhs->lhs_type->tt_type == VAR_OBJECT)
+	}
+	else if (use_class)
 	{
 	    // for an object or class member get the type of the member
-	    class_T *cl = (class_T *)lhs->lhs_type->tt_member;
+	    class_T *cl = lhs->lhs_type->tt_class;
 	    lhs->lhs_member_type = class_member_type(cl, after + 1,
 					   lhs->lhs_end, &lhs->lhs_member_idx);
 	    if (lhs->lhs_member_idx < 0)
 		return FAIL;
 	}
 	else
+	{
 	    lhs->lhs_member_type = lhs->lhs_type->tt_member;
+	}
     }
     return OK;
 }
@@ -2059,7 +2066,7 @@ compile_load_lhs_with_index(lhs_T *lhs, 
     {
 	// "this.value": load "this" object and get the value at index
 	// for an object or class member get the type of the member
-	class_T *cl = (class_T *)lhs->lhs_type->tt_member;
+	class_T *cl = lhs->lhs_type->tt_class;
 	type_T *type = class_member_type(cl, var_start + 5,
 					   lhs->lhs_end, &lhs->lhs_member_idx);
 	if (lhs->lhs_member_idx < 0)
@@ -2194,7 +2201,7 @@ compile_assign_unlet(
 
 		if (dest_type == VAR_OBJECT)
 		{
-		    class_T *cl = (class_T *)lhs->lhs_type->tt_member;
+		    class_T *cl = lhs->lhs_type->tt_class;
 
 		    if (cl->class_flags & CLASS_INTERFACE)
 		    {
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -263,7 +263,7 @@ compile_class_object_index(cctx_T *cctx,
 	return FAIL;
     }
 
-    class_T *cl = (class_T *)type->tt_member;
+    class_T *cl = type->tt_class;
     int is_super = type->tt_flags & TTFLAG_SUPER;
     if (type == &t_super)
     {
--- a/src/vim9type.c
+++ b/src/vim9type.c
@@ -86,11 +86,9 @@ copy_type_deep_rec(type_T *type, garray_
     ((type_T **)seen_types->ga_data)[seen_types->ga_len * 2 + 1] = copy;
     ++seen_types->ga_len;
 
-    if (copy->tt_member != NULL
-	    && copy->tt_type != VAR_OBJECT && copy->tt_type != VAR_CLASS)
+    if (copy->tt_member != NULL)
 	copy->tt_member = copy_type_deep_rec(copy->tt_member,
 							 type_gap, seen_types);
-
     if (type->tt_args != NULL)
 	for (int i = 0; i < type->tt_argcount; ++i)
 	    copy->tt_args[i] = copy_type_deep_rec(copy->tt_args[i],
@@ -144,11 +142,7 @@ alloc_type(type_T *type)
     *ret = *type;
 
     if (ret->tt_member != NULL)
-    {
-	// tt_member points to the class_T for VAR_CLASS and VAR_OBJECT
-	if (type->tt_type != VAR_CLASS && type->tt_type != VAR_OBJECT)
-	    ret->tt_member = alloc_type(ret->tt_member);
-    }
+	ret->tt_member = alloc_type(ret->tt_member);
 
     if (type->tt_args != NULL)
     {
@@ -180,9 +174,7 @@ free_type(type_T *type)
 	vim_free(type->tt_args);
     }
 
-    // for an object and class tt_member is a pointer to the class
-    if (type->tt_type != VAR_OBJECT && type->tt_type != VAR_CLASS)
-	free_type(type->tt_member);
+    free_type(type->tt_member);
 
     vim_free(type);
 }
@@ -419,6 +411,7 @@ typval2type_int(typval_T *tv, int copyID
 {
     type_T  *type;
     type_T  *member_type = NULL;
+    class_T *class_type = NULL;
     int	    argcount = 0;
     int	    min_argcount = 0;
 
@@ -584,9 +577,9 @@ typval2type_int(typval_T *tv, int copyID
     }
 
     if (tv->v_type == VAR_CLASS)
-	member_type = (type_T *)tv->vval.v_class;
+	class_type = tv->vval.v_class;
     else if (tv->v_type == VAR_OBJECT && tv->vval.v_object != NULL)
-	member_type = (type_T *)tv->vval.v_object->obj_class;
+	class_type = tv->vval.v_object->obj_class;
 
     type = get_type_ptr(type_gap);
     if (type == NULL)
@@ -601,6 +594,7 @@ typval2type_int(typval_T *tv, int copyID
 	type->tt_min_argcount -= tv->vval.v_partial->pt_argc;
     }
     type->tt_member = member_type;
+    type->tt_class = class_type;
 
     return type;
 }
@@ -887,19 +881,17 @@ check_type_maybe(
 	    if (actual->tt_type == VAR_ANY)
 		return MAYBE;	// use runtime type check
 	    if (actual->tt_type != VAR_OBJECT)
-		return FAIL;	// don't use tt_member
+		return FAIL;	// don't use tt_class
 
 	    // check the class, base class or an implemented interface matches
 	    class_T *cl;
-	    for (cl = (class_T *)actual->tt_member; cl != NULL;
-							cl = cl->class_extends)
+	    for (cl = actual->tt_class; cl != NULL; cl = cl->class_extends)
 	    {
-		if ((class_T *)expected->tt_member == cl)
+		if (expected->tt_class == cl)
 		    break;
 		int i;
 		for (i = cl->class_interface_count - 1; i >= 0; --i)
-		    if ((class_T *)expected->tt_member
-						 == cl->class_interfaces_cl[i])
+		    if (expected->tt_class == cl->class_interfaces_cl[i])
 			break;
 		if (i >= 0)
 		    break;
@@ -1321,7 +1313,7 @@ parse_type(char_u **arg, garray_T *type_
 		// Although the name is that of a class or interface, the type
 		// uses will be an object.
 		type->tt_type = VAR_OBJECT;
-		type->tt_member = (type_T *)tv.vval.v_class;
+		type->tt_class = tv.vval.v_class;
 		clear_tv(&tv);
 
 		*arg += len;
@@ -1659,8 +1651,8 @@ type_name(type_T *type, char **tofree)
 
     if (type->tt_type == VAR_OBJECT || type->tt_type == VAR_CLASS)
     {
-	char_u *class_name = type->tt_member == NULL ? (char_u *)"Unknown"
-				    : ((class_T *)type->tt_member)->class_name;
+	char_u *class_name = type->tt_class == NULL ? (char_u *)"Unknown"
+				    : type->tt_class->class_name;
 	size_t len = STRLEN(name) + STRLEN(class_name) + 3;
 	*tofree = alloc(len);
 	if (*tofree != NULL)