mirror of
https://github.com/luau-lang/luau.git
synced 2024-11-15 14:25:44 +08:00
Merge branch 'master' into merge
This commit is contained in:
commit
092e70115e
@ -64,14 +64,14 @@ enum lua_Type
|
|||||||
LUA_TNIL = 0, /* must be 0 due to lua_isnoneornil */
|
LUA_TNIL = 0, /* must be 0 due to lua_isnoneornil */
|
||||||
LUA_TBOOLEAN = 1, /* must be 1 due to l_isfalse */
|
LUA_TBOOLEAN = 1, /* must be 1 due to l_isfalse */
|
||||||
|
|
||||||
|
|
||||||
LUA_TLIGHTUSERDATA,
|
LUA_TLIGHTUSERDATA,
|
||||||
LUA_TNUMBER,
|
LUA_TNUMBER,
|
||||||
LUA_TVECTOR,
|
LUA_TVECTOR,
|
||||||
|
|
||||||
LUA_TSTRING, /* all types above this must be value types, all types below this must be GC types - see iscollectable */
|
LUA_TSTRING, /* all types above this must be value types, all types below this must be GC types - see iscollectable */
|
||||||
|
|
||||||
|
|
||||||
LUA_TTABLE,
|
LUA_TTABLE,
|
||||||
LUA_TFUNCTION,
|
LUA_TFUNCTION,
|
||||||
LUA_TUSERDATA,
|
LUA_TUSERDATA,
|
||||||
@ -300,6 +300,7 @@ LUA_API uintptr_t lua_encodepointer(lua_State* L, uintptr_t p);
|
|||||||
|
|
||||||
LUA_API double lua_clock();
|
LUA_API double lua_clock();
|
||||||
|
|
||||||
|
LUA_API void lua_setuserdatatag(lua_State* L, int idx, int tag);
|
||||||
LUA_API void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(lua_State*, void*));
|
LUA_API void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(lua_State*, void*));
|
||||||
|
|
||||||
LUA_API void lua_clonefunction(lua_State* L, int idx);
|
LUA_API void lua_clonefunction(lua_State* L, int idx);
|
||||||
|
@ -1320,6 +1320,14 @@ void lua_unref(lua_State* L, int ref)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lua_setuserdatatag(lua_State* L, int idx, int tag)
|
||||||
|
{
|
||||||
|
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
|
||||||
|
StkId o = index2addr(L, idx);
|
||||||
|
api_check(L, ttisuserdata(o));
|
||||||
|
uvalue(o)->tag = uint8_t(tag);
|
||||||
|
}
|
||||||
|
|
||||||
void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(lua_State*, void*))
|
void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(lua_State*, void*))
|
||||||
{
|
{
|
||||||
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
|
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
|
||||||
|
@ -683,7 +683,7 @@ Perform a bitwise `and` of all input numbers, and return `true` iff the result i
|
|||||||
function bit32.extract(n: number, f: number, w: number?): number
|
function bit32.extract(n: number, f: number, w: number?): number
|
||||||
```
|
```
|
||||||
|
|
||||||
Extracts bits at positions `[f..w]` and returns the resulting integer. `w` defaults to `f+1`, so a two-argument version of `extract` returns the bit value at position `f`.
|
Extracts bits of `n` at position `f` with a width of `w`, and returns the resulting integer. `w` defaults to `1`, so a two-argument version of `extract` returns the bit value at position `f`. Bits are indexed starting at 0. Errors if `f` and `f+w-1` are not between 0 and 31.
|
||||||
|
|
||||||
```
|
```
|
||||||
function bit32.lrotate(n: number, i: number): number
|
function bit32.lrotate(n: number, i: number): number
|
||||||
@ -701,7 +701,7 @@ Shifts `n` to the left by `i` bits (if `i` is negative, a right shift is perform
|
|||||||
function bit32.replace(n: number, r: number, f: number, w: number?): number
|
function bit32.replace(n: number, r: number, f: number, w: number?): number
|
||||||
```
|
```
|
||||||
|
|
||||||
Replaces bits at positions `[f..w]` of number `n` with `r` and returns the resulting integer. `w` defaults to `f+1`, so a three-argument version of `replace` changes one bit at position `f` to `r` (which should be 0 or 1) and returns the result.
|
Replaces bits of `n` at position `f` and width `w` with `r`, and returns the resulting integer. `w` defaults to `1`, so a three-argument version of `replace` changes one bit at position `f` to `r` (which should be 0 or 1) and returns the result. Bits are indexed starting at 0. Errors if `f` and `f+w-1` are not between 0 and 31.
|
||||||
|
|
||||||
```
|
```
|
||||||
function bit32.rrotate(n: number, i: number): number
|
function bit32.rrotate(n: number, i: number): number
|
||||||
|
88
docs/_posts/2022-07-07-luau-recap-june-2022.md
Normal file
88
docs/_posts/2022-07-07-luau-recap-june-2022.md
Normal file
@ -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)
|
@ -1202,6 +1202,10 @@ TEST_CASE("UserdataApi")
|
|||||||
CHECK(lua_touserdatatagged(L, -1, 41) == nullptr);
|
CHECK(lua_touserdatatagged(L, -1, 41) == nullptr);
|
||||||
CHECK(lua_userdatatag(L, -1) == 42);
|
CHECK(lua_userdatatag(L, -1) == 42);
|
||||||
|
|
||||||
|
lua_setuserdatatag(L, -1, 43);
|
||||||
|
CHECK(lua_userdatatag(L, -1) == 43);
|
||||||
|
lua_setuserdatatag(L, -1, 42);
|
||||||
|
|
||||||
// user data with inline dtor
|
// user data with inline dtor
|
||||||
void* ud3 = lua_newuserdatadtor(L, 4, [](void* data) {
|
void* ud3 = lua_newuserdatadtor(L, 4, [](void* data) {
|
||||||
dtorhits += *(int*)data;
|
dtorhits += *(int*)data;
|
||||||
|
Loading…
Reference in New Issue
Block a user