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
4399b17f95
@ -34,6 +34,8 @@ LUAU_DYNAMIC_FASTINT(LuauTypeSolverRelease)
|
||||
LUAU_FASTFLAG(LuauTypestateBuiltins2)
|
||||
|
||||
LUAU_FASTFLAGVARIABLE(LuauNewSolverVisitErrorExprLvalues)
|
||||
LUAU_FASTFLAGVARIABLE(LuauNewSolverPrePopulateClasses)
|
||||
LUAU_FASTFLAGVARIABLE(LuauNewSolverPopulateTableLocations)
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
@ -653,6 +655,7 @@ void ConstraintGenerator::applyRefinements(const ScopePtr& scope, Location locat
|
||||
void ConstraintGenerator::checkAliases(const ScopePtr& scope, AstStatBlock* block)
|
||||
{
|
||||
std::unordered_map<Name, Location> aliasDefinitionLocations;
|
||||
std::unordered_map<Name, Location> classDefinitionLocations;
|
||||
|
||||
// In order to enable mutually-recursive type aliases, we need to
|
||||
// populate the type bindings before we actually check any of the
|
||||
@ -750,6 +753,32 @@ void ConstraintGenerator::checkAliases(const ScopePtr& scope, AstStatBlock* bloc
|
||||
scope->privateTypeBindings[function->name.value] = std::move(typeFunction);
|
||||
aliasDefinitionLocations[function->name.value] = function->location;
|
||||
}
|
||||
else if (auto classDeclaration = stat->as<AstStatDeclareClass>())
|
||||
{
|
||||
if (!FFlag::LuauNewSolverPrePopulateClasses)
|
||||
continue;
|
||||
|
||||
if (scope->exportedTypeBindings.count(classDeclaration->name.value))
|
||||
{
|
||||
auto it = classDefinitionLocations.find(classDeclaration->name.value);
|
||||
LUAU_ASSERT(it != classDefinitionLocations.end());
|
||||
reportError(classDeclaration->location, DuplicateTypeDefinition{classDeclaration->name.value, it->second});
|
||||
continue;
|
||||
}
|
||||
|
||||
// A class might have no name if the code is syntactically
|
||||
// illegal. We mustn't prepopulate anything in this case.
|
||||
if (classDeclaration->name == kParseNameError)
|
||||
continue;
|
||||
|
||||
ScopePtr defnScope = childScope(classDeclaration, scope);
|
||||
|
||||
TypeId initialType = arena->addType(BlockedType{});
|
||||
TypeFun initialFun{initialType};
|
||||
scope->exportedTypeBindings[classDeclaration->name.value] = std::move(initialFun);
|
||||
|
||||
classDefinitionLocations[classDeclaration->name.value] = classDeclaration->location;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1645,6 +1674,11 @@ static bool isMetamethod(const Name& name)
|
||||
|
||||
ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatDeclareClass* declaredClass)
|
||||
{
|
||||
// If a class with the same name was already defined, we skip over
|
||||
auto bindingIt = scope->exportedTypeBindings.find(declaredClass->name.value);
|
||||
if (FFlag::LuauNewSolverPrePopulateClasses && bindingIt == scope->exportedTypeBindings.end())
|
||||
return ControlFlow::None;
|
||||
|
||||
std::optional<TypeId> superTy = std::make_optional(builtinTypes->classType);
|
||||
if (declaredClass->superName)
|
||||
{
|
||||
@ -1659,7 +1693,10 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatDeclareClas
|
||||
|
||||
// We don't have generic classes, so this assertion _should_ never be hit.
|
||||
LUAU_ASSERT(lookupType->typeParams.size() == 0 && lookupType->typePackParams.size() == 0);
|
||||
superTy = lookupType->type;
|
||||
if (FFlag::LuauNewSolverPrePopulateClasses)
|
||||
superTy = follow(lookupType->type);
|
||||
else
|
||||
superTy = lookupType->type;
|
||||
|
||||
if (!get<ClassType>(follow(*superTy)))
|
||||
{
|
||||
@ -1682,7 +1719,14 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatDeclareClas
|
||||
|
||||
ctv->metatable = metaTy;
|
||||
|
||||
scope->exportedTypeBindings[className] = TypeFun{{}, classTy};
|
||||
|
||||
if (FFlag::LuauNewSolverPrePopulateClasses)
|
||||
{
|
||||
TypeId classBindTy = bindingIt->second.type;
|
||||
emplaceType<BoundType>(asMutable(classBindTy), classTy);
|
||||
}
|
||||
else
|
||||
scope->exportedTypeBindings[className] = TypeFun{{}, classTy};
|
||||
|
||||
if (declaredClass->indexer)
|
||||
{
|
||||
@ -2844,6 +2888,10 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprTable* expr,
|
||||
|
||||
ttv->state = TableState::Unsealed;
|
||||
ttv->definitionModuleName = module->name;
|
||||
if (FFlag::LuauNewSolverPopulateTableLocations)
|
||||
{
|
||||
ttv->definitionLocation = expr->location;
|
||||
}
|
||||
ttv->scope = scope.get();
|
||||
|
||||
interiorTypes.back().push_back(ty);
|
||||
@ -3301,7 +3349,16 @@ TypeId ConstraintGenerator::resolveTableType(const ScopePtr& scope, AstType* ty,
|
||||
ice->ice("Unexpected property access " + std::to_string(int(astIndexer->access)));
|
||||
}
|
||||
|
||||
return arena->addType(TableType{props, indexer, scope->level, scope.get(), TableState::Sealed});
|
||||
TypeId tableTy = arena->addType(TableType{props, indexer, scope->level, scope.get(), TableState::Sealed});
|
||||
TableType* ttv = getMutable<TableType>(tableTy);
|
||||
|
||||
if (FFlag::LuauNewSolverPopulateTableLocations)
|
||||
{
|
||||
ttv->definitionModuleName = module->name;
|
||||
ttv->definitionLocation = tab->location;
|
||||
}
|
||||
|
||||
return tableTy;
|
||||
}
|
||||
|
||||
TypeId ConstraintGenerator::resolveFunctionType(
|
||||
|
@ -33,6 +33,7 @@ LUAU_FASTFLAGVARIABLE(DebugLuauLogBindings)
|
||||
LUAU_FASTINTVARIABLE(LuauSolverRecursionLimit, 500)
|
||||
LUAU_DYNAMIC_FASTINT(LuauTypeSolverRelease)
|
||||
LUAU_FASTFLAGVARIABLE(LuauRemoveNotAnyHack)
|
||||
LUAU_FASTFLAG(LuauNewSolverPopulateTableLocations)
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
@ -1109,9 +1110,15 @@ bool ConstraintSolver::tryDispatch(const TypeAliasExpansionConstraint& c, NotNul
|
||||
target = follow(instantiated);
|
||||
}
|
||||
|
||||
if (FFlag::LuauNewSolverPopulateTableLocations)
|
||||
{
|
||||
// This is a new type - redefine the location.
|
||||
ttv->definitionLocation = constraint->location;
|
||||
ttv->definitionModuleName = currentModuleName;
|
||||
}
|
||||
|
||||
ttv->instantiatedTypeParams = typeArguments;
|
||||
ttv->instantiatedTypePackParams = packArguments;
|
||||
// TODO: Fill in definitionModuleName.
|
||||
}
|
||||
|
||||
bindResult(target);
|
||||
@ -1433,7 +1440,8 @@ bool ConstraintSolver::tryDispatch(const FunctionCheckConstraint& c, NotNull<con
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (expr->is<AstExprConstantBool>() || expr->is<AstExprConstantString>() || expr->is<AstExprConstantNumber>() || expr->is<AstExprConstantNil>())
|
||||
else if (expr->is<AstExprConstantBool>() || expr->is<AstExprConstantString>() || expr->is<AstExprConstantNumber>() ||
|
||||
expr->is<AstExprConstantNil>())
|
||||
{
|
||||
Unifier2 u2{arena, builtinTypes, constraint->scope, NotNull{&iceReporter}};
|
||||
u2.unify(actualArgTy, expectedArgTy);
|
||||
@ -2326,12 +2334,7 @@ bool ConstraintSolver::tryDispatchIterableTable(TypeId iteratorTy, const Iterabl
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConstraintSolver::tryDispatchIterableFunction(
|
||||
TypeId nextTy,
|
||||
TypeId tableTy,
|
||||
const IterableConstraint& c,
|
||||
NotNull<const Constraint> constraint
|
||||
)
|
||||
bool ConstraintSolver::tryDispatchIterableFunction(TypeId nextTy, TypeId tableTy, const IterableConstraint& c, NotNull<const Constraint> constraint)
|
||||
{
|
||||
const FunctionType* nextFn = get<FunctionType>(nextTy);
|
||||
// If this does not hold, we should've never called `tryDispatchIterableFunction` in the first place.
|
||||
|
@ -8,7 +8,7 @@ Some questions help improve the language, implementation or documentation by ins
|
||||
|
||||
## Documentation
|
||||
|
||||
A [separate site repository](https://github.com/luau-lang/site) hosts the language documentation, which is accessible on https://luau-lang.org.
|
||||
A [separate site repository](https://github.com/luau-lang/site) hosts the language documentation, which is accessible on https://luau.org.
|
||||
Changes to this documentation that improve clarity, fix grammatical issues, explain aspects that haven't been explained before and the like are warmly welcomed.
|
||||
|
||||
Please feel free to [create a pull request](https://help.github.com/articles/about-pull-requests/) to improve our documentation. Note that at this point the documentation is English-only.
|
||||
|
@ -15,7 +15,7 @@ struct HotComment;
|
||||
|
||||
struct LintWarning
|
||||
{
|
||||
// Make sure any new lint codes are documented here: https://luau-lang.org/lint
|
||||
// Make sure any new lint codes are documented here: https://luau.org/lint
|
||||
// Note that in Studio, the active set of lint warnings is determined by FStringStudioLuauLints
|
||||
enum Code
|
||||
{
|
||||
|
@ -3,11 +3,11 @@ Luau ![CI](https://github.com/luau-lang/luau/actions/workflows/build.yml/badge.s
|
||||
|
||||
Luau (lowercase u, /ˈlu.aʊ/) is a fast, small, safe, gradually typed embeddable scripting language derived from [Lua](https://lua.org).
|
||||
|
||||
It is designed to be backwards compatible with Lua 5.1, as well as incorporating [some features](https://luau-lang.org/compatibility) from future Lua releases, but also expands the feature set (most notably with type annotations). Luau is largely implemented from scratch, with the language runtime being a very heavily modified version of Lua 5.1 runtime, with completely rewritten interpreter and other [performance innovations](https://luau-lang.org/performance). The runtime mostly preserves Lua 5.1 API, so existing bindings should be more or less compatible with a few caveats.
|
||||
It is designed to be backwards compatible with Lua 5.1, as well as incorporating [some features](https://luau.org/compatibility) from future Lua releases, but also expands the feature set (most notably with type annotations). Luau is largely implemented from scratch, with the language runtime being a very heavily modified version of Lua 5.1 runtime, with completely rewritten interpreter and other [performance innovations](https://luau.org/performance). The runtime mostly preserves Lua 5.1 API, so existing bindings should be more or less compatible with a few caveats.
|
||||
|
||||
Luau is used by Roblox game developers to write game code, as well as by Roblox engineers to implement large parts of the user-facing application code as well as portions of the editor (Roblox Studio) as plugins. Roblox chose to open-source Luau to foster collaboration within the Roblox community as well as to allow other companies and communities to benefit from the ongoing language and runtime innovation. As a consequence, Luau is now also used by games like Alan Wake 2 and Warframe.
|
||||
|
||||
This repository hosts source code for the language implementation and associated tooling. Documentation for the language is available at https://luau-lang.org/ and accepts contributions via [site repository](https://github.com/luau-lang/site); the language is evolved through RFCs that are located in [rfcs repository](https://github.com/luau-lang/rfcs).
|
||||
This repository hosts source code for the language implementation and associated tooling. Documentation for the language is available at https://luau.org/ and accepts contributions via [site repository](https://github.com/luau-lang/site); the language is evolved through RFCs that are located in [rfcs repository](https://github.com/luau-lang/rfcs).
|
||||
|
||||
# Usage
|
||||
|
||||
@ -15,7 +15,7 @@ Luau is an embeddable language, but it also comes with two command-line tools by
|
||||
|
||||
`luau` is a command-line REPL and can also run input files. Note that REPL runs in a sandboxed environment and as such doesn't have access to the underlying file system except for ability to `require` modules.
|
||||
|
||||
`luau-analyze` is a command-line type checker and linter; given a set of input files, it produces errors/warnings according to the file configuration, which can be customized by using `--!` comments in the files or [`.luaurc`](https://rfcs.luau-lang.org/config-luaurc) files. For details please refer to [type checking]( https://luau-lang.org/typecheck) and [linting](https://luau-lang.org/lint) documentation.
|
||||
`luau-analyze` is a command-line type checker and linter; given a set of input files, it produces errors/warnings according to the file configuration, which can be customized by using `--!` comments in the files or [`.luaurc`](https://rfcs.luau.org/config-luaurc) files. For details please refer to [type checking]( https://luau.org/typecheck) and [linting](https://luau.org/lint) documentation.
|
||||
|
||||
# Installation
|
||||
|
||||
@ -28,7 +28,7 @@ Alternatively, you can use one of the packaged distributions (note that these ar
|
||||
- Alpine Linux: [Enable community repositories](https://wiki.alpinelinux.org/w/index.php?title=Enable_Community_Repository) and run `apk add luau`
|
||||
- Gentoo Linux: Luau is [officially packaged by Gentoo](https://packages.gentoo.org/packages/dev-lang/luau) and can be installed using `emerge dev-lang/luau`. You may have to unmask the package first before installing it (which can be done by including the `--autounmask=y` option in the `emerge` command).
|
||||
|
||||
After installing, you will want to validate the installation was successful by running the test case [here](https://luau-lang.org/getting-started).
|
||||
After installing, you will want to validate the installation was successful by running the test case [here](https://luau.org/getting-started).
|
||||
|
||||
## Building
|
||||
|
||||
|
@ -40,7 +40,7 @@ const char* lua_ident = "$Lua: Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Ri
|
||||
"$URL: www.lua.org $\n";
|
||||
|
||||
const char* luau_ident = "$Luau: Copyright (C) 2019-2023 Roblox Corporation $\n"
|
||||
"$URL: luau-lang.org $\n";
|
||||
"$URL: luau.org $\n";
|
||||
|
||||
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
using namespace Luau;
|
||||
|
||||
LUAU_FASTFLAG(LuauNewSolverPrePopulateClasses)
|
||||
|
||||
TEST_SUITE_BEGIN("DefinitionTests");
|
||||
|
||||
TEST_CASE_FIXTURE(Fixture, "definition_file_simple")
|
||||
@ -492,11 +494,8 @@ TEST_CASE_FIXTURE(Fixture, "class_definition_indexer")
|
||||
|
||||
TEST_CASE_FIXTURE(Fixture, "class_definitions_reference_other_classes")
|
||||
{
|
||||
unfreeze(frontend.globals.globalTypes);
|
||||
LoadDefinitionFileResult result = frontend.loadDefinitionFile(
|
||||
frontend.globals,
|
||||
frontend.globals.globalScope,
|
||||
R"(
|
||||
ScopedFastFlag _{FFlag::LuauNewSolverPrePopulateClasses, true};
|
||||
loadDefinition(R"(
|
||||
declare class Channel
|
||||
Messages: { Message }
|
||||
OnMessage: (message: Message) -> ()
|
||||
@ -506,13 +505,19 @@ TEST_CASE_FIXTURE(Fixture, "class_definitions_reference_other_classes")
|
||||
Text: string
|
||||
Channel: Channel
|
||||
end
|
||||
)",
|
||||
"@test",
|
||||
/* captureComments */ false
|
||||
);
|
||||
freeze(frontend.globals.globalTypes);
|
||||
)");
|
||||
|
||||
REQUIRE(result.success);
|
||||
CheckResult result = check(R"(
|
||||
local a: Channel
|
||||
local b = a.Messages[1]
|
||||
local c = b.Channel
|
||||
)");
|
||||
|
||||
LUAU_REQUIRE_NO_ERRORS(result);
|
||||
|
||||
CHECK_EQ(toString(requireType("a")), "Channel");
|
||||
CHECK_EQ(toString(requireType("b")), "Message");
|
||||
CHECK_EQ(toString(requireType("c")), "Channel");
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(Fixture, "definition_file_has_source_module_name_set")
|
||||
|
@ -14,6 +14,7 @@ LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
||||
LUAU_FASTFLAG(LuauRequireCyclesDontAlwaysReturnAny)
|
||||
LUAU_FASTFLAG(LuauSolverV2)
|
||||
LUAU_FASTFLAG(LuauTypestateBuiltins2)
|
||||
LUAU_FASTFLAG(LuauNewSolverPopulateTableLocations)
|
||||
|
||||
using namespace Luau;
|
||||
|
||||
@ -466,7 +467,15 @@ local b: B.T = a
|
||||
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||
|
||||
if (FFlag::LuauSolverV2)
|
||||
CHECK(toString(result.errors.at(0)) == "Type 'T' could not be converted into 'T'; at [read \"x\"], number is not exactly string");
|
||||
{
|
||||
if (FFlag::LuauNewSolverPopulateTableLocations)
|
||||
CHECK(
|
||||
toString(result.errors.at(0)) ==
|
||||
"Type 'T' from 'game/A' could not be converted into 'T' from 'game/B'; at [read \"x\"], number is not exactly string"
|
||||
);
|
||||
else
|
||||
CHECK(toString(result.errors.at(0)) == "Type 'T' could not be converted into 'T'; at [read \"x\"], number is not exactly string");
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string expected = R"(Type 'T' from 'game/A' could not be converted into 'T' from 'game/B'
|
||||
@ -507,7 +516,15 @@ local b: B.T = a
|
||||
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||
|
||||
if (FFlag::LuauSolverV2)
|
||||
CHECK(toString(result.errors.at(0)) == "Type 'T' could not be converted into 'T'; at [read \"x\"], number is not exactly string");
|
||||
{
|
||||
if (FFlag::LuauNewSolverPopulateTableLocations)
|
||||
CHECK(
|
||||
toString(result.errors.at(0)) ==
|
||||
"Type 'T' from 'game/B' could not be converted into 'T' from 'game/C'; at [read \"x\"], number is not exactly string"
|
||||
);
|
||||
else
|
||||
CHECK(toString(result.errors.at(0)) == "Type 'T' could not be converted into 'T'; at [read \"x\"], number is not exactly string");
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string expected = R"(Type 'T' from 'game/B' could not be converted into 'T' from 'game/C'
|
||||
|
Loading…
Reference in New Issue
Block a user