changeset 34006:ab6a70fad5b5 v9.0.2184

patch 9.0.2184: Vim9: inconsistent :type/:class messages Commit: https://github.com/vim/vim/commit/e75fde6b043371a188660c3423e48b1b7fd7e14b Author: Ernie Rael <errael@raelity.com> Date: Thu Dec 21 17:18:54 2023 +0100 patch 9.0.2184: Vim9: inconsistent :type/:class messages Problem: Vim9: inconsistent :type/:class messages Solution: Update the Messages (Ernie Rael) closes: #13706 Signed-off-by: Ernie Rael <errael@raelity.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Thu, 21 Dec 2023 17:30:05 +0100
parents f5c639a69421
children bcc7d4e2de7c
files src/eval.c src/evalvars.c src/testdir/test_vim9_assign.vim src/testdir/test_vim9_class.vim src/testdir/test_vim9_disassemble.vim src/testdir/test_vim9_typealias.vim src/typval.c src/version.c src/vim9.h src/vim9compile.c src/vim9execute.c src/vim9instr.c src/vim9type.c
diffstat 13 files changed, 92 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -1890,10 +1890,8 @@ set_var_lval(
 	    if (eval_variable(lp->ll_name, (int)STRLEN(lp->ll_name),
 				 lp->ll_sid, &tv, &di, EVAL_VAR_VERBOSE) == OK)
 	    {
-		if (di != NULL && di->di_tv.v_type == VAR_TYPEALIAS)
+		if (di != NULL && check_typval_is_value(&di->di_tv) == FAIL)
 		{
-		    semsg(_(e_cannot_modify_typealias),
-					di->di_tv.vval.v_typealias->ta_name);
 		    clear_tv(&tv);
 		    return;
 		}
@@ -2007,9 +2005,10 @@ tv_op(typval_T *tv1, typval_T *tv2, char
     char_u	*s;
     int		failed = FALSE;
 
-    // Can't do anything with a Funcref or Dict on the right.
+    // Can't do anything with a Funcref or Dict or Type on the right.
     // v:true and friends only work with "..=".
     if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT
+		    && tv2->v_type != VAR_CLASS && tv2->v_type != VAR_TYPEALIAS
 		    && ((tv2->v_type != VAR_BOOL && tv2->v_type != VAR_SPECIAL)
 								|| *op == '.'))
     {
@@ -2026,10 +2025,12 @@ tv_op(typval_T *tv1, typval_T *tv2, char
 	    case VAR_JOB:
 	    case VAR_CHANNEL:
 	    case VAR_INSTR:
+	    case VAR_OBJECT:
+		break;
 	    case VAR_CLASS:
-	    case VAR_OBJECT:
 	    case VAR_TYPEALIAS:
-		break;
+		check_typval_is_value(tv1);
+		return FAIL;
 
 	    case VAR_BLOB:
 		if (*op != '+' || tv2->v_type != VAR_BLOB)
@@ -2142,7 +2143,8 @@ tv_op(typval_T *tv1, typval_T *tv2, char
 	}
     }
 
-    semsg(_(e_wrong_variable_type_for_str_equal), op);
+    if (check_typval_is_value(tv2) == OK)
+	semsg(_(e_wrong_variable_type_for_str_equal), op);
     return FAIL;
 }
 
@@ -5019,11 +5021,14 @@ check_can_index(typval_T *rettv, int eva
 	case VAR_JOB:
 	case VAR_CHANNEL:
 	case VAR_INSTR:
+	case VAR_OBJECT:
+	    if (verbose)
+		emsg(_(e_cannot_index_special_variable));
+	    return FAIL;
 	case VAR_CLASS:
-	case VAR_OBJECT:
 	case VAR_TYPEALIAS:
 	    if (verbose)
-		emsg(_(e_cannot_index_special_variable));
+		check_typval_is_value(rettv);
 	    return FAIL;
 	case VAR_UNKNOWN:
 	case VAR_ANY:
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -3974,12 +3974,8 @@ set_var_const(
 		goto failed;
 	    }
 
-	    if (di->di_tv.v_type == VAR_TYPEALIAS)
-	    {
-		semsg(_(e_cannot_modify_typealias),
-					    di->di_tv.vval.v_typealias->ta_name);
+	    if (check_typval_is_value(&di->di_tv) == FAIL)
 		goto failed;
-	    }
 
 	    if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0)
 	    {
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -3090,18 +3090,18 @@ def Test_type_check()
     assert_fails('l = N', 'E1012: Type mismatch; expected list<number> but got number')
     assert_fails('b = N', 'E1012: Type mismatch; expected blob but got number')
     assert_fails('Fn = N', 'E1012: Type mismatch; expected func(...): unknown but got number')
-    assert_fails('A = N', 'E1012: Type mismatch; expected class<A> but got number')
+    assert_fails('A = N', 'E1405: Class "A" cannot be used as a value')
     assert_fails('o = N', 'E1012: Type mismatch; expected object<A> but got number')
-    assert_fails('T = N', 'E1395: Type alias "T" cannot be modified')
+    assert_fails('T = N', 'E1403: Type alias "T" cannot be used as a value')
 
     # Use a compound operator with different LHS types
     assert_fails('d += N', 'E734: Wrong variable type for +=')
     assert_fails('l += N', 'E734: Wrong variable type for +=')
     assert_fails('b += N', 'E734: Wrong variable type for +=')
     assert_fails('Fn += N', 'E734: Wrong variable type for +=')
-    assert_fails('A += N', 'E734: Wrong variable type for +=')
+    assert_fails('A += N', 'E1405: Class "A" cannot be used as a value')
     assert_fails('o += N', 'E734: Wrong variable type for +=')
-    assert_fails('T += N', 'E1395: Type alias "T" cannot be modified')
+    assert_fails('T += N', 'E1403: Type alias "T" cannot be used as a value')
 
     # Assign to a number variable
     assert_fails('N = d', 'E1012: Type mismatch; expected number but got dict<number>')
@@ -3144,9 +3144,9 @@ def Test_type_check()
     assert_fails('l ..= S', 'E734: Wrong variable type for .=')
     assert_fails('b ..= S', 'E734: Wrong variable type for .=')
     assert_fails('Fn ..= S', 'E734: Wrong variable type for .=')
-    assert_fails('A ..= S', 'E734: Wrong variable type for .=')
+    assert_fails('A ..= S', 'E1405: Class "A" cannot be used as a value')
     assert_fails('o ..= S', 'E734: Wrong variable type for .=')
-    assert_fails('T ..= S', 'E1395: Type alias "T" cannot be modified')
+    assert_fails('T ..= S', 'E1403: Type alias "T" cannot be used as a value')
   END
   v9.CheckSourceSuccess(lines)
 
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -242,7 +242,7 @@ def Test_class_basic()
     if A
     endif
   END
-  v9.CheckSourceFailure(lines, 'E1319: Using a Class as a Number', 4)
+  v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
 
   # Test for using object as a bool
   lines =<< trim END
@@ -281,7 +281,7 @@ def Test_class_basic()
     endclass
     :exe 'call ' .. A
   END
-  v9.CheckSourceFailure(lines, 'E1323: Using a Class as a String', 4)
+  v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
 
   # Test for using object as a string
   lines =<< trim END
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -3193,7 +3193,7 @@ def Test_disassemble_ifargnotset()
   unlet g:instr
 enddef
 
-" Disassemble instructions for ISN_COMPARECLASS and ISN_COMPAREOBJECT
+" Disassemble instructions for ISN_COMPAREOBJECT
 def Test_disassemble_compare_class_object()
   var lines =<< trim END
     vim9script
@@ -3202,8 +3202,6 @@ def Test_disassemble_compare_class_objec
     class B
     endclass
     def Foo(a: A, b: B)
-      if A == B
-      endif
       if a == b
       endif
     enddef
@@ -3211,19 +3209,13 @@ def Test_disassemble_compare_class_objec
   END
   v9.CheckScriptSuccess(lines)
   assert_match('<SNR>\d*_Foo\_s*' ..
-    'if A == B\_s*' ..
-    '0 LOADSCRIPT A-0 from .*\_s*' ..
-    '1 LOADSCRIPT B-1 from .*\_s*' ..
-    '2 COMPARECLASS ==\_s*' ..
+    'if a == b\_s*' ..
+    '0 LOAD arg\[-2\]\_s*' ..
+    '1 LOAD arg\[-1\]\_s*' ..
+    '2 COMPAREOBJECT ==\_s*' ..
     '3 JUMP_IF_FALSE -> 4\_s*' ..
     'endif\_s*' ..
-    'if a == b\_s*' ..
-    '4 LOAD arg\[-2\]\_s*' ..
-    '5 LOAD arg\[-1\]\_s*' ..
-    '6 COMPAREOBJECT ==\_s*' ..
-    '7 JUMP_IF_FALSE -> 8\_s*' ..
-    'endif\_s*' ..
-    '8 RETURN void', g:instr)
+    '4 RETURN void', g:instr)
   unlet g:instr
 enddef
 
--- a/src/testdir/test_vim9_typealias.vim
+++ b/src/testdir/test_vim9_typealias.vim
@@ -18,7 +18,7 @@ def Test_typealias()
     assert_equal('typealias<list<string>>', typename(ListOfStrings))
     assert_equal(v:t_typealias, type(ListOfStrings))
     assert_equal('ListOfStrings', string(ListOfStrings))
-    assert_equal(false, null == ListOfStrings)
+    assert_fails('var x = null == ListOfStrings', 'E1403: Type alias "ListOfStrings" cannot be used as a value')
   END
   v9.CheckSourceSuccess(lines)
 
@@ -36,7 +36,7 @@ def Test_typealias()
       assert_equal('typealias<list<string>>', typename(ListOfStrings))
       assert_equal(v:t_typealias, type(ListOfStrings))
       assert_equal('ListOfStrings', string(ListOfStrings))
-      assert_equal(false, null == ListOfStrings)
+      #assert_equal(false, null == ListOfStrings)
     enddef
     Bar()
   END
@@ -201,7 +201,7 @@ def Test_typealias()
     type MyType = list<number>
     MyType = [1, 2, 3]
   END
-  v9.CheckSourceFailure(lines, 'E1395: Type alias "MyType" cannot be modified', 3)
+  v9.CheckSourceFailure(lines, 'E1403: Type alias "MyType" cannot be used as a value', 3)
 
   # Assigning a type alias (def function level)
   lines =<< trim END
@@ -219,11 +219,11 @@ def Test_typealias()
     vim9script
     type MyType = list<number>
     assert_fails('var m = MyType', 'E1403: Type alias "MyType" cannot be used as a value')
-    assert_fails('var i = MyType + 1', 'E1400: Using type alias "MyType" as a Number')
-    assert_fails('var f = 1.0 + MyType', 'E1400: Using type alias "MyType" as a Number')
-    assert_fails('MyType += 10', 'E1395: Type alias "MyType" cannot be modified')
-    assert_fails('var x = $"-{MyType}-"', 'E1402: Using type alias "MyType" as a String')
-    assert_fails('var x = MyType[1]', 'E909: Cannot index a special variable')
+    assert_fails('var i = MyType + 1', 'E1403: Type alias "MyType" cannot be used as a value')
+    assert_fails('var f = 1.0 + MyType', 'E1403: Type alias "MyType" cannot be used as a value')
+    assert_fails('MyType += 10', 'E1403: Type alias "MyType" cannot be used as a value')
+    assert_fails('var x = $"-{MyType}-"', 'E1403: Type alias "MyType" cannot be used as a value')
+    assert_fails('var x = MyType[1]', 'E1403: Type alias "MyType" cannot be used as a value')
   END
   v9.CheckSourceSuccess(lines)
 
@@ -236,7 +236,7 @@ def Test_typealias()
     enddef
     Foo()
   END
-  v9.CheckSourceFailure(lines, 'E1051: Wrong argument type for +', 1)
+  v9.CheckSourceFailure(lines, 'E1407: Cannot use a Typealias as a variable or value', 1)
 
   # Using type alias in an expression (def function level)
   lines =<< trim END
@@ -305,7 +305,7 @@ def Test_typealias()
     var n: number
     var x = A == n
   END
-  v9.CheckSourceFailure(lines, 'E1072: Cannot compare typealias with number', 4)
+  v9.CheckSourceFailure(lines, 'E1403: Type alias "A" cannot be used as a value', 4)
 
   # Comparing type alias with a number (def function level)
   lines =<< trim END
@@ -317,7 +317,7 @@ def Test_typealias()
     enddef
     Foo()
   END
-  v9.CheckSourceFailure(lines, 'E1072: Cannot compare typealias with number', 2)
+  v9.CheckSourceFailure(lines, 'E1407: Cannot use a Typealias as a variable or value', 2)
 
   # casting a number to a type alias (script level)
   lines =<< trim END
--- a/src/typval.c
+++ b/src/typval.c
@@ -262,7 +262,8 @@ tv_get_bool_or_number_chk(
 	    emsg(_(e_using_blob_as_number));
 	    break;
 	case VAR_CLASS:
-	    emsg(_(e_using_class_as_number));
+	case VAR_TYPEALIAS:
+	    check_typval_is_value(varp);
 	    break;
 	case VAR_OBJECT:
 	    emsg(_(e_using_object_as_number));
@@ -270,10 +271,6 @@ tv_get_bool_or_number_chk(
 	case VAR_VOID:
 	    emsg(_(e_cannot_use_void_value));
 	    break;
-	case VAR_TYPEALIAS:
-	    semsg(_(e_using_typealias_as_number),
-					varp->vval.v_typealias->ta_name);
-	    break;
 	case VAR_UNKNOWN:
 	case VAR_ANY:
 	case VAR_INSTR:
@@ -383,7 +380,8 @@ tv_get_float_chk(typval_T *varp, int *er
 	    emsg(_(e_using_blob_as_float));
 	    break;
 	case VAR_CLASS:
-	    emsg(_(e_using_class_as_float));
+	case VAR_TYPEALIAS:
+	    check_typval_is_value(varp);
 	    break;
 	case VAR_OBJECT:
 	    emsg(_(e_using_object_as_float));
@@ -391,10 +389,6 @@ tv_get_float_chk(typval_T *varp, int *er
 	case VAR_VOID:
 	    emsg(_(e_cannot_use_void_value));
 	    break;
-	case VAR_TYPEALIAS:
-	    semsg(_(e_using_typealias_as_float),
-					varp->vval.v_typealias->ta_name);
-	    break;
 	case VAR_UNKNOWN:
 	case VAR_ANY:
 	case VAR_INSTR:
@@ -1131,7 +1125,8 @@ tv_get_string_buf_chk_strict(typval_T *v
 	    emsg(_(e_using_blob_as_string));
 	    break;
 	case VAR_CLASS:
-	    emsg(_(e_using_class_as_string));
+	case VAR_TYPEALIAS:
+	    check_typval_is_value(varp);
 	    break;
 	case VAR_OBJECT:
 	    emsg(_(e_using_object_as_string));
@@ -1159,10 +1154,6 @@ tv_get_string_buf_chk_strict(typval_T *v
 	case VAR_VOID:
 	    emsg(_(e_cannot_use_void_value));
 	    break;
-	case VAR_TYPEALIAS:
-	    semsg(_(e_using_typealias_as_string),
-					varp->vval.v_typealias->ta_name);
-	    break;
 	case VAR_UNKNOWN:
 	case VAR_ANY:
 	case VAR_INSTR:
@@ -1358,7 +1349,13 @@ typval_compare(
     int		res = 0;
     int		type_is = type == EXPR_IS || type == EXPR_ISNOT;
 
-    if (type_is && tv1->v_type != tv2->v_type)
+    if (check_typval_is_value(tv1) == FAIL
+	|| check_typval_is_value(tv2) == FAIL)
+    {
+	clear_tv(tv1);
+	return FAIL;
+    }
+    else if (type_is && tv1->v_type != tv2->v_type)
     {
 	// For "is" a different type always means FALSE, for "isnot"
 	// it means TRUE.
@@ -1397,15 +1394,6 @@ typval_compare(
 	}
 	n1 = res;
     }
-    else if (tv1->v_type == VAR_CLASS || tv2->v_type == VAR_CLASS)
-    {
-	if (typval_compare_class(tv1, tv2, type, ic, &res) == FAIL)
-	{
-	    clear_tv(tv1);
-	    return FAIL;
-	}
-	n1 = res;
-    }
     else if (tv1->v_type == VAR_OBJECT || tv2->v_type == VAR_OBJECT)
     {
 	if (typval_compare_object(tv1, tv2, type, ic, &res) == FAIL)
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2184,
+/**/
     2183,
 /**/
     2182,
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -168,7 +168,6 @@ typedef enum {
     ISN_COMPAREDICT,
     ISN_COMPAREFUNC,
     ISN_COMPAREANY,
-    ISN_COMPARECLASS,
     ISN_COMPAREOBJECT,
 
     // expression operations
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -550,6 +550,12 @@ need_type_where(
 {
     int ret;
 
+    if (expected->tt_type != VAR_CLASS && expected->tt_type != VAR_TYPEALIAS)
+    {
+	if (check_type_is_value(actual) == FAIL)
+	    return FAIL;
+    }
+
     if (expected == &t_bool && actual != &t_bool
 					&& (actual->tt_flags & TTFLAG_BOOL_OK))
     {
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -5034,7 +5034,6 @@ exec_instructions(ectx_T *ectx)
 	    case ISN_COMPAREFUNC:
 	    case ISN_COMPARESTRING:
 	    case ISN_COMPAREBLOB:
-	    case ISN_COMPARECLASS:
 	    case ISN_COMPAREOBJECT:
 		{
 		    typval_T	*tv1 = STACK_TV_BOT(-2);
@@ -5069,11 +5068,6 @@ exec_instructions(ectx_T *ectx)
 		    {
 			status = typval_compare_blob(tv1, tv2, exprtype, &res);
 		    }
-		    else if (iptr->isn_type == ISN_COMPARECLASS)
-		    {
-			status = typval_compare_class(tv1, tv2,
-							exprtype, FALSE, &res);
-		    }
 		    else // ISN_COMPAREOBJECT
 		    {
 			status = typval_compare_object(tv1, tv2,
@@ -7206,7 +7200,6 @@ list_instructions(char *pfx, isn_T *inst
 	    case ISN_COMPARELIST:
 	    case ISN_COMPAREDICT:
 	    case ISN_COMPAREFUNC:
-	    case ISN_COMPARECLASS:
 	    case ISN_COMPAREOBJECT:
 	    case ISN_COMPAREANY:
 		   {
@@ -7245,7 +7238,6 @@ list_instructions(char *pfx, isn_T *inst
 			   case ISN_COMPARELIST: type = "COMPARELIST"; break;
 			   case ISN_COMPAREDICT: type = "COMPAREDICT"; break;
 			   case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break;
-			   case ISN_COMPARECLASS: type = "COMPARECLASS"; break;
 			   case ISN_COMPAREOBJECT:
 						 type = "COMPAREOBJECT"; break;
 			   case ISN_COMPAREANY: type = "COMPAREANY"; break;
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -255,13 +255,18 @@ may_generate_2STRING(int offset, int tol
 }
 
     static int
-check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
+check_number_or_float(type_T *typ1, type_T *typ2, char_u *op)
 {
+    vartype_T	    type1 = typ1->tt_type;
+    vartype_T	    type2 = typ2->tt_type;
     if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT
 				   || type1 == VAR_ANY || type1 == VAR_UNKNOWN)
 	    && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
 				 || type2 == VAR_ANY || type2 == VAR_UNKNOWN)))
     {
+	if (check_type_is_value(typ1) == FAIL
+		|| check_type_is_value(typ2) == FAIL)
+	    return FAIL;
 	if (*op == '+')
 	    emsg(_(e_wrong_argument_type_for_plus));
 	else
@@ -294,8 +299,7 @@ generate_add_instr(
 	    && type1->tt_type != VAR_UNKNOWN
 	    && type2->tt_type != VAR_ANY
 	    && type2->tt_type != VAR_UNKNOWN
-	    && check_number_or_float(
-			type1->tt_type, type2->tt_type, (char_u *)"+") == FAIL)
+	    && check_number_or_float(type1, type2, (char_u *)"+") == FAIL)
 	return FAIL;
 
     if (isn != NULL)
@@ -362,8 +366,7 @@ generate_two_op(cctx_T *cctx, char_u *op
 
 	case '-':
 	case '*':
-	case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
-								   op) == FAIL)
+	case '/': if (check_number_or_float(type1, type2, op) == FAIL)
 		      return FAIL;
 		  if (vartype == VAR_NUMBER)
 		      isn = generate_instr_drop(cctx, ISN_OPNR, 1);
@@ -409,6 +412,19 @@ generate_two_op(cctx_T *cctx, char_u *op
 }
 
 /*
+ * Choose correct error message for the specified type information.
+ */
+    static isntype_T
+compare_isn_not_values(typval_T *tv, type_T *type)
+{
+    if (tv != NULL)
+	check_typval_is_value(tv);
+    else
+	check_type_is_value(type);
+    return ISN_DROP;
+}
+
+/*
  * Get the instruction to use for comparing two values with specified types.
  * Either "tv1" and "tv2" are passed or "type1" and "type2".
  * Return ISN_DROP when failed.
@@ -425,6 +441,11 @@ get_compare_isn(
     vartype_T	vartype1 = tv1 != NULL ? tv1->v_type : type1->tt_type;
     vartype_T	vartype2 = tv2 != NULL ? tv2->v_type : type2->tt_type;
 
+    if (vartype1 == VAR_CLASS || vartype1 == VAR_TYPEALIAS)
+	return compare_isn_not_values(tv1, type1);
+    if (vartype2 == VAR_CLASS || vartype2 == VAR_TYPEALIAS)
+	return compare_isn_not_values(tv2, type2);
+
     if (vartype1 == vartype2)
     {
 	switch (vartype1)
@@ -438,7 +459,6 @@ get_compare_isn(
 	    case VAR_LIST: isntype = ISN_COMPARELIST; break;
 	    case VAR_DICT: isntype = ISN_COMPAREDICT; break;
 	    case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
-	    case VAR_CLASS: isntype = ISN_COMPARECLASS; break;
 	    case VAR_OBJECT: isntype = ISN_COMPAREOBJECT; break;
 	    default: isntype = ISN_COMPAREANY; break;
 	}
@@ -481,7 +501,7 @@ get_compare_isn(
     }
     if (!(exprtype == EXPR_IS || exprtype == EXPR_ISNOT
 		|| exprtype == EXPR_EQUAL || exprtype == EXPR_NEQUAL)
-	    && (isntype == ISN_COMPAREOBJECT || isntype == ISN_COMPARECLASS))
+	    && (isntype == ISN_COMPAREOBJECT))
     {
 	semsg(_(e_invalid_operation_for_str), vartype_name(vartype1));
 	return ISN_DROP;
@@ -2700,7 +2720,6 @@ delete_instr(isn_T *isn)
 	case ISN_COMPAREANY:
 	case ISN_COMPAREBLOB:
 	case ISN_COMPAREBOOL:
-	case ISN_COMPARECLASS:
 	case ISN_COMPAREDICT:
 	case ISN_COMPAREFLOAT:
 	case ISN_COMPAREFUNC:
--- a/src/vim9type.c
+++ b/src/vim9type.c
@@ -1871,7 +1871,10 @@ check_typval_is_value(typval_T *tv)
 	return OK;
     if (tv->v_type == VAR_CLASS)
     {
-        semsg(_(e_using_class_as_value_str), tv->vval.v_class->class_name);
+	if (tv->vval.v_class != NULL)
+	    semsg(_(e_using_class_as_value_str), tv->vval.v_class->class_name);
+	else
+	    emsg(e_using_class_as_var_val);
 	return FAIL;
     }
     else if (tv->v_type == VAR_TYPEALIAS)