From a934f742d81aefa53e8e45fa7eec0042d3fde7fc Mon Sep 17 00:00:00 2001 From: Andy Friesen Date: Mon, 11 Jul 2022 13:21:23 -0700 Subject: [PATCH] June recap (#583) --- .../_posts/2022-07-07-luau-recap-june-2022.md | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 docs/_posts/2022-07-07-luau-recap-june-2022.md diff --git a/docs/_posts/2022-07-07-luau-recap-june-2022.md b/docs/_posts/2022-07-07-luau-recap-june-2022.md new file mode 100644 index 0000000..1f58d89 --- /dev/null +++ b/docs/_posts/2022-07-07-luau-recap-june-2022.md @@ -0,0 +1,88 @@ +--- +layout: single +title: "Luau Recap: June 2022" +--- + +Luau is our new language that you can read more about at [https://luau-lang.org](https://luau-lang.org). + +[Cross-posted to the [Roblox Developer Forum](https://devforum.roblox.com/t/luau-recap-june-2022/).] + +# Lower bounds calculation + +A common problem that Luau has is that it primarily works by inspecting expressions in your program and narrowing the _upper bounds_ of the values that can inhabit particular variables. In other words, each time we see a variable used, we eliminate possible sets of values from that variable's domain. + +There are some important cases where this doesn't produce a helpful result. Take this function for instance: + +```lua +function find_first_if(vec, f) + for i, e in ipairs(vec) do + if f(e) then + return i + end + end + + return nil +end +``` + +Luau scans the function from top to bottom and first sees the line `return i`. It draws from this the inference that `find_first_if` must return the type of `i`, namely `number`. + +This is fine, but things go sour when we see the line `return nil`. Since we are always narrowing, we take from this line the judgement that the return type of the function is `nil`. Since we have already concluded that the function must return `number`, Luau reports an error. + +What we actually want to do in this case is to take these `return` statements as inferences about the _lower_ bound of the function's return type. Instead of saying "this function must return values of type `nil`," we should instead say "this function may _also_ return values of type `nil`." + +Lower bounds calculation does precisely this. Moving forward, Luau will instead infer the type `number?` for the above function. + +This does have one unfortunate consequence: If a function has no return type annotation, we will no longer ever report a type error on a `return` statement. We think this is the right balance but we'll be keeping an eye on things just to be sure. + +Lower-bounds calculation is larger and a little bit riskier than other things we've been working on so we've set up a beta feature in Roblox Studio to enable them. It is called "Experimental Luau language features." + +Please try it out and let us know what you think! + +## Known bug + +We have a known bug with certain kinds of cyclic types when lower-bounds calculation is enabled. The following, for instance, is known to be problematic. + +```lua +type T = {T?}? -- spuriously reduces to {nil}? +``` + +We hope to have this fixed soon. + +# All table literals now result in unsealed tables + +Previously, the only way to create a sealed table was by with a literal empty table. We have relaxed this somewhat: Any table created by a `{}` expression is considered to be unsealed within the scope where it was created: + +```lua +local T = {} +T.x = 5 -- OK + +local V = {x=5} +V.y = 2 -- previously disallowed. Now OK. + +function mkTable() + return {x = 5} +end + +local U = mkTable() +U.y = 2 -- Still disallowed: U is sealed +``` + +# Other fixes + +* Adjust indentation and whitespace when creating multiline string representations of types, resulting in types that are easier to read. +* Some small bugfixes to autocomplete +* Fix a case where accessing a nonexistent property of a table would not result in an error being reported. +* Improve parser recovery for the incorrect code `function foo() -> ReturnType` (the correct syntax is `function foo(): ReturnType`) +* Improve the parse error offered for code that improperly uses the `function` keyword to start a type eg `type T = function` +* Some small crash fixes and performance improvements + +# Thanks! + +A very special thanks to all of our open source contributors: + +* [Allan N Jeremy](https://github.com/AllanJeremy) +* [Daniel Nachun](https://github.com/danielnachun) +* [JohnnyMorganz](https://github.com/JohnnyMorganz/) +* [Petri Häkkinen](https://github.com/petrihakkinen) +* [Qualadore](https://github.com/Qualadore)