Skip to content

Commit

Permalink
Sync to upstream/release/534 (#569)
Browse files Browse the repository at this point in the history
  • Loading branch information
zeux committed Jun 30, 2022
1 parent fc76365 commit 2daa649
Show file tree
Hide file tree
Showing 54 changed files with 1,717 additions and 656 deletions.
19 changes: 18 additions & 1 deletion Analysis/include/Luau/Constraint.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once

#include "Luau/Ast.h" // Used for some of the enumerations
#include "Luau/NotNull.h"
#include "Luau/Variant.h"

Expand Down Expand Up @@ -47,14 +48,30 @@ struct InstantiationConstraint
TypeId superType;
};

struct UnaryConstraint
{
AstExprUnary::Op op;
TypeId operandType;
TypeId resultType;
};

struct BinaryConstraint
{
AstExprBinary::Op op;
TypeId leftType;
TypeId rightType;
TypeId resultType;
};

// name(namedType) = name
struct NameConstraint
{
TypeId namedType;
std::string name;
};

using ConstraintV = Variant<SubtypeConstraint, PackSubtypeConstraint, GeneralizationConstraint, InstantiationConstraint, NameConstraint>;
using ConstraintV = Variant<SubtypeConstraint, PackSubtypeConstraint, GeneralizationConstraint, InstantiationConstraint, UnaryConstraint,
BinaryConstraint, NameConstraint>;
using ConstraintPtr = std::unique_ptr<struct Constraint>;

struct Constraint
Expand Down
113 changes: 80 additions & 33 deletions Analysis/include/Luau/ConstraintGraphBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ struct ConstraintGraphBuilder
// scope pointers; the scopes themselves borrow pointers to other scopes to
// define the scope hierarchy.
std::vector<std::pair<Location, std::unique_ptr<Scope2>>> scopes;

ModuleName moduleName;
SingletonTypes& singletonTypes;
TypeArena* const arena;
const NotNull<TypeArena> arena;
// The root scope of the module we're generating constraints for.
// This is null when the CGB is initially constructed.
Scope2* rootScope;
// A mapping of AST node to TypeId.
DenseHashMap<const AstExpr*, TypeId> astTypes{nullptr};
Expand All @@ -39,40 +42,50 @@ struct ConstraintGraphBuilder
// Type packs resolved from type annotations. Analogous to astTypePacks.
DenseHashMap<const AstTypePack*, TypePackId> astResolvedTypePacks{nullptr};

explicit ConstraintGraphBuilder(TypeArena* arena);
int recursionCount = 0;

// It is pretty uncommon for constraint generation to itself produce errors, but it can happen.
std::vector<TypeError> errors;

// Occasionally constraint generation needs to produce an ICE.
const NotNull<InternalErrorReporter> ice;

NotNull<Scope2> globalScope;

ConstraintGraphBuilder(const ModuleName& moduleName, TypeArena* arena, NotNull<InternalErrorReporter> ice, NotNull<Scope2> globalScope);

/**
* Fabricates a new free type belonging to a given scope.
* @param scope the scope the free type belongs to. Must not be null.
* @param scope the scope the free type belongs to.
*/
TypeId freshType(Scope2* scope);
TypeId freshType(NotNull<Scope2> scope);

/**
* Fabricates a new free type pack belonging to a given scope.
* @param scope the scope the free type pack belongs to. Must not be null.
* @param scope the scope the free type pack belongs to.
*/
TypePackId freshTypePack(Scope2* scope);
TypePackId freshTypePack(NotNull<Scope2> scope);

/**
* Fabricates a scope that is a child of another scope.
* @param location the lexical extent of the scope in the source code.
* @param parent the parent scope of the new scope. Must not be null.
*/
Scope2* childScope(Location location, Scope2* parent);
NotNull<Scope2> childScope(Location location, NotNull<Scope2> parent);

/**
* Adds a new constraint with no dependencies to a given scope.
* @param scope the scope to add the constraint to. Must not be null.
* @param scope the scope to add the constraint to.
* @param cv the constraint variant to add.
*/
void addConstraint(Scope2* scope, ConstraintV cv);
void addConstraint(NotNull<Scope2> scope, ConstraintV cv);

/**
* Adds a constraint to a given scope.
* @param scope the scope to add the constraint to. Must not be null.
* @param c the constraint to add.
*/
void addConstraint(Scope2* scope, std::unique_ptr<Constraint> c);
void addConstraint(NotNull<Scope2> scope, std::unique_ptr<Constraint> c);

/**
* The entry point to the ConstraintGraphBuilder. This will construct a set
Expand All @@ -81,58 +94,92 @@ struct ConstraintGraphBuilder
*/
void visit(AstStatBlock* block);

