From edd071f99a6537a00b98752f9c9902e6fb74871b Mon Sep 17 00:00:00 2001 From: vegorov-rbx <75688451+vegorov-rbx@users.noreply.github.com> Date: Wed, 1 Jun 2022 16:27:42 -0700 Subject: [PATCH] Luau Recap: May 2022 (#513) * Recap is ready * Change the intro format so it shows up in the news section snippet * Fixed line breaks that were implied * Update docs/_posts/2022-06-01-luau-recap-may-2022.md Co-authored-by: Arseny Kapoulkine * Drop Autocomplete improvements and extend compiler optimization section In the cross-post to Roblox developer forum, Autocomplete section will be restored, while compiler optimization section can be optionally removed (although it might interest some developers) * One more optimization * Update docs/_posts/2022-06-01-luau-recap-may-2022.md Co-authored-by: dcope-rbx <91100513+dcope-rbx@users.noreply.github.com> Co-authored-by: Arseny Kapoulkine Co-authored-by: dcope-rbx <91100513+dcope-rbx@users.noreply.github.com> --- docs/_posts/2022-06-01-luau-recap-may-2022.md | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 docs/_posts/2022-06-01-luau-recap-may-2022.md diff --git a/docs/_posts/2022-06-01-luau-recap-may-2022.md b/docs/_posts/2022-06-01-luau-recap-may-2022.md new file mode 100644 index 0000000..500e6e4 --- /dev/null +++ b/docs/_posts/2022-06-01-luau-recap-may-2022.md @@ -0,0 +1,97 @@ +--- +layout: single +title: "Luau Recap: May 2022" +--- + +This month Luau team has worked to bring you a new language feature together with more typechecking improvements and bugfixes! + +[Cross-posted to the [Roblox Developer Forum](https://devforum.roblox.com/t/luau-recap-may-2022/).] + +## Generalized iteration + +We have extended the semantics of standard Lua syntax for iterating through containers, `for vars in values` with support for generalized iteration. +In Lua, to iterate over a table you need to use an iterator like `next` or a function that returns one like `pairs` or `ipairs`. In Luau, you can now simply iterate over a table: + +```lua +for k, v in {1, 4, 9} do + assert(k * k == v) +end +``` + +This works for tables but can also be customized for tables or userdata by implementing `__iter` metamethod. It is called before the iteration begins, and should return an iterator function like `next` (or a custom one): + +```lua +local obj = { items = {1, 4, 9} } +setmetatable(obj, { __iter = function(o) return next, o.items end }) + +for k, v in obj do + assert(k * k == v) +end +``` + +The default iteration order for tables is specified to be consecutive for elements `1..#t` and unordered after that, visiting every element. +Similar to iteration using `pairs`, modifying the table entries for keys other than the current one results in unspecified behavior. + +## Typechecking improvements + +We have added a missing check to compare implicit table keys against the key type of the table indexer: + +```lua +-- error is correctly reported, implicit keys (1,2,3) are not compatible with [string] +local t: { [string]: boolean } = { true, true, false } +``` + +Rules for `==` and `~=` have been relaxed for union types, if any of the union parts can be compared, operation succeeds: + +```lua +--!strict +local function compare(v1: Vector3, v2: Vector3?) + return v1 == v2 -- no longer an error +end +``` + +Table value type propagation now correctly works with `[any]` key type: + +```lua +--!strict +type X = {[any]: string | boolean} +local x: X = { key = "str" } -- no longer gives an incorrect error +``` + +If a generic function doesn't provide type annotations for all arguments and the return value, additional generic type parameters might be added automatically: + +```lua +-- previously it was foo, now it's foo, because second argument is also generic +function foo(x: T, y) end +``` + +We have also fixed various issues that have caused crashes, with many of them coming from your bug reports. + +## Linter improvements + +`GlobalUsedAsLocal` lint warning has been extended to notice when global variable writes always happen before their use in a local scope, suggesting that they can be replaced with a local variable: + +```lua +function bar() + foo = 6 -- Global 'foo' is never read before being written. Consider changing it to local + return foo +end +function baz() + foo = 10 + return foo +end +``` + +## Performance improvements + +Garbage collection CPU utilization has been tuned to further reduce frame time spikes of individual collection steps and to bring different GC stages to the same level of CPU utilization. + +Returning a type-cast local (`return a :: type`) as well as returning multiple local variables (`return a, b, c`) is now a little bit more efficient. + +### Function inlining and loop unrolling + +In the open-source release of Luau, when optimization level 2 is enabled, the compiler will now perform function inlining and loop unrolling. + +Only loops with loop bounds known at compile time, such as `for i=1,4 do`, can be unrolled. The loop body must be simple enough for the optimization to be profitable; compiler uses heuristics to estimate the performance benefit and automatically decide if unrolling should be performed. + +Only local functions (defined either as `local function foo` or `local foo = function`) can be inlined. The function body must be simple enough for the optimization to be profitable; compiler uses heuristics to estimate the performance benefit and automatically decide if each call to the function should be inlined instead. Additionally recursive invocations of a function can't be inlined at this time, and inlining is completely disabled for modules that use `getfenv`/`setfenv` functions.