vim / vim

The official Vim repository
https://www.vim.org
Vim License
36.62k stars 5.46k forks source link

Vim9: inconsistent type checking with map() between script-level and :def function #9665

Closed lacygoill closed 2 years ago

lacygoill commented 2 years ago

Steps to reproduce

Run this shell command:

vim -Nu NONE -S <(tee <<'EOF'
    vim9script
    echo range(3)->map((_, _) => 'x')
EOF
)

This is echo'ed:

['x', 'x', 'x']

Run this other shell command:

vim -Nu NONE -S <(tee <<'EOF'
    vim9script
    def Func()
        echo range(3)->map((_, _) => 'x')
    enddef
    defcompile
EOF
)

An error is given:

E1013: Argument 2: type mismatch, expected func(...): number but got func(any, any): string

Expected behavior

Not sure, but the current situation is inconsistent. Either the second shell command should not give any error. Or the first one should give a type mismatch error, like the second one.

I would prefer no error in both commands; but I suspect that – the way type checking is intended to work – an error should always be given. Because internally, the return type of range() is probably list<number>, that type is attached to the output (here range(3)), and map() cannot change the type of a value whose type is declared. Although, here, we did not declare list<number> anywhere (but Vim did it internally).

Version of Vim

8.2 Included patches: 1-4264

Environment

Operating system: Ubuntu 20.04.3 LTS Terminal: xterm Value of $TERM: xterm-256color Shell: zsh 5.8

brammool commented 2 years ago

There is no obvious right choice. If we follow recent changes, then type checking for map() should be strict for declared types (a variable must not change type) and permissive for constant values. The result of range() is not a constant, it's not declared either. Giving an error here does not appear useful, thus I tend to go for the permissive way.