luau/Analysis/include/Luau/ConstraintGraphBuilder.h

280 lines
11 KiB
C
Raw Normal View History

2022-06-03 21:32:20 +01:00
// 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"
2022-11-04 17:02:37 +00:00
#include "Luau/Connective.h"
2022-06-17 01:54:42 +01:00
#include "Luau/Constraint.h"
2022-12-02 10:46:05 +00:00
#include "Luau/DataFlowGraph.h"
2022-06-03 21:32:20 +01:00
#include "Luau/Module.h"
2022-09-02 00:00:14 +01:00
#include "Luau/ModuleResolver.h"
2022-06-17 01:54:42 +01:00
#include "Luau/NotNull.h"
2022-06-03 21:32:20 +01:00
#include "Luau/Symbol.h"
2023-01-03 17:33:19 +00:00
#include "Luau/Type.h"
2022-06-03 21:32:20 +01:00
#include "Luau/Variant.h"
2022-10-21 18:33:43 +01:00
#include <memory>
#include <vector>
#include <unordered_map>
2022-06-03 21:32:20 +01:00
namespace Luau
{
2022-07-29 04:41:13 +01:00
struct Scope;
using ScopePtr = std::shared_ptr<Scope>;
2022-06-03 21:32:20 +01:00
2022-09-08 22:44:50 +01:00
struct DcrLogger;
2022-10-27 23:22:49 +01:00
struct Inference
{
TypeId ty = nullptr;
2022-11-04 17:02:37 +00:00
ConnectiveId connective = nullptr;
2022-10-27 23:22:49 +01:00
Inference() = default;
2022-11-04 17:02:37 +00:00
explicit Inference(TypeId ty, ConnectiveId connective = nullptr)
2022-10-27 23:22:49 +01:00
: ty(ty)
2022-11-04 17:02:37 +00:00
, connective(connective)
2022-10-27 23:22:49 +01:00
{
}
};
struct InferencePack
{
TypePackId tp = nullptr;
2022-11-04 17:02:37 +00:00
std::vector<ConnectiveId> connectives;
2022-10-27 23:22:49 +01:00
InferencePack() = default;
2022-11-04 17:02:37 +00:00
explicit InferencePack(TypePackId tp, const std::vector<ConnectiveId>& connectives = {})
2022-10-27 23:22:49 +01:00
: tp(tp)
2022-11-04 17:02:37 +00:00
, connectives(connectives)
2022-10-27 23:22:49 +01:00
{
}
};
2022-06-03 21:32:20 +01:00
struct ConstraintGraphBuilder
{
// A list of all the scopes in the module. This vector holds ownership of the
// scope pointers; the scopes themselves borrow pointers to other scopes to
// define the scope hierarchy.
2022-07-29 04:41:13 +01:00
std::vector<std::pair<Location, ScopePtr>> scopes;
2022-07-01 00:29:02 +01:00
ModuleName moduleName;
2022-08-11 21:42:54 +01:00
ModulePtr module;
2023-01-03 17:33:19 +00:00
NotNull<BuiltinTypes> builtinTypes;
2022-07-01 00:29:02 +01:00
const NotNull<TypeArena> arena;
2022-06-03 21:32:20 +01:00
// The root scope of the module we're generating constraints for.
2022-07-01 00:29:02 +01:00
// This is null when the CGB is initially constructed.
2022-07-29 04:41:13 +01:00
Scope* rootScope;
2022-11-10 22:04:44 +00:00
// Constraints that go straight to the solver.
std::vector<ConstraintPtr> constraints;
// Constraints that do not go to the solver right away. Other constraints
// will enqueue them during solving.
std::vector<ConstraintPtr> unqueuedConstraints;
2022-06-17 01:54:42 +01:00
// A mapping of AST node to TypeId.
DenseHashMap<const AstExpr*, TypeId> astTypes{nullptr};
2022-12-09 18:07:25 +00:00
2022-06-17 01:54:42 +01:00
// A mapping of AST node to TypePackId.
DenseHashMap<const AstExpr*, TypePackId> astTypePacks{nullptr};
2022-12-09 18:07:25 +00:00
// If the node was applied as a function, this is the unspecialized type of
// that expression.
2023-01-06 16:07:19 +00:00
DenseHashMap<const void*, TypeId> astOriginalCallTypes{nullptr};
2022-12-09 18:07:25 +00:00
// If overload resolution was performed on this element, this is the
// overload that was selected.
2023-01-06 16:07:19 +00:00
DenseHashMap<const void*, TypeId> astOverloadResolvedTypes{nullptr};
2022-12-09 18:07:25 +00:00
2022-06-24 02:44:07 +01:00
// Types resolved from type annotations. Analogous to astTypes.
DenseHashMap<const AstType*, TypeId> astResolvedTypes{nullptr};
2022-12-09 18:07:25 +00:00
2022-06-24 02:44:07 +01:00
// Type packs resolved from type annotations. Analogous to astTypePacks.
DenseHashMap<const AstTypePack*, TypePackId> astResolvedTypePacks{nullptr};
2022-12-09 18:07:25 +00:00
2022-08-04 22:27:28 +01:00
// Defining scopes for AST nodes.
DenseHashMap<const AstStatTypeAlias*, ScopePtr> astTypeAliasDefiningScopes{nullptr};
2022-12-09 18:07:25 +00:00
2022-10-21 18:33:43 +01:00
NotNull<const DataFlowGraph> dfg;
2022-11-04 17:02:37 +00:00
ConnectiveArena connectiveArena;
2022-06-03 21:32:20 +01:00
2022-07-01 00:29:02 +01:00
int recursionCount = 0;
// It is pretty uncommon for constraint generation to itself produce errors, but it can happen.
std::vector<TypeError> errors;
2022-09-02 00:00:14 +01:00
// Needed to resolve modules to make 'require' import types properly.
NotNull<ModuleResolver> moduleResolver;
2022-07-01 00:29:02 +01:00
// Occasionally constraint generation needs to produce an ICE.
const NotNull<InternalErrorReporter> ice;
2022-08-11 21:42:54 +01:00
ScopePtr globalScope;
2022-09-08 22:44:50 +01:00
DcrLogger* logger;
2022-07-01 00:29:02 +01:00
2022-09-02 00:00:14 +01:00
ConstraintGraphBuilder(const ModuleName& moduleName, ModulePtr module, TypeArena* arena, NotNull<ModuleResolver> moduleResolver,
2023-01-03 17:33:19 +00:00
NotNull<BuiltinTypes> builtinTypes, NotNull<InternalErrorReporter> ice, const ScopePtr& globalScope, DcrLogger* logger,
2022-10-21 18:33:43 +01:00
NotNull<DataFlowGraph> dfg);
2022-06-03 21:32:20 +01:00
/**
* Fabricates a new free type belonging to a given scope.
2022-07-01 00:29:02 +01:00
* @param scope the scope the free type belongs to.
2022-06-03 21:32:20 +01:00
*/
2022-07-29 04:41:13 +01:00
TypeId freshType(const ScopePtr& scope);
2022-06-03 21:32:20 +01:00
/**
* Fabricates a new free type pack belonging to a given scope.
2022-07-01 00:29:02 +01:00
* @param scope the scope the free type pack belongs to.
2022-06-03 21:32:20 +01:00
*/
2022-07-29 04:41:13 +01:00
TypePackId freshTypePack(const ScopePtr& scope);
2022-06-03 21:32:20 +01:00
/**
* Fabricates a scope that is a child of another scope.
2022-08-18 22:04:33 +01:00
* @param node the lexical node that the scope belongs to.
2022-06-03 21:32:20 +01:00
* @param parent the parent scope of the new scope. Must not be null.
*/
2022-08-18 22:04:33 +01:00
ScopePtr childScope(AstNode* node, const ScopePtr& parent);
2022-06-03 21:32:20 +01:00
/**
* Adds a new constraint with no dependencies to a given scope.
2022-07-01 00:29:02 +01:00
* @param scope the scope to add the constraint to.
2022-06-03 21:32:20 +01:00
* @param cv the constraint variant to add.
2022-10-21 18:33:43 +01:00
* @return the pointer to the inserted constraint
2022-06-03 21:32:20 +01:00
*/
2022-10-21 18:33:43 +01:00
NotNull<Constraint> addConstraint(const ScopePtr& scope, const Location& location, ConstraintV cv);
2022-06-03 21:32:20 +01:00
/**
* 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.
2022-10-21 18:33:43 +01:00
* @return the pointer to the inserted constraint
2022-06-03 21:32:20 +01:00
*/
2022-10-21 18:33:43 +01:00
NotNull<Constraint> addConstraint(const ScopePtr& scope, std::unique_ptr<Constraint> c);
2022-06-03 21:32:20 +01:00
2022-11-04 17:02:37 +00:00
void applyRefinements(const ScopePtr& scope, Location location, ConnectiveId connective);
2022-06-03 21:32:20 +01:00
/**
* The entry point to the ConstraintGraphBuilder. This will construct a set
* of scopes, constraints, and free types that can be solved later.
* @param block the root block to generate constraints for.
*/
void visit(AstStatBlock* block);
2022-07-29 04:41:13 +01:00
void visitBlockWithoutChildScope(const ScopePtr& scope, AstStatBlock* block);
2022-07-01 00:29:02 +01:00
2022-07-29 04:41:13 +01:00
void visit(const ScopePtr& scope, AstStat* stat);
void visit(const ScopePtr& scope, AstStatBlock* block);
void visit(const ScopePtr& scope, AstStatLocal* local);
void visit(const ScopePtr& scope, AstStatFor* for_);
2022-09-02 00:00:14 +01:00
void visit(const ScopePtr& scope, AstStatForIn* forIn);
2022-08-11 21:42:54 +01:00
void visit(const ScopePtr& scope, AstStatWhile* while_);
2022-08-18 22:04:33 +01:00
void visit(const ScopePtr& scope, AstStatRepeat* repeat);
2022-07-29 04:41:13 +01:00
void visit(const ScopePtr& scope, AstStatLocalFunction* function);
void visit(const ScopePtr& scope, AstStatFunction* function);
void visit(const ScopePtr& scope, AstStatReturn* ret);
void visit(const ScopePtr& scope, AstStatAssign* assign);
2022-08-18 22:04:33 +01:00
void visit(const ScopePtr& scope, AstStatCompoundAssign* assign);
2022-07-29 04:41:13 +01:00
void visit(const ScopePtr& scope, AstStatIf* ifStatement);
void visit(const ScopePtr& scope, AstStatTypeAlias* alias);
2022-08-04 22:27:28 +01:00
void visit(const ScopePtr& scope, AstStatDeclareGlobal* declareGlobal);
void visit(const ScopePtr& scope, AstStatDeclareClass* declareClass);
void visit(const ScopePtr& scope, AstStatDeclareFunction* declareFunction);
2022-09-29 23:11:54 +01:00
void visit(const ScopePtr& scope, AstStatError* error);
2022-06-17 01:54:42 +01:00
2022-10-27 23:22:49 +01:00
InferencePack checkPack(const ScopePtr& scope, AstArray<AstExpr*> exprs, const std::vector<TypeId>& expectedTypes = {});
InferencePack checkPack(const ScopePtr& scope, AstExpr* expr, const std::vector<TypeId>& expectedTypes = {});
InferencePack checkPack(const ScopePtr& scope, AstExprCall* call, const std::vector<TypeId>& expectedTypes);
2022-06-03 21:32:20 +01:00
2022-06-17 01:54:42 +01:00
/**
* 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.
2022-09-23 19:32:10 +01:00
* @param expectedType the type of the expression that is expected from its
* surrounding context. Used to implement bidirectional type checking.
2022-06-17 01:54:42 +01:00
* @return the type of the expression.
*/
2022-11-04 17:02:37 +00:00
Inference check(const ScopePtr& scope, AstExpr* expr, std::optional<TypeId> expectedType = {}, bool forceSingleton = false);
2022-10-27 23:22:49 +01:00
2022-11-04 17:02:37 +00:00
Inference check(const ScopePtr& scope, AstExprConstantString* string, std::optional<TypeId> expectedType, bool forceSingleton);
Inference check(const ScopePtr& scope, AstExprConstantBool* bool_, std::optional<TypeId> expectedType, bool forceSingleton);
2022-10-27 23:22:49 +01:00
Inference check(const ScopePtr& scope, AstExprLocal* local);
Inference check(const ScopePtr& scope, AstExprGlobal* global);
Inference check(const ScopePtr& scope, AstExprIndexName* indexName);
Inference check(const ScopePtr& scope, AstExprIndexExpr* indexExpr);
Inference check(const ScopePtr& scope, AstExprUnary* unary);
Inference check(const ScopePtr& scope, AstExprBinary* binary, std::optional<TypeId> expectedType);
Inference check(const ScopePtr& scope, AstExprIfElse* ifElse, std::optional<TypeId> expectedType);
Inference check(const ScopePtr& scope, AstExprTypeAssertion* typeAssert);
Inference check(const ScopePtr& scope, AstExprTable* expr, std::optional<TypeId> expectedType);
2022-11-04 17:02:37 +00:00
std::tuple<TypeId, TypeId, ConnectiveId> checkBinary(const ScopePtr& scope, AstExprBinary* binary, std::optional<TypeId> expectedType);
2022-10-21 18:33:43 +01:00
TypePackId checkLValues(const ScopePtr& scope, AstArray<AstExpr*> exprs);
TypeId checkLValue(const ScopePtr& scope, AstExpr* expr);
2022-07-01 00:29:02 +01:00
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).
2022-07-29 04:41:13 +01:00
ScopePtr signatureScope;
2022-07-01 00:29:02 +01:00
// The scope that encompasses the function's body. Is a child scope of
// signatureScope, if present.
2022-07-29 04:41:13 +01:00
ScopePtr bodyScope;
2022-07-01 00:29:02 +01:00
};
2022-12-02 10:46:05 +00:00
FunctionSignature checkFunctionSignature(const ScopePtr& parent, AstExprFunction* fn, std::optional<TypeId> expectedType = {});
2022-06-17 01:54:42 +01:00
/**
* 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.
*/
2022-07-29 04:41:13 +01:00
void checkFunctionBody(const ScopePtr& scope, AstExprFunction* fn);
2022-06-24 02:44:07 +01:00
/**
* Resolves a type from its AST annotation.
* @param scope the scope that the type annotation appears within.
* @param ty the AST annotation to resolve.
2022-08-04 22:27:28 +01:00
* @param topLevel whether the annotation is a "top-level" annotation.
2022-06-24 02:44:07 +01:00
* @return the type of the AST annotation.
**/
2022-08-04 22:27:28 +01:00
TypeId resolveType(const ScopePtr& scope, AstType* ty, bool topLevel = false);
2022-06-24 02:44:07 +01:00
/**
* 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.
**/
2022-07-29 04:41:13 +01:00
TypePackId resolveTypePack(const ScopePtr& scope, AstTypePack* tp);
2022-07-01 00:29:02 +01:00
2022-07-29 04:41:13 +01:00
TypePackId resolveTypePack(const ScopePtr& scope, const AstTypeList& list);
2022-07-01 00:29:02 +01:00
2022-07-29 04:41:13 +01:00
std::vector<std::pair<Name, GenericTypeDefinition>> createGenerics(const ScopePtr& scope, AstArray<AstGenericType> generics);
std::vector<std::pair<Name, GenericTypePackDefinition>> createGenericPacks(const ScopePtr& scope, AstArray<AstGenericTypePack> packs);
2022-06-24 02:44:07 +01:00
2022-10-27 23:22:49 +01:00
Inference flattenPack(const ScopePtr& scope, Location location, InferencePack pack);
2022-07-01 00:29:02 +01:00
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.
*/
2022-07-29 04:41:13 +01:00
void prepopulateGlobalScope(const ScopePtr& globalScope, AstStatBlock* program);
2022-06-03 21:32:20 +01:00
};
2022-11-10 22:04:44 +00:00
/** Borrow a vector of pointers from a vector of owning pointers to constraints.
2022-06-17 01:54:42 +01:00
*/
2022-11-10 22:04:44 +00:00
std::vector<NotNull<Constraint>> borrowConstraints(const std::vector<ConstraintPtr>& constraints);
2022-06-03 21:32:20 +01:00
} // namespace Luau