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:
committed by
Christian Brabandt
parent
d4e4ecbb37
commit
5c018bee0e
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user