luau/Analysis/include/Luau/ConstraintGenerator.h

386 lines
17 KiB
C
Raw Normal View History

2022-06-04 04:32:20 +08: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-06-17 08:54:42 +08:00
#include "Luau/Constraint.h"
2023-03-17 22:59:30 +08:00
#include "Luau/ControlFlow.h"
2022-12-02 18:46:05 +08:00
#include "Luau/DataFlowGraph.h"
2023-10-21 04:36:26 +08:00
#include "Luau/InsertionOrderedMap.h"
2022-06-04 04:32:20 +08:00
#include "Luau/Module.h"
2022-09-02 07:00:14 +08:00
#include "Luau/ModuleResolver.h"
2023-10-21 04:36:26 +08:00
#include "Luau/Normalize.h"
2022-06-17 08:54:42 +08:00
#include "Luau/NotNull.h"
2023-03-17 22:59:30 +08:00
#include "Luau/Refinement.h"
2022-06-04 04:32:20 +08:00
#include "Luau/Symbol.h"
2023-10-21 04:36:26 +08:00
#include "Luau/TypeFwd.h"
2023-04-28 19:55:55 +08:00
#include "Luau/TypeUtils.h"
2022-06-04 04:32:20 +08:00
#include "Luau/Variant.h"
2023-10-21 04:36:26 +08:00
#include "Luau/Normalize.h"
2022-06-04 04:32:20 +08:00
2022-10-22 01:33:43 +08:00
#include <memory>
#include <vector>
#include <unordered_map>
2022-06-04 04:32:20 +08:00
namespace Luau
{
2022-07-29 11:41:13 +08:00
struct Scope;
using ScopePtr = std::shared_ptr<Scope>;
2022-06-04 04:32:20 +08:00
2022-09-09 05:44:50 +08:00
struct DcrLogger;
2022-10-28 06:22:49 +08:00
struct Inference
{
TypeId ty = nullptr;
2023-02-03 20:34:12 +08:00
RefinementId refinement = nullptr;
2022-10-28 06:22:49 +08:00
Inference() = default;
2023-02-03 20:34:12 +08:00
explicit Inference(TypeId ty, RefinementId refinement = nullptr)
2022-10-28 06:22:49 +08:00
: ty(ty)
2023-02-03 20:34:12 +08:00
, refinement(refinement)
2022-10-28 06:22:49 +08:00
{
}
};
struct InferencePack
{
TypePackId tp = nullptr;
2023-02-03 20:34:12 +08:00
std::vector<RefinementId> refinements;
2022-10-28 06:22:49 +08:00
InferencePack() = default;
2023-02-03 20:34:12 +08:00
explicit InferencePack(TypePackId tp, const std::vector<RefinementId>& refinements = {})
2022-10-28 06:22:49 +08:00
: tp(tp)
2023-02-03 20:34:12 +08:00
, refinements(refinements)
2022-10-28 06:22:49 +08:00
{
}
};
2023-11-04 03:47:28 +08:00
struct ConstraintGenerator
2022-06-04 04:32:20 +08:00
{
// 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 11:41:13 +08:00
std::vector<std::pair<Location, ScopePtr>> scopes;
2022-07-01 07:29:02 +08:00
2022-08-12 04:42:54 +08:00
ModulePtr module;
2023-01-04 01:33:19 +08:00
NotNull<BuiltinTypes> builtinTypes;
2022-07-01 07:29:02 +08:00
const NotNull<TypeArena> arena;
2022-06-04 04:32:20 +08:00
// The root scope of the module we're generating constraints for.
2023-11-04 03:47:28 +08:00
// This is null when the CG is initially constructed.
2022-07-29 11:41:13 +08:00
Scope* rootScope;
2022-11-11 06:04:44 +08:00
2024-03-16 05:01:00 +08:00
TypeContext typeContext = TypeContext::Default;
2023-10-21 04:36:26 +08:00
struct InferredBinding
{
Scope* scope;
Location location;
TypeIds types;
};
2023-11-18 02:15:31 +08:00
// Some locals have multiple type states. We wish for Scope::bindings to
// map each local name onto the union of every type that the local can have
// over its lifetime, so we use this map to accumulate the set of types it
// might have.
//
// See the functions recordInferredBinding and fillInInferredBindings.
DenseHashMap<Symbol, InferredBinding> inferredBindings{{}};
2023-10-14 03:38:31 +08:00
2022-11-11 06:04:44 +08: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;
2023-02-03 20:34:12 +08:00
// The private scope of type aliases for which the type parameters belong to.
2022-08-05 05:27:28 +08:00
DenseHashMap<const AstStatTypeAlias*, ScopePtr> astTypeAliasDefiningScopes{nullptr};
2022-12-10 02:07:25 +08:00
2022-10-22 01:33:43 +08:00
NotNull<const DataFlowGraph> dfg;
2023-02-03 20:34:12 +08:00
RefinementArena refinementArena;
2022-06-04 04:32:20 +08:00
2022-07-01 07:29:02 +08:00
int recursionCount = 0;
// It is pretty uncommon for constraint generation to itself produce errors, but it can happen.
std::vector<TypeError> errors;
// Needed to be able to enable error-suppression preservation for immediate refinements.
NotNull<Normalizer> normalizer;
2022-09-02 07:00:14 +08:00
// Needed to resolve modules to make 'require' import types properly.
NotNull<ModuleResolver> moduleResolver;
2022-07-01 07:29:02 +08:00
// Occasionally constraint generation needs to produce an ICE.
const NotNull<InternalErrorReporter> ice;
2022-08-12 04:42:54 +08:00
ScopePtr globalScope;
2023-04-28 19:55:55 +08:00
std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope;
2023-07-28 19:37:00 +08:00
std::vector<RequireCycle> requireCycles;
2023-04-28 19:55:55 +08:00
2022-09-09 05:44:50 +08:00
DcrLogger* logger;
2022-07-01 07:29:02 +08:00
2024-02-16 09:25:31 +08:00
ConstraintGenerator(ModulePtr module, NotNull<Normalizer> normalizer, NotNull<ModuleResolver> moduleResolver, NotNull<BuiltinTypes> builtinTypes,
NotNull<InternalErrorReporter> ice, const ScopePtr& globalScope, std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope,
DcrLogger* logger, NotNull<DataFlowGraph> dfg, std::vector<RequireCycle> requireCycles);
2022-06-04 04:32:20 +08:00
2023-09-30 08:22:06 +08:00
/**
2023-11-04 03:47:28 +08:00
* The entry point to the ConstraintGenerator. This will construct a set
2023-09-30 08:22:06 +08:00
* of scopes, constraints, and free types that can be solved later.
* @param block the root block to generate constraints for.
*/
void visitModuleRoot(AstStatBlock* block);
private:
2024-02-24 02:40:00 +08:00
std::vector<std::vector<TypeId>> interiorTypes;
2022-06-04 04:32:20 +08:00
/**
* Fabricates a new free type belonging to a given scope.
2022-07-01 07:29:02 +08:00
* @param scope the scope the free type belongs to.
2022-06-04 04:32:20 +08:00
*/
2022-07-29 11:41:13 +08:00
TypeId freshType(const ScopePtr& scope);
2022-06-04 04:32:20 +08:00
/**
* Fabricates a new free type pack belonging to a given scope.
2022-07-01 07:29:02 +08:00
* @param scope the scope the free type pack belongs to.
2022-06-04 04:32:20 +08:00
*/
2022-07-29 11:41:13 +08:00
TypePackId freshTypePack(const ScopePtr& scope);
2022-06-04 04:32:20 +08:00
2024-02-03 02:20:03 +08:00
/**
* Allocate a new TypePack with the given head and tail.
*
* Avoids allocating 0-length type packs:
*
* If the head is non-empty, allocate and return a type pack with the given
* head and tail.
* If the head is empty and tail is non-empty, return *tail.
* If both the head and tail are empty, return an empty type pack.
*/
TypePackId addTypePack(std::vector<TypeId> head, std::optional<TypePackId> tail);
2022-06-04 04:32:20 +08:00
/**
* Fabricates a scope that is a child of another scope.
2022-08-19 05:04:33 +08:00
* @param node the lexical node that the scope belongs to.
2022-06-04 04:32:20 +08:00
* @param parent the parent scope of the new scope. Must not be null.
*/
2022-08-19 05:04:33 +08:00
ScopePtr childScope(AstNode* node, const ScopePtr& parent);
2022-06-04 04:32:20 +08:00
2024-04-26 04:57:23 +08:00
std::optional<TypeId> lookup(const ScopePtr& scope, Location location, DefId def, bool prototype = true);
2023-11-11 02:05:48 +08:00
2022-06-04 04:32:20 +08:00
/**
* Adds a new constraint with no dependencies to a given scope.
2022-07-01 07:29:02 +08:00
* @param scope the scope to add the constraint to.
2022-06-04 04:32:20 +08:00
* @param cv the constraint variant to add.
2022-10-22 01:33:43 +08:00
* @return the pointer to the inserted constraint
2022-06-04 04:32:20 +08:00
*/
2022-10-22 01:33:43 +08:00
NotNull<Constraint> addConstraint(const ScopePtr& scope, const Location& location, ConstraintV cv);
2022-06-04 04:32:20 +08: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-22 01:33:43 +08:00
* @return the pointer to the inserted constraint
2022-06-04 04:32:20 +08:00
*/
2022-10-22 01:33:43 +08:00
NotNull<Constraint> addConstraint(const ScopePtr& scope, std::unique_ptr<Constraint> c);
2022-06-04 04:32:20 +08:00
2023-10-21 04:36:26 +08:00
struct RefinementPartition
{
// Types that we want to intersect against the type of the expression.
std::vector<TypeId> discriminantTypes;
// Sometimes the type we're discriminating against is implicitly nil.
bool shouldAppendNilType = false;
};
using RefinementContext = InsertionOrderedMap<DefId, RefinementPartition>;
2024-02-16 09:25:31 +08:00
void unionRefinements(const ScopePtr& scope, Location location, const RefinementContext& lhs, const RefinementContext& rhs,
RefinementContext& dest, std::vector<ConstraintV>* constraints);
void computeRefinement(const ScopePtr& scope, Location location, RefinementId refinement, RefinementContext* refis, bool sense, bool eq,
std::vector<ConstraintV>* constraints);
2023-02-03 20:34:12 +08:00
void applyRefinements(const ScopePtr& scope, Location location, RefinementId refinement);
2022-11-05 01:02:37 +08:00
2023-03-17 22:59:30 +08:00
ControlFlow visitBlockWithoutChildScope(const ScopePtr& scope, AstStatBlock* block);
ControlFlow visit(const ScopePtr& scope, AstStat* stat);
ControlFlow visit(const ScopePtr& scope, AstStatBlock* block);
ControlFlow visit(const ScopePtr& scope, AstStatLocal* local);
ControlFlow visit(const ScopePtr& scope, AstStatFor* for_);
ControlFlow visit(const ScopePtr& scope, AstStatForIn* forIn);
ControlFlow visit(const ScopePtr& scope, AstStatWhile* while_);
ControlFlow visit(const ScopePtr& scope, AstStatRepeat* repeat);
ControlFlow visit(const ScopePtr& scope, AstStatLocalFunction* function);
ControlFlow visit(const ScopePtr& scope, AstStatFunction* function);
ControlFlow visit(const ScopePtr& scope, AstStatReturn* ret);
ControlFlow visit(const ScopePtr& scope, AstStatAssign* assign);
ControlFlow visit(const ScopePtr& scope, AstStatCompoundAssign* assign);
ControlFlow visit(const ScopePtr& scope, AstStatIf* ifStatement);
ControlFlow visit(const ScopePtr& scope, AstStatTypeAlias* alias);
ControlFlow visit(const ScopePtr& scope, AstStatDeclareGlobal* declareGlobal);
ControlFlow visit(const ScopePtr& scope, AstStatDeclareClass* declareClass);
ControlFlow visit(const ScopePtr& scope, AstStatDeclareFunction* declareFunction);
ControlFlow visit(const ScopePtr& scope, AstStatError* error);
2022-06-17 08:54:42 +08:00
2023-02-17 22:53:37 +08:00
InferencePack checkPack(const ScopePtr& scope, AstArray<AstExpr*> exprs, const std::vector<std::optional<TypeId>>& expectedTypes = {});
2023-09-30 08:22:06 +08:00
InferencePack checkPack(
const ScopePtr& scope, AstExpr* expr, const std::vector<std::optional<TypeId>>& expectedTypes = {}, bool generalize = true);
2022-10-28 06:22:49 +08:00
2023-02-17 22:53:37 +08:00
InferencePack checkPack(const ScopePtr& scope, AstExprCall* call);
2022-06-04 04:32:20 +08:00
2022-06-17 08:54:42 +08: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-24 02:32:10 +08:00
* @param expectedType the type of the expression that is expected from its
* surrounding context. Used to implement bidirectional type checking.
2023-09-30 08:22:06 +08:00
* @param generalize If true, generalize any lambdas that are encountered.
2022-06-17 08:54:42 +08:00
* @return the type of the expression.
*/
2023-10-07 01:31:16 +08:00
Inference check(
const ScopePtr& scope, AstExpr* expr, std::optional<TypeId> expectedType = {}, bool forceSingleton = false, bool generalize = true);
2022-10-28 06:22:49 +08:00
2022-11-05 01:02:37 +08: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);
2023-10-07 01:31:16 +08:00
Inference check(const ScopePtr& scope, AstExprLocal* local);
2022-10-28 06:22:49 +08:00
Inference check(const ScopePtr& scope, AstExprGlobal* global);
2024-04-26 04:57:23 +08:00
Inference checkIndexName(const ScopePtr& scope, const RefinementKey* key, AstExpr* indexee, const std::string& index, Location indexLocation);
2022-10-28 06:22:49 +08:00
Inference check(const ScopePtr& scope, AstExprIndexName* indexName);
Inference check(const ScopePtr& scope, AstExprIndexExpr* indexExpr);
2023-09-30 08:22:06 +08:00
Inference check(const ScopePtr& scope, AstExprFunction* func, std::optional<TypeId> expectedType, bool generalize);
2022-10-28 06:22:49 +08:00
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);
2023-01-28 05:28:45 +08:00
Inference check(const ScopePtr& scope, AstExprInterpString* interpString);
2022-10-28 06:22:49 +08:00
Inference check(const ScopePtr& scope, AstExprTable* expr, std::optional<TypeId> expectedType);
2023-02-03 20:34:12 +08:00
std::tuple<TypeId, TypeId, RefinementId> checkBinary(const ScopePtr& scope, AstExprBinary* binary, std::optional<TypeId> expectedType);
2022-10-22 01:33:43 +08:00
2024-03-31 06:49:03 +08:00
struct LValueBounds
{
std::optional<TypeId> annotationTy;
std::optional<TypeId> assignedTy;
};
2024-04-12 18:44:40 +08:00
LValueBounds checkLValue(const ScopePtr& scope, AstExpr* expr);
LValueBounds checkLValue(const ScopePtr& scope, AstExprLocal* local);
2024-03-31 06:49:03 +08:00
LValueBounds checkLValue(const ScopePtr& scope, AstExprGlobal* global);
LValueBounds checkLValue(const ScopePtr& scope, AstExprIndexName* indexName);
LValueBounds checkLValue(const ScopePtr& scope, AstExprIndexExpr* indexExpr);
LValueBounds updateProperty(const ScopePtr& scope, AstExpr* expr);
2022-07-01 07:29:02 +08: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 11:41:13 +08:00
ScopePtr signatureScope;
2022-07-01 07:29:02 +08:00
// The scope that encompasses the function's body. Is a child scope of
// signatureScope, if present.
2022-07-29 11:41:13 +08:00
ScopePtr bodyScope;
2022-07-01 07:29:02 +08:00
};
2023-05-20 02:59:59 +08:00
FunctionSignature checkFunctionSignature(
const ScopePtr& parent, AstExprFunction* fn, std::optional<TypeId> expectedType = {}, std::optional<Location> originalName = {});
2022-06-17 08:54:42 +08: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 11:41:13 +08:00
void checkFunctionBody(const ScopePtr& scope, AstExprFunction* fn);
2022-06-24 09:44:07 +08: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.
2023-01-20 20:02:39 +08:00
* @param inTypeArguments whether we are resolving a type that's contained within type arguments, `<...>`.
2022-06-24 09:44:07 +08:00
* @return the type of the AST annotation.
**/
2023-03-03 21:45:38 +08:00
TypeId resolveType(const ScopePtr& scope, AstType* ty, bool inTypeArguments, bool replaceErrorWithFresh = false);
2022-06-24 09:44:07 +08: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.
2023-01-20 20:02:39 +08:00
* @param inTypeArguments whether we are resolving a type that's contained within type arguments, `<...>`.
2022-06-24 09:44:07 +08:00
* @return the type pack of the AST annotation.
**/
2023-03-03 21:45:38 +08:00
TypePackId resolveTypePack(const ScopePtr& scope, AstTypePack* tp, bool inTypeArguments, bool replaceErrorWithFresh = false);
2022-07-01 07:29:02 +08:00
2023-01-20 20:02:39 +08:00
/**
* Resolves a type pack from its AST annotation.
* @param scope the scope that the type annotation appears within.
* @param list the AST annotation to resolve.
* @param inTypeArguments whether we are resolving a type that's contained within type arguments, `<...>`.
* @return the type pack of the AST annotation.
**/
2023-03-03 21:45:38 +08:00
TypePackId resolveTypePack(const ScopePtr& scope, const AstTypeList& list, bool inTypeArguments, bool replaceErrorWithFresh = false);
2022-07-01 07:29:02 +08:00
2023-02-25 02:24:22 +08:00
/**
* Creates generic types given a list of AST definitions, resolving default
* types as required.
* @param scope the scope that the generics should belong to.
* @param generics the AST generics to create types for.
* @param useCache whether to use the generic type cache for the given
* scope.
* @param addTypes whether to add the types to the scope's
* privateTypeBindings map.
**/
2023-02-17 22:53:37 +08:00
std::vector<std::pair<Name, GenericTypeDefinition>> createGenerics(
2023-02-25 02:24:22 +08:00
const ScopePtr& scope, AstArray<AstGenericType> generics, bool useCache = false, bool addTypes = true);
/**
* Creates generic type packs given a list of AST definitions, resolving
* default type packs as required.
* @param scope the scope that the generic packs should belong to.
* @param generics the AST generics to create type packs for.
* @param useCache whether to use the generic type pack cache for the given
* scope.
* @param addTypes whether to add the types to the scope's
* privateTypePackBindings map.
**/
2023-02-17 22:53:37 +08:00
std::vector<std::pair<Name, GenericTypePackDefinition>> createGenericPacks(
2023-02-25 02:24:22 +08:00
const ScopePtr& scope, AstArray<AstGenericTypePack> packs, bool useCache = false, bool addTypes = true);
2022-06-24 09:44:07 +08:00
2022-10-28 06:22:49 +08:00
Inference flattenPack(const ScopePtr& scope, Location location, InferencePack pack);
2022-07-01 07:29:02 +08:00
void reportError(Location location, TypeErrorData err);
void reportCodeTooComplex(Location location);
2024-01-27 10:30:40 +08:00
// make a union type family of these two types
TypeId makeUnion(const ScopePtr& scope, Location location, TypeId lhs, TypeId rhs);
// make an intersect type family of these two types
TypeId makeIntersect(const ScopePtr& scope, Location location, TypeId lhs, TypeId rhs);
2022-07-01 07:29:02 +08:00
/** Scan the program for global definitions.
*
2023-11-04 03:47:28 +08:00
* ConstraintGenerator needs to differentiate between globals and accesses to undefined symbols. Doing this "for
2022-07-01 07:29:02 +08:00
* 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 11:41:13 +08:00
void prepopulateGlobalScope(const ScopePtr& globalScope, AstStatBlock* program);
2023-03-03 21:45:38 +08:00
2023-11-18 02:15:31 +08:00
// Record the fact that a particular local has a particular type in at least
// one of its states.
void recordInferredBinding(AstLocal* local, TypeId ty);
2023-10-14 03:38:31 +08:00
void fillInInferredBindings(const ScopePtr& globalScope, AstStatBlock* block);
2023-03-03 21:45:38 +08:00
/** Given a function type annotation, return a vector describing the expected types of the calls to the function
* For example, calling a function with annotation ((number) -> string & ((string) -> number))
* yields a vector of size 1, with value: [number | string]
*/
std::vector<std::optional<TypeId>> getExpectedCallTypesForFunctionOverloads(const TypeId fnType);
2024-03-31 06:49:03 +08:00
2024-05-17 06:22:22 +08:00
TypeId createTypeFamilyInstance(
const TypeFamily& family, std::vector<TypeId> typeArguments, std::vector<TypePackId> packArguments, const ScopePtr& scope, Location location);
2022-06-04 04:32:20 +08:00
};
2022-11-11 06:04:44 +08:00
/** Borrow a vector of pointers from a vector of owning pointers to constraints.
2022-06-17 08:54:42 +08:00
*/
2022-11-11 06:04:44 +08:00
std::vector<NotNull<Constraint>> borrowConstraints(const std::vector<ConstraintPtr>& constraints);
2022-06-04 04:32:20 +08:00
2023-03-03 21:45:38 +08:00
2022-06-04 04:32:20 +08:00
} // namespace Luau