0
0
mirror of https://github.com/vim/vim.git synced 2025-09-27 04:14:06 -04:00

patch 9.0.1796: Vim9 problems with null_objects

Problem:  Vim9 problems with null_objects
Solution: Vim9 improve null_object usage

Fix "xvar == null", where xvar might have been assigned null_object.

Fix compilation failure: "var o2: C = null_object".

closes: #12890

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Ernie Rael <errael@raelity.com>
This commit is contained in:
Ernie Rael
2023-08-27 18:40:26 +02:00
committed by Christian Brabandt
parent d4e4ecbb37
commit 5c018bee0e
7 changed files with 54 additions and 4 deletions

View File

@@ -28,6 +28,7 @@ int generate_PUSHCHANNEL(cctx_T *cctx);
int generate_PUSHJOB(cctx_T *cctx); int generate_PUSHJOB(cctx_T *cctx);
int generate_PUSHBLOB(cctx_T *cctx, blob_T *blob); int generate_PUSHBLOB(cctx_T *cctx, blob_T *blob);
int generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type, int may_prefix); int generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type, int may_prefix);
int generate_PUSHOBJ(cctx_T *cctx);
int generate_AUTOLOAD(cctx_T *cctx, char_u *name, type_T *type); int generate_AUTOLOAD(cctx_T *cctx, char_u *name, type_T *type);
int generate_GETITEM(cctx_T *cctx, int index, int with_op); int generate_GETITEM(cctx_T *cctx, int index, int with_op);
int generate_SLICE(cctx_T *cctx, int count); int generate_SLICE(cctx_T *cctx, int count);

View File

@@ -337,7 +337,7 @@ def Test_object_not_set()
var bg: Background # UNINITIALIZED var bg: Background # UNINITIALIZED
echo Colorscheme.new(bg).GetBackground() echo Colorscheme.new(bg).GetBackground()
END END
v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Background> but got object<Unknown>') v9.CheckScriptFailure(lines, 'E1360:')
# TODO: this should not give an error but be handled at runtime # TODO: this should not give an error but be handled at runtime
lines =<< trim END lines =<< trim END
@@ -359,6 +359,46 @@ def Test_object_not_set()
v9.CheckScriptFailure(lines, 'E1363:') v9.CheckScriptFailure(lines, 'E1363:')
enddef enddef
def Test_null_object_assign_compare()
var lines =<< trim END
vim9script
var nullo = null_object
def F(): any
return nullo
enddef
assert_equal('object<Unknown>', typename(F()))
var o0 = F()
assert_true(o0 == null_object)
assert_true(o0 == null)
var o1: any = nullo
assert_true(o1 == null_object)
assert_true(o1 == null)
def G()
var x = null_object
enddef
class C
endclass
var o2: C
assert_true(o2 == null_object)
assert_true(o2 == null)
o2 = null_object
assert_true(o2 == null)
o2 = C.new()
assert_true(o2 != null)
o2 = null_object
assert_true(o2 == null)
END
v9.CheckScriptSuccess(lines)
enddef
def Test_class_member_initializer() def Test_class_member_initializer()
var lines =<< trim END var lines =<< trim END
vim9script vim9script

View File

@@ -1578,12 +1578,15 @@ typval_compare_null(typval_T *tv1, typval_T *tv2)
#ifdef FEAT_JOB_CHANNEL #ifdef FEAT_JOB_CHANNEL
case VAR_CHANNEL: return tv->vval.v_channel == NULL; case VAR_CHANNEL: return tv->vval.v_channel == NULL;
#endif #endif
// TODO: null_class handling
// case VAR_CLASS: return tv->vval.v_class == NULL;
case VAR_DICT: return tv->vval.v_dict == NULL; case VAR_DICT: return tv->vval.v_dict == NULL;
case VAR_FUNC: return tv->vval.v_string == NULL; case VAR_FUNC: return tv->vval.v_string == NULL;
#ifdef FEAT_JOB_CHANNEL #ifdef FEAT_JOB_CHANNEL
case VAR_JOB: return tv->vval.v_job == NULL; case VAR_JOB: return tv->vval.v_job == NULL;
#endif #endif
case VAR_LIST: return tv->vval.v_list == NULL; case VAR_LIST: return tv->vval.v_list == NULL;
case VAR_OBJECT: return tv->vval.v_object == NULL;
case VAR_PARTIAL: return tv->vval.v_partial == NULL; case VAR_PARTIAL: return tv->vval.v_partial == NULL;
case VAR_STRING: return tv->vval.v_string == NULL; case VAR_STRING: return tv->vval.v_string == NULL;

View File

@@ -699,6 +699,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1796,
/**/ /**/
1795, 1795,
/**/ /**/

View File

@@ -2299,6 +2299,9 @@ push_default_value(
case VAR_CHANNEL: case VAR_CHANNEL:
r = generate_PUSHCHANNEL(cctx); r = generate_PUSHCHANNEL(cctx);
break; break;
case VAR_OBJECT:
r = generate_PUSHOBJ(cctx);
break;
case VAR_NUMBER: case VAR_NUMBER:
case VAR_UNKNOWN: case VAR_UNKNOWN:
case VAR_ANY: case VAR_ANY:
@@ -2306,7 +2309,6 @@ push_default_value(
case VAR_VOID: case VAR_VOID:
case VAR_INSTR: case VAR_INSTR:
case VAR_CLASS: case VAR_CLASS:
case VAR_OBJECT:
case VAR_SPECIAL: // cannot happen case VAR_SPECIAL: // cannot happen
// This is skipped for local variables, they are always // This is skipped for local variables, they are always
// initialized to zero. But in a "for" or "while" loop // initialized to zero. But in a "for" or "while" loop

View File

@@ -662,11 +662,11 @@ generate_SETTYPE(
/* /*
* Generate an ISN_PUSHOBJ instruction. Object is always NULL. * Generate an ISN_PUSHOBJ instruction. Object is always NULL.
*/ */
static int int
generate_PUSHOBJ(cctx_T *cctx) generate_PUSHOBJ(cctx_T *cctx)
{ {
RETURN_OK_IF_SKIP(cctx); RETURN_OK_IF_SKIP(cctx);
if (generate_instr_type(cctx, ISN_PUSHOBJ, &t_any) == NULL) if (generate_instr_type(cctx, ISN_PUSHOBJ, &t_object) == NULL)
return FAIL; return FAIL;
return OK; return OK;
} }

View File

@@ -907,6 +907,8 @@ check_type_maybe(
return MAYBE; // use runtime type check return MAYBE; // use runtime type check
if (actual->tt_type != VAR_OBJECT) if (actual->tt_type != VAR_OBJECT)
return FAIL; // don't use tt_class return FAIL; // don't use tt_class
if (actual->tt_class == NULL)
return OK; // A null object matches
if (class_instance_of(actual->tt_class, expected->tt_class) == FALSE) if (class_instance_of(actual->tt_class, expected->tt_class) == FALSE)
ret = FAIL; ret = FAIL;