Merge branch 'master' into merge

This commit is contained in:
Arseny Kapoulkine 2021-11-18 14:25:28 -08:00
commit c5ac146580
11 changed files with 95 additions and 87 deletions

View File

@ -27,13 +27,13 @@ jobs:
- uses: actions/checkout@v1
- name: make test
run: |
make -j2 config=sanitize test
make -j2 config=sanitize werror=1 test
- name: make test w/flags
run: |
make -j2 config=sanitize flags=true test
make -j2 config=sanitize werror=1 flags=true test
- name: make cli
run: |
make -j2 config=sanitize luau luau-analyze # match config with tests to improve build time
make -j2 config=sanitize werror=1 luau luau-analyze # match config with tests to improve build time
./luau tests/conformance/assert.lua
./luau-analyze tests/conformance/assert.lua
@ -45,7 +45,7 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: cmake configure
run: cmake . -A ${{matrix.arch}}
run: cmake . -A ${{matrix.arch}} -DLUAU_WERROR=ON
- name: cmake test
shell: bash # necessary for fail-fast
run: |

View File

@ -1509,7 +1509,7 @@ ExprResult<TypeId> TypeChecker::checkExpr(const ScopePtr& scope, const AstExprVa
std::vector<TypeId> types = flatten(varargPack).first;
return {!types.empty() ? types[0] : nilType};
}
else if (auto ftp = get<FreeTypePack>(varargPack))
else if (get<FreeTypePack>(varargPack))
{
TypeId head = freshType(scope);
TypePackId tail = freshTypePack(scope);
@ -1539,7 +1539,7 @@ ExprResult<TypeId> TypeChecker::checkExpr(const ScopePtr& scope, const AstExprCa
{
return {pack->head.empty() ? nilType : pack->head[0], std::move(result.predicates)};
}
else if (auto ftp = get<Unifiable::Free>(retPack))
else if (get<Unifiable::Free>(retPack))
{
TypeId head = freshType(scope);
TypePackId pack = addTypePack(TypePackVar{TypePack{{head}, freshTypePack(scope)}});

View File

@ -293,7 +293,7 @@ bool isGeneric(TypeId ty)
bool maybeGeneric(TypeId ty)
{
ty = follow(ty);
if (auto ftv = get<FreeTypeVar>(ty))
if (get<FreeTypeVar>(ty))
return true;
else if (auto ttv = get<TableTypeVar>(ty))
{

View File

@ -142,6 +142,7 @@ static bool traverseDirectoryRec(const std::string& path, const std::function<vo
joinPaths(buf, path.c_str(), data.d_name);
int type = data.d_type;
int mode = -1;
// we need to stat DT_UNKNOWN to be able to tell the type
if (type == DT_UNKNOWN)
@ -153,18 +154,18 @@ static bool traverseDirectoryRec(const std::string& path, const std::function<vo
lstat(buf.c_str(), &st);
#endif
type = IFTODT(st.st_mode);
mode = st.st_mode;
}
if (type == DT_DIR)
if (type == DT_DIR || mode == S_IFDIR)
{
traverseDirectoryRec(buf, callback);
}
else if (type == DT_REG)
else if (type == DT_REG || mode == S_IFREG)
{
callback(buf);
}
else if (type == DT_LNK)
else if (type == DT_LNK || mode == S_IFLNK)
{
// Skip symbolic links to avoid handling cycles
}

View File

@ -9,6 +9,7 @@ project(Luau LANGUAGES CXX)
option(LUAU_BUILD_CLI "Build CLI" ON)
option(LUAU_BUILD_TESTS "Build tests" ON)
option(LUAU_WERROR "Warnings as errors" OFF)
add_library(Luau.Ast STATIC)
add_library(Luau.Compiler STATIC)
@ -57,11 +58,18 @@ set(LUAU_OPTIONS)
if(MSVC)
list(APPEND LUAU_OPTIONS /D_CRT_SECURE_NO_WARNINGS) # We need to use the portable CRT functions.
list(APPEND LUAU_OPTIONS /WX) # Warnings are errors
list(APPEND LUAU_OPTIONS /MP) # Distribute single project compilation across multiple cores
else()
list(APPEND LUAU_OPTIONS -Wall) # All warnings
list(APPEND LUAU_OPTIONS -Werror) # Warnings are errors
endif()
# Enabled in CI; we should be warning free on our main compiler versions but don't guarantee being warning free everywhere
if(LUAU_WERROR)
if(MSVC)
list(APPEND LUAU_OPTIONS /WX) # Warnings are errors
else()
list(APPEND LUAU_OPTIONS -Werror) # Warnings are errors
endif()
endif()
target_compile_options(Luau.Ast PRIVATE ${LUAU_OPTIONS})
@ -79,7 +87,10 @@ if(LUAU_BUILD_CLI)
target_link_libraries(Luau.Repl.CLI PRIVATE Luau.Compiler Luau.VM)
if(UNIX)
target_link_libraries(Luau.Repl.CLI PRIVATE pthread)
find_library(LIBPTHREAD pthread)
if (LIBPTHREAD)
target_link_libraries(Luau.Repl.CLI PRIVATE pthread)
endif()
endif()
if(NOT EMSCRIPTEN)

View File

@ -46,14 +46,20 @@ endif
OBJECTS=$(AST_OBJECTS) $(COMPILER_OBJECTS) $(ANALYSIS_OBJECTS) $(VM_OBJECTS) $(TESTS_OBJECTS) $(CLI_OBJECTS) $(FUZZ_OBJECTS)
# common flags
CXXFLAGS=-g -Wall -Werror
CXXFLAGS=-g -Wall
LDFLAGS=
# temporary, for older gcc versions as they treat var in `if (type var = val)` as unused
# some gcc versions treat var in `if (type var = val)` as unused
# some gcc versions treat variables used in constexpr if blocks as unused
ifeq ($(findstring g++,$(shell $(CXX) --version)),g++)
CXXFLAGS+=-Wno-unused
endif
# enabled in CI; we should be warning free on our main compiler versions but don't guarantee being warning free everywhere
ifneq ($(werror),)
CXXFLAGS+=-Werror
endif
# configuration-specific flags
ifeq ($(config),release)
CXXFLAGS+=-O2 -DNDEBUG

14
SECURITY.md Normal file
View File

@ -0,0 +1,14 @@
# Security Guarantees
Luau provides a safe sandbox that scripts can not escape from, short of vulnerabilities in custom C functions exposed by the host. This includes the virtual machine and builtin libraries.
Any source code can not result in memory safety errors or crashes during its compilation or execution. Violations of memory safety are considered vulnerabilities.
Note that Luau does not provide termination guarantees - some code may exhaust CPU or RAM resources on the system during compilation or execution.
The runtime expects valid bytecode as an input. Feeding bytecode that was not produced by Luau compiler into the VM is not supported and
doesn't come with any security guarantees; make sure to sign and/or encrypt the bytecode when it crosses a network or file system boundary to avoid tampering.
# Reporting a Vulnerability
You can report security bugs via [Hackerone](https://hackerone.com/roblox). Please refer to the linked page for rules of the bounty program.

View File

@ -759,7 +759,7 @@ Otherwise, `s` is interpreted as a [date format string](https://www.cplusplus.co
function os.difftime(a: number, b: number): number
```
Calculates the difference in seconds between `a` and `b`; provided for compatibility.
Calculates the difference in seconds between `a` and `b`; provided for compatibility only. Please use `a - b` instead.
```
function os.time(t: table?): number

View File

@ -0,0 +1,34 @@
# coroutine.close
## Summary
Add `coroutine.close` function from Lua 5.4 that takes a suspended coroutine and makes it "dead" (non-runnable).
## Motivation
When implementing various higher level objects on top of coroutines, such as promises, it can be useful to cancel the coroutine execution externally - when the caller is not
interested in getting the results anymore, execution can be aborted. Since coroutines don't provide a way to do that externally, this requires the framework to implement
cancellation on top of coroutines by keeping extra status/token and checking that token in all places where the coroutine is resumed.
Since coroutine execution can be aborted with an error at any point, coroutines already implement support for "dead" status. If it were possible to externally transition a coroutine
to that status, it would be easier to implement cancellable promises on top of coroutines.
## Design
We implement Lua 5.4 behavior exactly with the exception of to-be-closed variables that we don't support. Quoting Lua 5.4 manual:
> coroutine.close (co)
> Closes coroutine co, that is, puts the coroutine in a dead state. The given coroutine must be dead or suspended. In case of error (either the original error that stopped the coroutine or errors in closing methods), returns false plus the error object; otherwise returns true.
The `co` argument must be a coroutine object (of type `thread`).
After closing the coroutine, it gets transitioned to dead state which means that `coroutine.status` will return `"dead"` and attempts to resume the coroutine will fail. In addition, the coroutine stack (which can be accessed via `debug.traceback` or `debug.info`) will become empty. Calling `coroutine.close` on a closed coroutine will return `true` - after closing, the coroutine transitions into a "dead" state with no error information.
## Drawbacks
None known, as this function doesn't introduce any existing states to coroutines, and is similar to running the coroutine to completion/error.
## Alternatives
Lua's name for this function is likely in part motivated by to-be-closed variables that we don't support. As such, a more appropriate name could be `coroutine.cancel` which also
aligns with use cases better. However, since the semantics is otherwise the same, using the same name as Lua 5.4 reduces library fragmentation.

View File

@ -1,70 +0,0 @@
# Allow method call on string literals
> Note: this RFC was adapted from an internal proposal that predates RFC process
## Summary
Allow string literals to be indexed on without parentheses or from an identifier. That is, the following snippet will become legal under this proposal:
```lua
print("Hello, %s!":format("world"))
print("0123456789ABCDEF":sub(i, i))
```
## Motivation
Experienced Lua developers occasionally run into this paper-cut even after years of working with the language. Programmers in Lua frequently wants to format a user-facing message using a constant string, but the parser will not accept it as legible syntax.
## Design
Formally, the proposal is to move the `String` parser from `exp` to `prefixexp`:
```diff
var ::= Name | prefixexp `[´ exp `]´ | prefixexp `.´ Name
- exp ::= nil | false | true | Number | String | `...´ | function |
+ exp ::= nil | false | true | Number | `...´ | function
| prefixexp | tableconstructor | exp binop exp | unop exp
- prefixexp ::= var | functioncall | `(´ exp `)´
+ prefixexp ::= String | var | functioncall | `(´ exp `)´
functioncall ::= prefixexp args | prefixexp `:´ Name args
```
By itself, this change introduces an additional ambiguity because of the combination of non-significant whitespace and function calls with string literal as the first argument without the use of parentheses.
Consider code like this:
```lua
local foo = bar
("fmt"):format(...)
```
The grammar for this sequence suggests that the above is a function call to bar with a single string literal argument, "fmt", and format method is called on the result. This is a consequence of line endings not being significant, but humans don't read the code like this, and are likely to think that here, format is called on the string literal "fmt".
Because of this, Lua 5.1 produces a syntax error whenever function call arguments start on the next line. Luau has the same error production rule; future versions of Lua remove this restriction but it's not clear that we want to remove this as this does help prevent errors.
The grammar today also allows calling functions with string literals as their first (and only) argument without the use of parentheses; bar "fmt" is a function call. This is helpful when defining embedded domain-specific languages.
By itself, this proposal thus would create a similar ambiguity in code like this:
```lua
local foo = bar
"fmt":format(...)
```
While we could extend the line-based error check to include function literal arguments, this is not syntactically backwards compatible and as such may break existing code. A simpler and more conservative solution is to disallow string literal as the leading token of a new statement - there are no cases when this is valid today, so it's safe to limit this.
Doing so would prohibit code like this:
```lua
"fmt":format(...)
```
However, there are no methods on the string object where code like this would be meaningful. As such, in addition to changing the grammar wrt string literals, we will add an extra ambiguity error whenever a statement starts with a string literal.
## Drawbacks
None known.
## Alternatives
The infallible parser could be mended in this exact scenario to report a more friendly error message. We decided not to do this because there is more value to gain by simply supporting the main proposal.

View File

@ -48,6 +48,18 @@ type Animals = "Dog" | "Cat" | "Bird"
type TrueOrNil = true?
```
Adding constant strings as type means that it is now legal to write
`{["foo"]:T}` as a table type. This should be parsed as a property,
not an indexer. For example:
```lua
type T = {
["foo"]: number,
["$$bar"]: string,
baz: boolean,
}
```
The table type `T` is a table with three properties and no indexer.
### Semantics
You are allowed to provide a constant value to the generic primitive type.