void visit(Scope2* scope, AstStat* stat);
void visit(Scope2* scope, AstStatBlock* block);
void visit(Scope2* scope, AstStatLocal* local);
void visit(Scope2* scope, AstStatLocalFunction* function);
void visit(Scope2* scope, AstStatFunction* function);
void visit(Scope2* scope, AstStatReturn* ret);
void visit(Scope2* scope, AstStatAssign* assign);
void visit(Scope2* scope, AstStatIf* ifStatement);
void visit(Scope2* scope, AstStatTypeAlias* alias);
void visitBlockWithoutChildScope(NotNull<Scope2> scope, AstStatBlock* block);

void visit(NotNull<Scope2> scope, AstStat* stat);
void visit(NotNull<Scope2> scope, AstStatBlock* block);
void visit(NotNull<Scope2> scope, AstStatLocal* local);
void visit(NotNull<Scope2> scope, AstStatLocalFunction* function);
void visit(NotNull<Scope2> scope, AstStatFunction* function);
void visit(NotNull<Scope2> scope, AstStatReturn* ret);
void visit(NotNull<Scope2> scope, AstStatAssign* assign);
void visit(NotNull<Scope2> scope, AstStatIf* ifStatement);
void visit(NotNull<Scope2> scope, AstStatTypeAlias* alias);

TypePackId checkExprList(Scope2* scope, const AstArray<AstExpr*>& exprs);
TypePackId checkExprList(NotNull<Scope2> scope, const AstArray<AstExpr*>& exprs);

TypePackId checkPack(Scope2* scope, AstArray<AstExpr*> exprs);
TypePackId checkPack(Scope2* scope, AstExpr* expr);
TypePackId checkPack(NotNull<Scope2> scope, AstArray<AstExpr*> exprs);
TypePackId checkPack(NotNull<Scope2> scope, AstExpr* expr);

/**
* Checks an expression that is expected to evaluate to one type.
* @param scope the scope the expression is contained within.
* @param expr the expression to check.
* @return the type of the expression.
*/
TypeId check(Scope2* scope, AstExpr* expr);

TypeId checkExprTable(Scope2* scope, AstExprTable* expr);
TypeId check(Scope2* scope, AstExprIndexName* indexName);

std::pair<TypeId, Scope2*> checkFunctionSignature(Scope2* parent, AstExprFunction* fn);
TypeId check(NotNull<Scope2> scope, AstExpr* expr);

TypeId checkExprTable(NotNull<Scope2> scope, AstExprTable* expr);
TypeId check(NotNull<Scope2> scope, AstExprIndexName* indexName);
TypeId check(NotNull<Scope2> scope, AstExprIndexExpr* indexExpr);
TypeId check(NotNull<Scope2> scope, AstExprUnary* unary);
TypeId check(NotNull<Scope2> scope, AstExprBinary* binary);

struct FunctionSignature
{
// The type of the function.
TypeId signature;
// The scope that encompasses the function's signature. May be nullptr
// if there was no need for a signature scope (the function has no
// generics).
Scope2* signatureScope;
// The scope that encompasses the function's body. Is a child scope of
// signatureScope, if present.
NotNull<Scope2> bodyScope;
};

FunctionSignature checkFunctionSignature(NotNull<Scope2> parent, AstExprFunction* fn);

/**
* Checks the body of a function expression.
* @param scope the interior scope of the body of the function.
* @param fn the function expression to check.
*/
void checkFunctionBody(Scope2* scope, AstExprFunction* fn);
void checkFunctionBody(NotNull<Scope2> scope, AstExprFunction* fn);

/**
* Resolves a type from its AST annotation.
* @param scope the scope that the type annotation appears within.
* @param ty the AST annotation to resolve.
* @return the type of the AST annotation.
**/
TypeId resolveType(Scope2* scope, AstType* ty);
TypeId resolveType(NotNull<Scope2> scope, AstType* ty);

/**
* Resolves a type pack from its AST annotation.
* @param scope the scope that the type annotation appears within.
* @param tp the AST annotation to resolve.
* @return the type pack of the AST annotation.
**/
TypePackId resolveTypePack(Scope2* scope, AstTypePack* tp);
TypePackId resolveTypePack(NotNull<Scope2> scope, AstTypePack* tp);

TypePackId resolveTypePack(NotNull<Scope2> scope, const AstTypeList& list);

std::vector<std::pair<Name, GenericTypeDefinition>> createGenerics(NotNull<Scope2> scope, AstArray<AstGenericType> generics);
std::vector<std::pair<Name, GenericTypePackDefinition>> createGenericPacks(NotNull<Scope2> scope, AstArray<AstGenericTypePack> packs);

TypePackId resolveTypePack(Scope2* scope, const AstTypeList& list);
TypeId flattenPack(NotNull<Scope2> scope, Location location, TypePackId tp);

void reportError(Location location, TypeErrorData err);
void reportCodeTooComplex(Location location);

/** Scan the program for global definitions.
*
* ConstraintGraphBuilder needs to differentiate between globals and accesses to undefined symbols. Doing this "for
* real" in a general way is going to be pretty hard, so we are choosing not to tackle that yet. For now, we do an
* initial scan of the AST and note what globals are defined.
*/
void prepopulateGlobalScope(NotNull<Scope2> globalScope, AstStatBlock* program);
};

