2021-10-30 04:25:12 +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/Location.h"
|
|
|
|
#include "Luau/TxnLog.h"
|
|
|
|
#include "Luau/TypeInfer.h"
|
|
|
|
#include "Luau/Module.h" // FIXME: For TypeArena. It merits breaking out into its own header.
|
2021-11-05 10:42:00 +08:00
|
|
|
#include "Luau/UnifierSharedState.h"
|
2021-10-30 04:25:12 +08:00
|
|
|
|
|
|
|
#include <unordered_set>
|
|
|
|
|
|
|
|
namespace Luau
|
|
|
|
{
|
|
|
|
|
|
|
|
enum Variance
|
|
|
|
{
|
|
|
|
Covariant,
|
|
|
|
Invariant
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Unifier
|
|
|
|
{
|
|
|
|
TypeArena* const types;
|
|
|
|
Mode mode;
|
|
|
|
ScopePtr globalScope; // sigh. Needed solely to get at string's metatable.
|
|
|
|
|
|
|
|
TxnLog log;
|
|
|
|
ErrorVec errors;
|
|
|
|
Location location;
|
|
|
|
Variance variance = Covariant;
|
|
|
|
CountMismatch::Context ctx = CountMismatch::Arg;
|
|
|
|
|
2021-11-05 10:42:00 +08:00
|
|
|
UnifierSharedState& sharedState;
|
2021-10-30 04:25:12 +08:00
|
|
|
|
2021-11-05 10:42:00 +08:00
|
|
|
Unifier(TypeArena* types, Mode mode, ScopePtr globalScope, const Location& location, Variance variance, UnifierSharedState& sharedState);
|
|
|
|
Unifier(TypeArena* types, Mode mode, ScopePtr globalScope, std::vector<std::pair<TypeId, TypeId>>* sharedSeen, const Location& location,
|
2021-12-03 07:20:08 +08:00
|
|
|
Variance variance, UnifierSharedState& sharedState);
|
2021-10-30 04:25:12 +08:00
|
|
|
|
|
|
|
// Test whether the two type vars unify. Never commits the result.
|
|
|
|
ErrorVec canUnify(TypeId superTy, TypeId subTy);
|
|
|
|
ErrorVec canUnify(TypePackId superTy, TypePackId subTy, bool isFunctionCall = false);
|
|
|
|
|
|
|
|
/** Attempt to unify left with right.
|
|
|
|
* Populate the vector errors with any type errors that may arise.
|
|
|
|
* Populate the transaction log with the set of TypeIds that need to be reset to undo the unification attempt.
|
|
|
|
*/
|
|
|
|
void tryUnify(TypeId superTy, TypeId subTy, bool isFunctionCall = false, bool isIntersection = false);
|
|
|
|
|
|
|
|
private:
|
|
|
|
void tryUnify_(TypeId superTy, TypeId subTy, bool isFunctionCall = false, bool isIntersection = false);
|
|
|
|
void tryUnifyPrimitives(TypeId superTy, TypeId subTy);
|
2021-11-19 06:21:07 +08:00
|
|
|
void tryUnifySingletons(TypeId superTy, TypeId subTy);
|
2021-10-30 04:25:12 +08:00
|
|
|
void tryUnifyFunctions(TypeId superTy, TypeId subTy, bool isFunctionCall = false);
|
|
|
|
void tryUnifyTables(TypeId left, TypeId right, bool isIntersection = false);
|
2021-11-05 10:07:18 +08:00
|
|
|
void DEPRECATED_tryUnifyTables(TypeId left, TypeId right, bool isIntersection = false);
|
2021-10-30 04:25:12 +08:00
|
|
|
void tryUnifyFreeTable(TypeId free, TypeId other);
|
|
|
|
void tryUnifySealedTables(TypeId left, TypeId right, bool isIntersection);
|
|
|
|
void tryUnifyWithMetatable(TypeId metatable, TypeId other, bool reversed);
|
|
|
|
void tryUnifyWithClass(TypeId superTy, TypeId subTy, bool reversed);
|
|
|
|
void tryUnify(const TableIndexer& superIndexer, const TableIndexer& subIndexer);
|
2021-11-05 10:42:00 +08:00
|
|
|
TypeId deeplyOptional(TypeId ty, std::unordered_map<TypeId, TypeId> seen = {});
|
|
|
|
void cacheResult(TypeId superTy, TypeId subTy);
|
2021-10-30 04:25:12 +08:00
|
|
|
|
|
|
|
public:
|
|
|
|
void tryUnify(TypePackId superTy, TypePackId subTy, bool isFunctionCall = false);
|
|
|
|
|
|
|
|
private:
|
|
|
|
void tryUnify_(TypePackId superTy, TypePackId subTy, bool isFunctionCall = false);
|
|
|
|
void tryUnifyVariadics(TypePackId superTy, TypePackId subTy, bool reversed, int subOffset = 0);
|
|
|
|
|
|
|
|
void tryUnifyWithAny(TypeId any, TypeId ty);
|
|
|
|
void tryUnifyWithAny(TypePackId any, TypePackId ty);
|
|
|
|
|
|
|
|
std::optional<TypeId> findTablePropertyRespectingMeta(TypeId lhsType, Name name);
|
|
|
|
|
|
|
|
public:
|
|
|
|
// Report an "infinite type error" if the type "needle" already occurs within "haystack"
|
|
|
|
void occursCheck(TypeId needle, TypeId haystack);
|
2021-12-03 07:20:08 +08:00
|
|
|
void occursCheck(DenseHashSet<TypeId>& seen, TypeId needle, TypeId haystack);
|
2021-10-30 04:25:12 +08:00
|
|
|
void occursCheck(TypePackId needle, TypePackId haystack);
|
2021-12-03 07:20:08 +08:00
|
|
|
void occursCheck(DenseHashSet<TypePackId>& seen, TypePackId needle, TypePackId haystack);
|
2021-10-30 04:25:12 +08:00
|
|
|
|
|
|
|
Unifier makeChildUnifier();
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool isNonstrictMode() const;
|
|
|
|
|
|
|
|
void checkChildUnifierTypeMismatch(const ErrorVec& innerErrors, TypeId wantedType, TypeId givenType);
|
2021-11-12 10:12:39 +08:00
|
|
|
void checkChildUnifierTypeMismatch(const ErrorVec& innerErrors, const std::string& prop, TypeId wantedType, TypeId givenType);
|
2021-10-30 04:25:12 +08:00
|
|
|
|
|
|
|
[[noreturn]] void ice(const std::string& message, const Location& location);
|
|
|
|
[[noreturn]] void ice(const std::string& message);
|
2021-12-11 05:17:10 +08:00
|
|
|
|
|
|
|
// Available after regular type pack unification errors
|
|
|
|
std::optional<int> firstPackErrorPos;
|
2021-10-30 04:25:12 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Luau
|