mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 9.1.0988: Vim9: no error when using uninitialized var in new()
Problem: Vim9: no error when using uninitialized var in new() (lifepillar, Aliaksei Budavei) Solution: Give an error if an uninitialized object variable is referenced in new() (Yegappan Lakshmanan) fixes: #14411 fixes: #16344 closes: #16374 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
27f2e473e1
commit
b04af4cc96
@@ -3616,8 +3616,10 @@ EXTERN char e_duplicate_enum_str[]
|
||||
INIT(= N_("E1428: Duplicate enum value: %s"));
|
||||
EXTERN char e_class_can_only_be_used_in_script[]
|
||||
INIT(= N_("E1429: Class can only be used in a script"));
|
||||
EXTERN char e_uninitialized_object_var_reference[]
|
||||
INIT(= N_("E1430: Uninitialized object variable '%s' referenced"));
|
||||
#endif
|
||||
// E1429 - E1499 unused (reserved for Vim9 class support)
|
||||
// E1431 - E1499 unused (reserved for Vim9 class support)
|
||||
EXTERN char e_cannot_mix_positional_and_non_positional_str[]
|
||||
INIT(= N_("E1500: Cannot mix positional and non-positional arguments: %s"));
|
||||
EXTERN char e_fmt_arg_nr_unused_str[]
|
||||
|
@@ -11723,4 +11723,120 @@ def Test_use_object_method_in_a_method_call()
|
||||
v9.CheckSourceFailure(lines, 'E1326: Variable "NewCost" not found in object "Foo"')
|
||||
enddef
|
||||
|
||||
" Test for referencing an object variable which is not yet initialized
|
||||
def Test_uninitialized_object_var()
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
class Foo
|
||||
const two: number = Foo.Two(this)
|
||||
const one: number = 1
|
||||
|
||||
static def Two(that: Foo): number
|
||||
return that.one + 2
|
||||
enddef
|
||||
endclass
|
||||
|
||||
echo Foo.Two(Foo.new())
|
||||
END
|
||||
v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'one' referenced")
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class Foo
|
||||
const one: number = Foo.One(this)
|
||||
|
||||
static def One(that: Foo): number
|
||||
return 1
|
||||
enddef
|
||||
endclass
|
||||
|
||||
assert_equal(1, Foo.One(Foo.new()))
|
||||
END
|
||||
v9.CheckSourceSuccess(lines)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class Foo
|
||||
const one: number = 1
|
||||
const two: number = Foo.Two(this)
|
||||
|
||||
static def Two(that: Foo): number
|
||||
return that.one + 1
|
||||
enddef
|
||||
endclass
|
||||
|
||||
assert_equal(2, Foo.Two(Foo.new()))
|
||||
END
|
||||
v9.CheckSourceSuccess(lines)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class Foo
|
||||
const Id: func(any): any = ((_) => (v) => v)(this)
|
||||
|
||||
static def Id(that: Foo): func(any): any
|
||||
return that.Id
|
||||
enddef
|
||||
endclass
|
||||
|
||||
assert_equal(5, Foo.Id(Foo.new())(5))
|
||||
assert_equal(7, Foo.new().Id(7))
|
||||
END
|
||||
v9.CheckSourceSuccess(lines)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class Foo
|
||||
const Id: func(any): any = ((that) => (_) => that)(this)
|
||||
|
||||
static def Id(that: Foo): func(any): any
|
||||
return that.Id
|
||||
enddef
|
||||
endclass
|
||||
|
||||
const Id0: func(any): any = Foo.Id(Foo.new())
|
||||
const Id1: func(any): any = Foo.new().Id
|
||||
END
|
||||
v9.CheckSourceSuccess(lines)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class Foo
|
||||
const Id: any = Foo.Id(this)
|
||||
|
||||
static def Id(that: Foo): any
|
||||
return that.Id
|
||||
enddef
|
||||
endclass
|
||||
|
||||
const Id2: any = Foo.Id(Foo.new())
|
||||
const Id3: any = Foo.new().Id
|
||||
END
|
||||
v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'Id' referenced")
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class Foo
|
||||
var x: string = ''
|
||||
var Y: func(): string = () => this.x
|
||||
endclass
|
||||
|
||||
var foo = Foo.new('ok')
|
||||
assert_equal('ok', foo.Y())
|
||||
END
|
||||
v9.CheckSourceSuccess(lines)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class Foo
|
||||
var x: string = this.x
|
||||
endclass
|
||||
|
||||
var foo = Foo.new('ok')
|
||||
END
|
||||
v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'x' referenced")
|
||||
enddef
|
||||
|
||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||
|
@@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
988,
|
||||
/**/
|
||||
987,
|
||||
/**/
|
||||
|
@@ -4844,6 +4844,20 @@ exec_instructions(ectx_T *ectx)
|
||||
int arg_set = tv->v_type != VAR_UNKNOWN
|
||||
&& !(tv->v_type == VAR_SPECIAL
|
||||
&& tv->vval.v_number == VVAL_NONE);
|
||||
|
||||
if (iptr->isn_type == ISN_JUMP_IF_ARG_NOT_SET && !arg_set)
|
||||
{
|
||||
dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
|
||||
+ ectx->ec_dfunc_idx;
|
||||
ufunc_T *ufunc = df->df_ufunc;
|
||||
// jump_arg_off is negative for arguments
|
||||
size_t argidx = ufunc->uf_def_args.ga_len
|
||||
+ iptr->isn_arg.jumparg.jump_arg_off
|
||||
+ STACK_FRAME_SIZE;
|
||||
type_T *t = ufunc->uf_arg_types[argidx];
|
||||
tv->v_type = t->tt_type;
|
||||
}
|
||||
|
||||
if (iptr->isn_type == ISN_JUMP_IF_ARG_SET ? arg_set : !arg_set)
|
||||
ectx->ec_iidx = iptr->isn_arg.jumparg.jump_where;
|
||||
break;
|
||||
@@ -5718,6 +5732,17 @@ exec_instructions(ectx_T *ectx)
|
||||
|
||||
// The members are located right after the object struct.
|
||||
typval_T *mtv = ((typval_T *)(obj + 1)) + idx;
|
||||
if (mtv->v_type == VAR_UNKNOWN)
|
||||
{
|
||||
// Referencing an object variable (without a type)
|
||||
// which is not yet initialized. So the type is not
|
||||
// yet known.
|
||||
ocmember_T *m = &obj->obj_class->class_obj_members[idx];
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
semsg(_(e_uninitialized_object_var_reference),
|
||||
m->ocm_name);
|
||||
goto on_error;
|
||||
}
|
||||
copy_tv(mtv, tv);
|
||||
|
||||
// Unreference the object after getting the member, it may
|
||||
|
Reference in New Issue
Block a user