/**
Expand All @@ -145,6 +192,6 @@ struct ConstraintGraphBuilder
* @return a list of pointers to constraints contained within the scope graph.
* None of these pointers should be null.
*/
std::vector<NotNull<Constraint>> collectConstraints(Scope2* rootScope);
std::vector<NotNull<Constraint>> collectConstraints(NotNull<Scope2> rootScope);

} // namespace Luau
12 changes: 9 additions & 3 deletions Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct ConstraintSolver
// is important to not add elements to this vector, lest the underlying
// storage that we retain pointers to be mutated underneath us.
const std::vector<NotNull<Constraint>> constraints;
Scope2* rootScope;
NotNull<Scope2> rootScope;

// This includes every constraint that has not been fully solved.
// A constraint can be both blocked and unsolved, for instance.
Expand All @@ -40,7 +40,7 @@ struct ConstraintSolver

ConstraintSolverLogger logger;

explicit ConstraintSolver(TypeArena* arena, Scope2* rootScope);
explicit ConstraintSolver(TypeArena* arena, NotNull<Scope2> rootScope);

/**
* Attempts to dispatch all pending constraints and reach a type solution
Expand All @@ -50,11 +50,17 @@ struct ConstraintSolver

bool done();

/** Attempt to dispatch a constraint. Returns true if it was successful.
* If tryDispatch() returns false, the constraint remains in the unsolved set and will be retried later.
*/
bool tryDispatch(NotNull<const Constraint> c, bool force);

bool tryDispatch(const SubtypeConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const PackSubtypeConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const GeneralizationConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const InstantiationConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const UnaryConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const BinaryConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const NameConstraint& c, NotNull<const Constraint> constraint);

void block(NotNull<const Constraint> target, NotNull<const Constraint> constraint);
Expand Down Expand Up @@ -115,6 +121,6 @@ struct ConstraintSolver
void unblock_(BlockedConstraintId progressed);
};

void dump(Scope2* rootScope, struct ToStringOptions& opts);
void dump(NotNull<Scope2> rootScope, struct ToStringOptions& opts);

} // namespace Luau
35 changes: 18 additions & 17 deletions Analysis/include/Luau/Error.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,24 +369,25 @@ struct InternalErrorReporter
[[noreturn]] void ice(const std::string& message);
};

class InternalCompilerError : public std::exception {
class InternalCompilerError : public std::exception
{
public:
explicit InternalCompilerError(const std::string& message, const std::string& moduleName)
: message(message)
, moduleName(moduleName)
{
}
explicit InternalCompilerError(const std::string& message, const std::string& moduleName, const Location& location)
: message(message)
, moduleName(moduleName)
, location(location)
{
}
virtual const char* what() const throw();

const std::string message;
const std::string moduleName;
const std::optional<Location> location;
explicit InternalCompilerError(const std::string& message, const std::string& moduleName)
: message(message)
, moduleName(moduleName)
{
}
explicit InternalCompilerError(const std::string& message, const std::string& moduleName, const Location& location)
: message(message)
, moduleName(moduleName)
, location(location)
{
}
virtual const char* what() const throw();

const std::string message;
const std::string moduleName;
const std::optional<Location> location;
};

} // namespace Luau
5 changes: 5 additions & 0 deletions Analysis/include/Luau/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Luau/Module.h"
#include "Luau/ModuleResolver.h"
#include "Luau/RequireTracer.h"
#include "Luau/Scope.h"
#include "Luau/TypeInfer.h"
#include "Luau/Variant.h"

Expand Down Expand Up @@ -158,6 +159,8 @@ struct Frontend
void registerBuiltinDefinition(const std::string& name, std::function<void(TypeChecker&, ScopePtr)>);
void applyBuiltinDefinitionToEnvironment(const std::string& environmentName, const std::string& definitionName);

NotNull<Scope2> getGlobalScope2();

private:
ModulePtr check(const SourceModule& sourceModule, Mode mode, const ScopePtr& environmentScope);

Expand All @@ -173,6 +176,8 @@ struct Frontend
std::unordered_map<std::string, ScopePtr> environments;
std::unordered_map<std::string, std::function<void(TypeChecker&, ScopePtr)>> builtinDefinitions;

std::unique_ptr<Scope2> globalScope2;

public:
FileResolver* fileResolver;
FrontendModuleResolver moduleResolver;
Expand Down
2 changes: 1 addition & 1 deletion Analysis/include/Luau/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ struct Module
std::shared_ptr<Allocator> allocator;
std::shared_ptr<AstNameTable> names;

std::vector<std::pair<Location, ScopePtr>> scopes; // never empty
std::vector<std::pair<Location, ScopePtr>> scopes; // never empty
std::vector<std::pair<Location, std::unique_ptr<Scope2>>> scope2s; // never empty

DenseHashMap<const AstExpr*, TypeId> astTypes{nullptr};
Expand Down
Loading

0 comments on commit 2daa649

Please sign in to comment.