luau/Analysis/include/Luau/ConstraintSolver.h

127 lines
4.9 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/Error.h"
#include "Luau/Variant.h"
2022-06-17 08:54:42 +08:00
#include "Luau/Constraint.h"
#include "Luau/ConstraintSolverLogger.h"
2022-06-04 04:32:20 +08:00
#include "Luau/TypeVar.h"
#include <vector>
namespace Luau
{
// TypeId, TypePackId, or Constraint*. It is impossible to know which, but we
// never dereference this pointer.
using BlockedConstraintId = const void*;
struct ConstraintSolver
{
TypeArena* arena;
InternalErrorReporter iceReporter;
2022-06-17 08:54:42 +08:00
// The entire set of constraints that the solver is trying to resolve. It
// 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;
2022-07-29 11:41:13 +08:00
NotNull<Scope> rootScope;
2022-06-04 04:32:20 +08:00
// This includes every constraint that has not been fully solved.
// A constraint can be both blocked and unsolved, for instance.
2022-06-17 08:54:42 +08:00
std::vector<NotNull<const Constraint>> unsolvedConstraints;
2022-06-04 04:32:20 +08:00
// A mapping of constraint pointer to how many things the constraint is
// blocked on. Can be empty or 0 for constraints that are not blocked on
// anything.
2022-06-17 08:54:42 +08:00
std::unordered_map<NotNull<const Constraint>, size_t> blockedConstraints;
2022-06-04 04:32:20 +08:00
// A mapping of type/pack pointers to the constraints they block.
2022-06-17 08:54:42 +08:00
std::unordered_map<BlockedConstraintId, std::vector<NotNull<const Constraint>>> blocked;
ConstraintSolverLogger logger;
2022-06-04 04:32:20 +08:00
2022-07-29 11:41:13 +08:00
explicit ConstraintSolver(TypeArena* arena, NotNull<Scope> rootScope);
2022-06-04 04:32:20 +08:00
/**
* Attempts to dispatch all pending constraints and reach a type solution
2022-06-17 08:54:42 +08:00
* that satisfies all of the constraints.
2022-06-04 04:32:20 +08:00
**/
void run();
bool done();
2022-07-01 07:29:02 +08:00
/** 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.
*/
2022-06-17 08:54:42 +08:00
bool tryDispatch(NotNull<const Constraint> c, bool force);
2022-07-01 07:29:02 +08:00
2022-06-17 08:54:42 +08:00
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);
2022-07-01 07:29:02 +08:00
bool tryDispatch(const UnaryConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const BinaryConstraint& c, NotNull<const Constraint> constraint, bool force);
2022-06-24 09:44:07 +08:00
bool tryDispatch(const NameConstraint& c, NotNull<const Constraint> constraint);
2022-06-04 04:32:20 +08:00
2022-06-17 08:54:42 +08:00
void block(NotNull<const Constraint> target, NotNull<const Constraint> constraint);
2022-06-04 04:32:20 +08:00
/**
2022-06-17 08:54:42 +08:00
* Block a constraint on the resolution of a TypeVar.
* @returns false always. This is just to allow tryDispatch to return the result of block()
*/
bool block(TypeId target, NotNull<const Constraint> constraint);
bool block(TypePackId target, NotNull<const Constraint> constraint);
2022-06-04 04:32:20 +08:00
2022-06-17 08:54:42 +08:00
void unblock(NotNull<const Constraint> progressed);
2022-06-04 04:32:20 +08:00
void unblock(TypeId progressed);
void unblock(TypePackId progressed);
2022-06-17 08:54:42 +08:00
/**
* @returns true if the TypeId is in a blocked state.
*/
bool isBlocked(TypeId ty);
2022-06-04 04:32:20 +08:00
/**
* Returns whether the constraint is blocked on anything.
* @param constraint the constraint to check.
*/
2022-06-17 08:54:42 +08:00
bool isBlocked(NotNull<const Constraint> constraint);
2022-06-04 04:32:20 +08:00
/**
* Creates a new Unifier and performs a single unification operation. Commits
2022-06-17 08:54:42 +08:00
* the result.
2022-06-04 04:32:20 +08:00
* @param subType the sub-type to unify.
* @param superType the super-type to unify.
*/
2022-06-24 09:44:07 +08:00
void unify(TypeId subType, TypeId superType);
2022-06-04 04:32:20 +08:00
/**
* Creates a new Unifier and performs a single unification operation. Commits
2022-06-17 08:54:42 +08:00
* the result.
2022-06-04 04:32:20 +08:00
* @param subPack the sub-type pack to unify.
* @param superPack the super-type pack to unify.
*/
2022-06-24 09:44:07 +08:00
void unify(TypePackId subPack, TypePackId superPack);
2022-06-17 08:54:42 +08:00
private:
/**
* Marks a constraint as being blocked on a type or type pack. The constraint
* solver will not attempt to dispatch blocked constraints until their
* dependencies have made progress.
* @param target the type or type pack pointer that the constraint is blocked on.
* @param constraint the constraint to block.
**/
void block_(BlockedConstraintId target, NotNull<const Constraint> constraint);
/**
* Informs the solver that progress has been made on a type or type pack. The
* solver will wake up all constraints that are blocked on the type or type pack,
* and will resume attempting to dispatch them.
* @param progressed the type or type pack pointer that has progressed.
**/
void unblock_(BlockedConstraintId progressed);
2022-06-04 04:32:20 +08:00
};
2022-07-29 11:41:13 +08:00
void dump(NotNull<Scope> rootScope, struct ToStringOptions& opts);
2022-06-04 04:32:20 +08:00
} // namespace Luau