New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix edge cases for NULL typval_T Lists #4615
Comments
To check the above I used local helpers = require('test.functional.helpers')
local exc_exec = helpers.exc_exec
local command = helpers.command
local clear = helpers.clear
local meths = helpers.meths
local eq = helpers.eq
describe('NULL', function()
before_each(function()
clear()
command('let L = v:_null_list')
command('let D = v:_null_dict')
command('let S = $XXX_NONEXISTENT_VAR_XXX')
end)
describe('list', function()
local null_list_test = function(name, cmd, err)
it(name, function()
eq(err, exc_exec(cmd))
end)
end
local null_list_expr_test = function(name, expr, err, val)
it(name, function()
eq((err == 0) and err or ('Vim(let):' .. err),
exc_exec('let g:_var = ' .. expr))
eq(val, meths.set_var('_var', NIL))
meths.del_var('_var')
end)
end
-- FIXME map() should not return 0 without error
null_list_expr_test('does not crash map()', 'map(L, "v:val")', 0, 0)
-- FIXME map() should not return 0 without error
null_list_expr_test('does not crash filter()', 'filter(L, "1")', 0, 0)
-- FIXME map() should at least return L
null_list_expr_test('makes map() return v:_null_list', 'map(L, "v:val") is# L', 0, 0)
-- FIXME filter() should at least return L
null_list_expr_test('makes filter() return v:_null_list', 'map(L, "1") is# L', 0, 0)
-- FIXME add() should not return 1 at all
null_list_expr_test('does not crash add()', 'add(L, 0)', 0, 1)
-- FIXME extend() should not return 0 without error
null_list_expr_test('does not crash extend()', 'extend(L, [1])', 0, 0)
-- FIXME extend() should not return 0 at all
null_list_expr_test('does not crash extend() (second position)', 'extend([1], L)', 0, 0)
-- FIXME Crashes
-- null_list_expr_test('does not crash setreg', 'setreg("x", L)', 0, 0)
null_list_expr_test('does not crash append()', 'append(1, L)', 0, 0)
-- FIXME Crashes
-- null_list_expr_test('does not crash setline', 'setline(1, L)', 0, 0)
-- FIXME Should return 1
null_list_expr_test('is equal to itself', 'L == L', 0, 0)
null_list_expr_test('is not not equal to itself', 'L != L', 0, 1)
null_list_expr_test('is identical to itself', 'L is L', 0, 1)
-- FIXME Should return 1
null_list_expr_test('is equal to empty list', 'L == []', 0, 0)
-- FIXME Should return 1
null_list_expr_test('is equal to empty list (reverse order)', '[] == L', 0, 0)
-- FIXME?
null_list_expr_test('is not locked', 'islocked("v:_null_list")', 0, 0)
-- FIXME Should return empty list
null_list_expr_test('can be added to itself', '(L + L)', 'E15: Invalid expression: (L + L)', NIL)
-- FIXME Should return [1]
null_list_expr_test('can be added to non-empty list', '(L + [1])',
'E15: Invalid expression: (L + [1])', NIL)
-- FIXME Should return [1]
null_list_expr_test('can be added to non-empty list (reversed)', '([1] + L)',
'E15: Invalid expression: ([1] + L)', NIL)
null_list_expr_test('can be sliced', 'L[:]', 0, {})
null_list_expr_test('can be copied', 'copy(L)', 0, {})
null_list_expr_test('can be deepcopied', 'deepcopy(L)', 0, {})
null_list_expr_test('does not crash when indexed', 'L[1]', 'E684: list index out of range: 1', NIL)
null_list_expr_test('does not crash call()', 'call("arglistid", L)', 0, 0)
null_list_expr_test('does not crash col()', 'col(L)', 0, 0)
null_list_expr_test('does not crash virtcol()', 'virtcol(L)', 0, 0)
null_list_expr_test('does not crash line()', 'line(L)', 0, 0)
null_list_expr_test('does not crash count()', 'count(L, 1)', 0, 0)
-- FIXME Should return 1
null_list_expr_test('counts correctly', 'count([L], L)', 0, 0)
null_list_expr_test('does not crash cursor()', 'cursor(L)', 0, -1)
null_list_expr_test('is empty', 'empty(L)', 0, 1)
null_list_expr_test('does not crash get()', 'get(L, 1, 10)', 0, 10)
-- FIXME should be accepted by inputlist()
null_list_expr_test('is accepted as an empty list by inputlist()',
'[feedkeys("\\n"), inputlist(L)]', 'E686: Argument of inputlist() must be a List', NIL)
null_list_expr_test('has zero length', 'len(L)', 0, 0)
null_list_expr_test('is accepted as an empty list by max()', 'max(L)', 0, 0)
null_list_expr_test('is accepted as an empty list by min()', 'min(L)', 0, 0)
describe('', function()
local tmpfname = 'Xtest-functional-viml-null'
after_each(function()
os.remove(tmpfname)
end)
-- FIXME should be accepted by writefile(), return {0, {}}
null_list_expr_test('is accepted as an empty list by writefile()',
('[writefile(L, "%s"), readfile("%s")]'):format(tmpfname, tmpfname), 'E484: Can\'t open file ' .. tmpfname, NIL)
end)
-- FIXME should give error message
null_list_expr_test('does not crash remove()', 'remove(L, 0)', 0, 0)
-- FIXME should return 0
null_list_expr_test('is accepted by setqflist()', 'setqflist(L)', 0, -1)
-- FIXME should return 0
null_list_expr_test('is accepted by setloclist()', 'setloclist(1, L)', 0, -1)
-- FIXME should return 0
null_list_expr_test('is accepted by setmatches()', 'setmatches(L)', 0, -1)
-- FIXME should return empty list or error out
null_list_expr_test('is accepted by sort()', 'sort(L)', 0, 0)
null_list_expr_test('is accepted by sort()', 'sort(L) is L', 0, 0)
null_list_expr_test('is stringified correctly', 'string(L)', 0, '[]')
null_list_expr_test('is JSON encoded correctly', 'json_encode(L)', 0, '[]')
-- FIXME crashes
-- null_list_expr_test('does not crash system()', 'system("cat", L)', 0, '')
-- FIXME crashes
-- null_list_expr_test('does not crash systemlist()', 'systemlist("cat", L)', 0, {})
-- FIXME should not error out
null_list_test('is accepted by :cexpr', 'cexpr L', 'Vim(cexpr):E777: String or List expected')
-- FIXME should not error out
null_list_test('is accepted by :lexpr', 'lexpr L', 'Vim(lexpr):E777: String or List expected')
-- FIXME should not error out
null_list_test('is accepted by :for', 'for x in L|throw x|endfor', 'Vim(for):E714: List required')
end)
end) placed in test/functional/viml/null_spec.lua. |
Update: |
Update: indexing v:_null_dict. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Also found some bugs: 1. var_item_copy() always fails to copy v:_null_list and v:_null_dict. Fixing this should mean fixing `deepcopy(v:_null_list)` which should’ve been, but was not listed in neovim#4615. This also fixes `deepcopy(v:_null_dict)`. 2. var_item_copy() crashes when trying to copy NULL string with `conv != NULL`. 3. `conv` argument is ignored when copying list unless `deep` is true, but it was not reflected in documentation. 4. `tv_dict_item_alloc_len()` allocated more memory then needed. 5. typvalt2lua was not able to handle self-referencing containers.
Also found some bugs: 1. var_item_copy() always fails to copy v:_null_list and v:_null_dict. Fixing this should mean fixing `deepcopy(v:_null_list)` which should’ve been, but was not listed in neovim#4615. This also fixes `deepcopy(v:_null_dict)`. 2. var_item_copy() crashes when trying to copy NULL string with `conv != NULL`. 3. `conv` argument is ignored when copying list unless `deep` is true, but it was not reflected in documentation. 4. `tv_dict_item_alloc_len()` allocated more memory then needed. 5. typvalt2lua was not able to handle self-referencing containers.
For now it is full of FIXMEs and tests for incorrect behaviour. Sorted out to have FIXMEs in one place, commented crashing tests in other and correctly working tests in the third one.
Also found some bugs: 1. var_item_copy() always fails to copy v:_null_list and v:_null_dict. Fixing this should mean fixing `deepcopy(v:_null_list)` which should’ve been, but was not listed in neovim#4615. This also fixes `deepcopy(v:_null_dict)`. 2. var_item_copy() crashes when trying to copy NULL string with `conv != NULL`. 3. `conv` argument is ignored when copying list unless `deep` is true, but it was not reflected in documentation. 4. `tv_dict_item_alloc_len()` allocated more memory then needed. 5. typvalt2lua was not able to handle self-referencing containers.
For now it is full of FIXMEs and tests for incorrect behaviour. Sorted out to have FIXMEs in one place, commented crashing tests in other and correctly working tests in the third one.
Also found some bugs: 1. var_item_copy() always fails to copy v:_null_list and v:_null_dict. Fixing this should mean fixing `deepcopy(v:_null_list)` which should’ve been, but was not listed in neovim#4615. This also fixes `deepcopy(v:_null_dict)`. 2. var_item_copy() crashes when trying to copy NULL string with `conv != NULL`. 3. `conv` argument is ignored when copying list unless `deep` is true, but it was not reflected in documentation. 4. `tv_dict_item_alloc_len()` allocated more memory then needed. 5. typvalt2lua was not able to handle self-referencing containers.
For now it is full of FIXMEs and tests for incorrect behaviour. Sorted out to have FIXMEs in one place, commented crashing tests in other and correctly working tests in the third one.
Also found some bugs: 1. var_item_copy() always fails to copy v:_null_list and v:_null_dict. Fixing this should mean fixing `deepcopy(v:_null_list)` which should’ve been, but was not listed in neovim#4615. This also fixes `deepcopy(v:_null_dict)`. 2. var_item_copy() crashes when trying to copy NULL string with `conv != NULL`. 3. `conv` argument is ignored when copying list unless `deep` is true, but it was not reflected in documentation. 4. `tv_dict_item_alloc_len()` allocated more memory then needed. 5. typvalt2lua was not able to handle self-referencing containers.
For now it is full of FIXMEs and tests for incorrect behaviour. Sorted out to have FIXMEs in one place, commented crashing tests in other and correctly working tests in the third one.
Also found some bugs: 1. var_item_copy() always fails to copy v:_null_list and v:_null_dict. Fixing this should mean fixing `deepcopy(v:_null_list)` which should’ve been, but was not listed in neovim#4615. This also fixes `deepcopy(v:_null_dict)`. 2. var_item_copy() crashes when trying to copy NULL string with `conv != NULL`. 3. `conv` argument is ignored when copying list unless `deep` is true, but it was not reflected in documentation. 4. `tv_dict_item_alloc_len()` allocated more memory then needed. 5. typvalt2lua was not able to handle self-referencing containers.
For now it is full of FIXMEs and tests for incorrect behaviour. Sorted out to have FIXMEs in one place, commented crashing tests in other and correctly working tests in the third one.
Also found some bugs: 1. var_item_copy() always fails to copy v:_null_list and v:_null_dict. Fixing this should mean fixing `deepcopy(v:_null_list)` which should’ve been, but was not listed in neovim#4615. This also fixes `deepcopy(v:_null_dict)`. 2. var_item_copy() crashes when trying to copy NULL string with `conv != NULL`. 3. `conv` argument is ignored when copying list unless `deep` is true, but it was not reflected in documentation. 4. `tv_dict_item_alloc_len()` allocated more memory then needed. 5. typvalt2lua was not able to handle self-referencing containers.
For now it is full of FIXMEs and tests for incorrect behaviour. Sorted out to have FIXMEs in one place, commented crashing tests in other and correctly working tests in the third one.
Also found some bugs: 1. var_item_copy() always fails to copy v:_null_list and v:_null_dict. Fixing this should mean fixing `deepcopy(v:_null_list)` which should’ve been, but was not listed in neovim#4615. This also fixes `deepcopy(v:_null_dict)`. 2. var_item_copy() crashes when trying to copy NULL string with `conv != NULL`. 3. `conv` argument is ignored when copying list unless `deep` is true, but it was not reflected in documentation. 4. `tv_dict_item_alloc_len()` allocated more memory then needed. 5. typvalt2lua was not able to handle self-referencing containers.
For now it is full of FIXMEs and tests for incorrect behaviour. Sorted out to have FIXMEs in one place, commented crashing tests in other and correctly working tests in the third one.
Also found some bugs: 1. var_item_copy() always fails to copy v:_null_list and v:_null_dict. Fixing this should mean fixing `deepcopy(v:_null_list)` which should’ve been, but was not listed in neovim#4615. This also fixes `deepcopy(v:_null_dict)`. 2. var_item_copy() crashes when trying to copy NULL string with `conv != NULL`. 3. `conv` argument is ignored when copying list unless `deep` is true, but it was not reflected in documentation. 4. `tv_dict_item_alloc_len()` allocated more memory then needed. 5. typvalt2lua was not able to handle self-referencing containers.
For now it is full of FIXMEs and tests for incorrect behaviour. Sorted out to have FIXMEs in one place, commented crashing tests in other and correctly working tests in the third one.
Also found some bugs: 1. var_item_copy() always fails to copy v:_null_list and v:_null_dict. Fixing this should mean fixing `deepcopy(v:_null_list)` which should’ve been, but was not listed in neovim#4615. This also fixes `deepcopy(v:_null_dict)`. 2. var_item_copy() crashes when trying to copy NULL string with `conv != NULL`. 3. `conv` argument is ignored when copying list unless `deep` is true, but it was not reflected in documentation. 4. `tv_dict_item_alloc_len()` allocated more memory then needed. 5. typvalt2lua was not able to handle self-referencing containers.
For now it is full of FIXMEs and tests for incorrect behaviour. Sorted out to have FIXMEs in one place, commented crashing tests in other and correctly working tests in the third one.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
About setreg: “already reported” suggests that it could’ve been fixed in Vim and fix was backported. Though null_spec.lua still needs to be updated. |
Good point. I'll fix the test in the pull request above, referencing the commit and issue you found. |
Happened to find another error: |
I am currently in process of refactoring the code base to abstract away list implementation (not created a PR yet, but will do soon). So I am removing label |
|
And |
|
This doesn't seem to happen anymore, |
List issues were fixed, but you surely do not see a list of dictionary and string issues here, that requires some investigation (or the issue could be renamed to mention only lists and closed). Note that my previous change of title removed mention of lists. |
Problem: List test doesn't fail. Solution: Adjust the test for NULL list handling. vim/vim@f574972 Cherry-pick Test_null_list() from patch 8.2.0610. Partial revert of commit 274f32d because it removed "NULL" checks. neovim#4615 vim/vim#768 ZyX-I@fa852e7
Problem: List test doesn't fail. Solution: Adjust the test for NULL list handling. vim/vim@f574972 Comment out test cases that modify null lists because Neovim throws error messages instead of silently failing. Null lists should be read-only and constant. neovim#4615 Add v:_null_string to test split() with null strings.
Problem: List test doesn't fail. Solution: Adjust the test for NULL list handling. vim/vim@f574972 Comment out test cases that modify null lists because Neovim throws error messages instead of silently failing. Null lists should be read-only and constant. neovim#4615
Problem: List test doesn't fail. Solution: Adjust the test for NULL list handling. vim/vim@f574972 Comment out test cases that modify null lists because Neovim throws error messages instead of silently failing. Null lists should be read-only and constant. neovim#4615
…blob Problem: Add() silently skips when adding to null list or blob. Solution: Give an error in Vim9 script. Allocate blob when it is NULL like with list and dict. vim/vim@b7c21af Do not implicitly change a NULL blob/dict/list to an empty one. N/A patches for version.c: vim-patch:8.2.1949: Vim9: using extend() on null dict is silently ignored Problem: Vim9: using extend() on null dict is silently ignored. Solution: Give an error message. Initialize a dict variable with an empty dictionary. (closes vim/vim#7251) vim/vim@348be7e N/A because Nvim's current behavior is an error message as a locked list/dict, which is more consistent. Ref neovim#4615. Co-authored-by: Bram Moolenaar <Bram@vim.org>
vim-patch:8.2.2781: add() silently skips when adding to null list or blob Problem: Add() silently skips when adding to null list or blob. Solution: Give an error in Vim9 script. Allocate blob when it is NULL like with list and dict. vim/vim@b7c21af Do not implicitly change a NULL blob/dict/list to an empty one. N/A patches for version.c: vim-patch:8.2.1949: Vim9: using extend() on null dict is silently ignored Problem: Vim9: using extend() on null dict is silently ignored. Solution: Give an error message. Initialize a dict variable with an empty dictionary. (closes vim/vim#7251) vim/vim@348be7e N/A because Nvim's current behavior is an error message as a locked list/dict, which is more consistent. Ref #4615. Co-authored-by: Bram Moolenaar <Bram@vim.org>
vim-patch:8.2.2781: add() silently skips when adding to null list or blob Problem: Add() silently skips when adding to null list or blob. Solution: Give an error in Vim9 script. Allocate blob when it is NULL like with list and dict. vim/vim@b7c21af Do not implicitly change a NULL blob/dict/list to an empty one. N/A patches for version.c: vim-patch:8.2.1949: Vim9: using extend() on null dict is silently ignored Problem: Vim9: using extend() on null dict is silently ignored. Solution: Give an error message. Initialize a dict variable with an empty dictionary. (closes vim/vim#7251) vim/vim@348be7e N/A because Nvim's current behavior is an error message as a locked list/dict, which is more consistent. Ref neovim#4615. Co-authored-by: Bram Moolenaar <Bram@vim.org>
vim-patch:8.2.2781: add() silently skips when adding to null list or blob Problem: Add() silently skips when adding to null list or blob. Solution: Give an error in Vim9 script. Allocate blob when it is NULL like with list and dict. vim/vim@b7c21af Do not implicitly change a NULL blob/dict/list to an empty one. N/A patches for version.c: vim-patch:8.2.1949: Vim9: using extend() on null dict is silently ignored Problem: Vim9: using extend() on null dict is silently ignored. Solution: Give an error message. Initialize a dict variable with an empty dictionary. (closes vim/vim#7251) vim/vim@348be7e N/A because Nvim's current behavior is an error message as a locked list/dict, which is more consistent. Ref neovim#4615. Co-authored-by: Bram Moolenaar <Bram@vim.org>
See vim/vim#768, later there will probably be more issues. Current list of known issues:
map(v:_null_list, 'v:val')
returns 0. It should return v:_null_list. ([RDY] Add curdir as a default viewoption (vim-patch:8.0.128) #7447)filter(v:_null_list, 'v:val')
returns 0. It should return v:_null_list. ([RDY] Add curdir as a default viewoption (vim-patch:8.0.128) #7447)add(v:_null_list, 1)
returns 1, it should fail. Though with locked list it returns 1 as well, so probably it should fail and return 1. (Viml: null list, add() and setline() #7695, [RFC] Hide list implementation #7708)extend(v:_null_list, [])
returns 0, it should fail. Again locked list returns 0 and fails. ([RFC] eval: Refactor eval.c #5119)setreg('x', v:_null_list)
crashes. Already reported. ([RFC] vim-patch:7.4.1847 #5835)setline(1, v:_null_list)
crashes.append()
is fine. ([RFC] Hide list implementation #7708)v:_null_list == v:_null_list
returns 0. NULL list is not equal to itself!is
operator works as expected. ([RFC] eval: Refactor eval.c #5119)v:_null_list == []
: returns 0, should return 1. (Considered to be not a bug.)islocked('v:_null_list')
does not crash. Though it does not return 1. I am not sure whether this needs to be fixed because e.g.islocked('v:throwpoint')
is also zero (as it is VAR_FIXED and not VAR_LOCKED).v:_null_list + any_other_list
isE15: Invalid expression
, as well asany_other_list + v:_null_list
. Sincelist + list
produces a new list it should work like[] + any_other_list
. ([RFC] eval: Refactor eval.c #5119)count([v:_null_list], v:_null_list)
returns 0 in place of 1. Guess same problem as with==
. ([RFC] eval: Refactor eval.c #5119)extend([1], v:_null_list)
returns 0 in place of returning[1]
. ([RFC] eval: Refactor eval.c #5119)inputlist(v:_null_list)
treats this as non-list. ([RFC] Hide list implementation #7708)writefile(v:_null_list, "/tmp/test.fname")
returns 0, but does not actually do anything, with empty list it creates empty file (and returns 0). ([RFC] Hide list implementation #7708)remove(v:_null_list, 0)
returns 0 in place of E684. ([RFC] Hide list implementation #7708)setqflist(v:_null_list)
returns -1 (and I guess, does nothing with quickfix list), same forsetloclist(1, v:_null_list)
. For empty list it returns 0. ([RFC] Hide list implementation #7708)setmatches(v:_null_list)
also returns -1 in place of 0 like with empty list. ([RFC] Hide list implementation #7708)sort(v:_null_list)
returns 0 in place of v:_null_list, yet does not error out. ([RFC] Hide list implementation #7708)string(v:_null_list)
returns empty string in place of[]
. Neovim behaves correctly here.json_encode(v:_null_list)
encodes empty list asnull
, same forjs_encode()
. Neovim uses[]
in first case and does not havejs_encode()
.system("cat", v:_null_list)
crashes, as well assystemlist()
. ([RFC] Hide list implementation #7708)for x in v:_null_list
does not work as well, it thinks:for
is given a non-list.cexpr v:_null_list
thinks it was given a non-list in place of empty list. ([RFC] Hide list implementation #7708)deepcopy(v:_null_list)
returns an empty string without any errors. ([RFC] eval: Refactor eval.c #5119)insert(v:_null_list, 1)
does not report an error. ([RFC] Hide list implementation #7708)rpcstart(, v:_null_list)
should not crash. ([RFC] Hide list implementation #7708)join(v:_null_list, "")
should return empty string likejoin([], "")
. ([RFC] Hide list implementation #7708)msgpackdump(v:_null_list)
should treat list like empty. ([RFC] Hide list implementation #7708)dictwatcher*(v:_null_dict, …)
crashes. ([RFC] eval: Refactor eval.c #5119)This is missing most tests with
v:_null_dict
and$XXX_NONEXISTENT_VAR_XXX
.Marking this as
entry-level
because fixes in most cases should be simple and straightforward.The text was updated successfully, but these errors were encountered: