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>
diff --git a/src/eval.c b/src/eval.c
index 6f88e03..8563aa6 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1890,10 +1890,8 @@
 	    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 @@
     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 @@
 	    case VAR_JOB:
 	    case VAR_CHANNEL:
 	    case VAR_INSTR:
-	    case VAR_CLASS:
 	    case VAR_OBJECT:
-	    case VAR_TYPEALIAS:
 		break;
+	    case VAR_CLASS:
+	    case VAR_TYPEALIAS:
+		check_typval_is_value(tv1);
+		return FAIL;
 
 	    case VAR_BLOB:
 		if (*op != '+' || tv2->v_type != VAR_BLOB)
@@ -2142,7 +2143,8 @@
 	}
     }
 
-    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,12 +5021,15 @@
 	case VAR_JOB:
 	case VAR_CHANNEL:
 	case VAR_INSTR:
-	case VAR_CLASS:
 	case VAR_OBJECT:
-	case VAR_TYPEALIAS:
 	    if (verbose)
 		emsg(_(e_cannot_index_special_variable));
 	    return FAIL;
+	case VAR_CLASS:
+	case VAR_TYPEALIAS:
+	    if (verbose)
+		check_typval_is_value(rettv);
+	    return FAIL;
 	case VAR_UNKNOWN:
 	case VAR_ANY:
 	case VAR_VOID:
diff --git a/src/evalvars.c b/src/evalvars.c
index 64455f0..ea039cb 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -3974,12 +3974,8 @@
 		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)
 	    {
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index f904696..aef09c5 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -3090,18 +3090,18 @@
     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 @@
     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)
 
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index e2c61b0..b34d2ad 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -242,7 +242,7 @@
     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 @@
     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
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index 4e81122..1a192cc 100644
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -3193,7 +3193,7 @@
   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 @@
     class B
     endclass
     def Foo(a: A, b: B)
-      if A == B
-      endif
       if a == b
       endif
     enddef
@@ -3211,19 +3209,13 @@
   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
 
diff --git a/src/testdir/test_vim9_typealias.vim b/src/testdir/test_vim9_typealias.vim
index 4f88768..4155744 100644
--- a/src/testdir/test_vim9_typealias.vim
+++ b/src/testdir/test_vim9_typealias.vim
@@ -18,7 +18,7 @@
     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 @@
       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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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
diff --git a/src/typval.c b/src/typval.c
index 65cd912..35c9e24 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -262,7 +262,8 @@
 	    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 @@
 	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 @@
 	    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 @@
 	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 @@
 	    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 @@
 	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 @@
     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 @@
 	}
 	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)
diff --git a/src/version.c b/src/version.c
index ec2d0e2..396a163 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2184,
+/**/
     2183,
 /**/
     2182,
diff --git a/src/vim9.h b/src/vim9.h
index 63aec46..dd5ad73 100644
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -168,7 +168,6 @@
     ISN_COMPAREDICT,
     ISN_COMPAREFUNC,
     ISN_COMPAREANY,
-    ISN_COMPARECLASS,
     ISN_COMPAREOBJECT,
 
     // expression operations
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 868acb4..ad1f6b4 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -550,6 +550,12 @@
 {
     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))
     {
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 3bcdce4..1efed35 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -5034,7 +5034,6 @@
 	    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 @@
 		    {
 			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 @@
 	    case ISN_COMPARELIST:
 	    case ISN_COMPAREDICT:
 	    case ISN_COMPAREFUNC:
-	    case ISN_COMPARECLASS:
 	    case ISN_COMPAREOBJECT:
 	    case ISN_COMPAREANY:
 		   {
@@ -7245,7 +7238,6 @@
 			   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;
diff --git a/src/vim9instr.c b/src/vim9instr.c
index b7cad76..5059eb0 100644
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -255,13 +255,18 @@
 }
 
     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 @@
 	    && 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 @@
 
 	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 @@
 }
 
 /*
+ * 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 @@
     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 @@
 	    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 @@
     }
     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 @@
 	case ISN_COMPAREANY:
 	case ISN_COMPAREBLOB:
 	case ISN_COMPAREBOOL:
-	case ISN_COMPARECLASS:
 	case ISN_COMPAREDICT:
 	case ISN_COMPAREFLOAT:
 	case ISN_COMPAREFUNC:
diff --git a/src/vim9type.c b/src/vim9type.c
index 423043a..0d004c8 100644
--- a/src/vim9type.c
+++ b/src/vim9type.c
@@ -1871,7 +1871,10 @@
 	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)