Skip to content

Commit

Permalink
pre-populate class bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
checkraisefold committed Oct 28, 2024
1 parent db80939 commit 1e5efd8
Showing 1 changed file with 35 additions and 5 deletions.
40 changes: 35 additions & 5 deletions Analysis/src/ConstraintGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,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
Expand Down Expand Up @@ -750,6 +751,29 @@ 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 (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;
}
}
}

Expand Down Expand Up @@ -1645,6 +1669,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 (bindingIt == scope->exportedTypeBindings.end())
return ControlFlow::None;

std::optional<TypeId> superTy = std::make_optional(builtinTypes->classType);
if (declaredClass->superName)
{
Expand All @@ -1659,9 +1688,9 @@ 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;
superTy = follow(lookupType->type);

if (!get<ClassType>(follow(*superTy)))
if (!get<ClassType>(*superTy))
{
reportError(
declaredClass->location,
Expand All @@ -1682,7 +1711,8 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatDeclareClas

ctv->metatable = metaTy;

scope->exportedTypeBindings[className] = TypeFun{{}, classTy};
TypeId classBindTy = bindingIt->second.type;
emplaceType<BoundType>(asMutable(classBindTy), classTy);

if (declaredClass->indexer)
{
Expand Down Expand Up @@ -2913,7 +2943,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprTable* expr,
std::vector<TypeId> toBlock;
if (DFInt::LuauTypeSolverRelease >= 648)
{
// This logic is incomplete as we want to re-run this
// This logic is incomplete as we want to re-run this
// _after_ blocked types have resolved, but this
// allows us to do some bidirectional inference.
toBlock = findBlockedTypesIn(expr, NotNull{&module->astTypes});
Expand All @@ -2931,7 +2961,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprTable* expr,
toBlock
);
// The visitor we ran prior should ensure that there are no
// blocked types that we would encounter while matching on
// blocked types that we would encounter while matching on
// this expression.
LUAU_ASSERT(toBlock.empty());
}
Expand Down

0 comments on commit 1e5efd8

Please sign in to comment.