[vim/vim] Type safety issue with `legacy call map()` or `legacy let` breaking a Vim9 script variable's declared type (Issue #18531)

9 views
Skip to first unread message

Peter Kenny

unread,
Oct 9, 2025, 4:31:44 PM10/9/25
to vim/vim, Subscribed
kennypete created an issue (vim/vim#18531)

The following script shows a dict<number> allowing string values after a legacy call map(). It still reports as as dict<number>, despite containing strings. At the script level, legacy let can add an invalid type to the dictionary too:

vim9script

echo "---- myDict is type dict<number> ----"
var myDict: dict<number> = {'one': 1, 'two': 2}
echo myDict
echo myDict->typename()

echo "\n---- myDict containing strings ----"

def BreakMyDict()
    legacy call map(s:myDict, {i -> $"item {i}"})
enddef
BreakMyDict()
echo $"myDict is now {myDict}"
echo myDict->typename()
echo myDict['one']->typename()
echo myDict['two']->typename()

echo "\n---- myDict containing any ----"

legacy let s:myDict['two'] = (2, )
echo $"myDict is now {myDict}"
echo myDict->typename()
echo myDict['one']->typename()
echo myDict['two']->typename()
image.png (view on web)
# " This undermines Vim9 script's type safety guarantees.
# " Code relying on declared types fails unexpectedly.
# " Since `typename()` reports incorrect information, even runtime
# " type checking does not detect the type mismatch
# " E.g., Later in code, presuming dict<number> is safe ...
if myDict->typename() == 'dict<number>'
  # " Yes, sure is ...
  try
    var mySum: number = myDict['one'] + 1 
  catch
    echo v:exception
    # " E1030: Using String as a Number
  endtry
  try
    var mySum: number = 1 + myDict['two']
  catch
    echo v:exception
    # " E1520: Using Tuple as a Number
  endtry
endif

Version 9.1 w/ 1833


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/18531@github.com>

Peter Kenny

unread,
Jan 24, 2026, 1:01:22 PM (23 hours ago) Jan 24
to vim/vim, Subscribed
kennypete left a comment (vim/vim#18531)

Hi @chrisbra - Could this have a vim9script label added? It has been dormant since I found it during vim9.txt rewrite testing. Although it's unlikely to occur given (presumed) low use of legacy in Vim9 script, allowing it to corrupt the type of a strictly typed variable, while typename() reports the originally declared type incorrectly, makes runtime type checking ineffective and breaks Vim9 script's strict type system's benefits. Thanks


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/18531/3795278834@github.com>

Aliaksei Budavei

unread,
Jan 24, 2026, 7:43:49 PM (16 hours ago) Jan 24
to vim/vim, Subscribed
zzzyxwvut left a comment (vim/vim#18531)

Reported changed types are correct with type() and this
is guaranteed according to :help :let and :help map().

Maybe typename() needs looking into.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/18531/3795765854@github.com>

Peter Kenny

unread,
Jan 24, 2026, 8:32:57 PM (15 hours ago) Jan 24
to vim/vim, Subscribed
kennypete left a comment (vim/vim#18531)

Reported changed types are correct with type() and this is guaranteed according to :help :let and :help map().

Thanks @zzzyxwvut. In principle, though, shouldn't a Vim9 script prioritise strict typing guaranteed by Vim9 script? Of course, if it's a massive fix, maybe the second best option, fixing typename(), would be pragmatic (given the use of legacy in Vim9 script is not common, and there is an argument for allowing an overt legacy-driven change, the current behaviour, though I'd add it as a warning in my next vim9.txt PR).

Maybe typename() needs looking into.

Yes, if this (IMO) second best option is advanced, allowing legacy let, etc., to change types, it should return correct type names.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/18531/3795806405@github.com>

Reply all
Reply to author
Forward
0 new messages