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()
# " 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.![]()
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.![]()
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.![]()
Reported changed types are correct with
type()and this is guaranteed according to:help :letand: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.![]()