mirror of
https://github.com/luau-lang/luau.git
synced 2025-04-05 19:30:54 +01:00
pre-populate class bindings
This commit is contained in:
parent
a251bc68a2
commit
55895a006e
1 changed files with 33 additions and 3 deletions
|
@ -653,6 +653,7 @@ void ConstraintGenerator::applyRefinements(const ScopePtr& scope, Location locat
|
||||||
void ConstraintGenerator::checkAliases(const ScopePtr& scope, AstStatBlock* block)
|
void ConstraintGenerator::checkAliases(const ScopePtr& scope, AstStatBlock* block)
|
||||||
{
|
{
|
||||||
std::unordered_map<Name, Location> aliasDefinitionLocations;
|
std::unordered_map<Name, Location> aliasDefinitionLocations;
|
||||||
|
std::unordered_map<Name, Location> classDefinitionLocations;
|
||||||
|
|
||||||
// In order to enable mutually-recursive type aliases, we need to
|
// In order to enable mutually-recursive type aliases, we need to
|
||||||
// populate the type bindings before we actually check any of the
|
// populate the type bindings before we actually check any of the
|
||||||
|
@ -750,6 +751,29 @@ void ConstraintGenerator::checkAliases(const ScopePtr& scope, AstStatBlock* bloc
|
||||||
scope->privateTypeBindings[function->name.value] = std::move(typeFunction);
|
scope->privateTypeBindings[function->name.value] = std::move(typeFunction);
|
||||||
aliasDefinitionLocations[function->name.value] = function->location;
|
aliasDefinitionLocations[function->name.value] = function->location;
|
||||||
}
|
}
|
||||||
|
else if (auto classDeclaration = stat->as<AstStatDeclareClass>())
|
||||||
|
{
|
||||||
|
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 +1669,11 @@ static bool isMetamethod(const Name& name)
|
||||||
|
|
||||||
ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatDeclareClass* declaredClass)
|
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 (bindingIt == scope->exportedTypeBindings.end())
|
||||||
|
return ControlFlow::None;
|
||||||
|
|
||||||
std::optional<TypeId> superTy = std::make_optional(builtinTypes->classType);
|
std::optional<TypeId> superTy = std::make_optional(builtinTypes->classType);
|
||||||
if (declaredClass->superName)
|
if (declaredClass->superName)
|
||||||
{
|
{
|
||||||
|
@ -1659,9 +1688,9 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatDeclareClas
|
||||||
|
|
||||||
// We don't have generic classes, so this assertion _should_ never be hit.
|
// We don't have generic classes, so this assertion _should_ never be hit.
|
||||||
LUAU_ASSERT(lookupType->typeParams.size() == 0 && lookupType->typePackParams.size() == 0);
|
LUAU_ASSERT(lookupType->typeParams.size() == 0 && lookupType->typePackParams.size() == 0);
|
||||||
superTy = lookupType->type;
|
superTy = follow(lookupType->type);
|
||||||
|
|
||||||
if (!get<ClassType>(follow(*superTy)))
|
if (!get<ClassType>(*superTy))
|
||||||
{
|
{
|
||||||
reportError(
|
reportError(
|
||||||
declaredClass->location,
|
declaredClass->location,
|
||||||
|
@ -1682,7 +1711,8 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatDeclareClas
|
||||||
|
|
||||||
ctv->metatable = metaTy;
|
ctv->metatable = metaTy;
|
||||||
|
|
||||||
scope->exportedTypeBindings[className] = TypeFun{{}, classTy};
|
TypeId classBindTy = bindingIt->second.type;
|
||||||
|
emplaceType<BoundType>(asMutable(classBindTy), classTy);
|
||||||
|
|
||||||
if (declaredClass->indexer)
|
if (declaredClass->indexer)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue