diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cdee2f6..506a4c8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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: | diff --git a/Analysis/src/TypeInfer.cpp b/Analysis/src/TypeInfer.cpp index a6696ef..96b7992 100644 --- a/Analysis/src/TypeInfer.cpp +++ b/Analysis/src/TypeInfer.cpp @@ -1509,7 +1509,7 @@ ExprResult TypeChecker::checkExpr(const ScopePtr& scope, const AstExprVa std::vector types = flatten(varargPack).first; return {!types.empty() ? types[0] : nilType}; } - else if (auto ftp = get(varargPack)) + else if (get(varargPack)) { TypeId head = freshType(scope); TypePackId tail = freshTypePack(scope); @@ -1539,7 +1539,7 @@ ExprResult TypeChecker::checkExpr(const ScopePtr& scope, const AstExprCa { return {pack->head.empty() ? nilType : pack->head[0], std::move(result.predicates)}; } - else if (auto ftp = get(retPack)) + else if (get(retPack)) { TypeId head = freshType(scope); TypePackId pack = addTypePack(TypePackVar{TypePack{{head}, freshTypePack(scope)}}); diff --git a/Analysis/src/TypeVar.cpp b/Analysis/src/TypeVar.cpp index cd447ca..4ee5cb8 100644 --- a/Analysis/src/TypeVar.cpp +++ b/Analysis/src/TypeVar.cpp @@ -293,7 +293,7 @@ bool isGeneric(TypeId ty) bool maybeGeneric(TypeId ty) { ty = follow(ty); - if (auto ftv = get(ty)) + if (get(ty)) return true; else if (auto ttv = get(ty)) { diff --git a/CLI/FileUtils.cpp b/CLI/FileUtils.cpp index 0702b74..fff5e42 100644 --- a/CLI/FileUtils.cpp +++ b/CLI/FileUtils.cpp @@ -142,6 +142,7 @@ static bool traverseDirectoryRec(const std::string& path, const std::function 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. diff --git a/rfcs/syntax-method-call-on-string-literals.md b/rfcs/syntax-method-call-on-string-literals.md deleted file mode 100644 index 877774d..0000000 --- a/rfcs/syntax-method-call-on-string-literals.md +++ /dev/null @@ -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. diff --git a/rfcs/syntax-singleton-types.md b/rfcs/syntax-singleton-types.md index 749006c..26ea302 100644 --- a/rfcs/syntax-singleton-types.md +++ b/rfcs/syntax-singleton-types.md @@ -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.