luau/Analysis/include/Luau/Unifier.h

194 lines
7.8 KiB
C
Raw Normal View History

// 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"
2022-09-09 05:44:50 +08:00
#include "Luau/ParseOptions.h"
2022-08-19 05:04:33 +08:00
#include "Luau/Scope.h"
2022-09-09 05:44:50 +08:00
#include "Luau/Substitution.h"
#include "Luau/TxnLog.h"
2022-05-20 07:46:52 +08:00
#include "Luau/TypeArena.h"
#include "Luau/UnifierSharedState.h"
2022-10-07 07:55:58 +08:00
#include "Normalize.h"
#include <unordered_set>
namespace Luau
{
enum Variance
{
Covariant,
Invariant
};
2022-02-25 07:15:41 +08:00
// A substitution which replaces singleton types by their wider types
struct Widen : Substitution
{
2023-01-04 01:33:19 +08:00
Widen(TypeArena* arena, NotNull<BuiltinTypes> builtinTypes)
2022-02-25 07:15:41 +08:00
: Substitution(TxnLog::empty(), arena)
2023-01-04 01:33:19 +08:00
, builtinTypes(builtinTypes)
2022-02-25 07:15:41 +08:00
{
}
2023-01-04 01:33:19 +08:00
NotNull<BuiltinTypes> builtinTypes;
2022-09-09 05:44:50 +08:00
2022-02-25 07:15:41 +08:00
bool isDirty(TypeId ty) override;
bool isDirty(TypePackId ty) override;
TypeId clean(TypeId ty) override;
TypePackId clean(TypePackId ty) override;
bool ignoreChildren(TypeId ty) override;
2022-05-27 04:33:48 +08:00
TypeId operator()(TypeId ty);
TypePackId operator()(TypePackId ty);
2022-02-25 07:15:41 +08:00
};
2023-07-28 19:37:00 +08:00
/**
* Normally, when we unify table properties, we must do so invariantly, but we
* can introduce a special exception: If the table property in the subtype
* position arises from a literal expression, it is safe to instead perform a
* covariant check.
*
* This is very useful for typechecking cases where table literals (and trees of
* table literals) are passed directly to functions.
*
* In this case, we know that the property has no other name referring to it and
* so it is perfectly safe for the function to mutate the table any way it
* wishes.
*/
using LiteralProperties = DenseHashSet<Name>;
2022-02-25 07:15:41 +08:00
// TODO: Use this more widely.
struct UnifierOptions
{
bool isFunctionCall = false;
};
struct Unifier
{
TypeArena* const types;
2023-01-04 01:33:19 +08:00
NotNull<BuiltinTypes> builtinTypes;
2022-10-07 07:55:58 +08:00
NotNull<Normalizer> normalizer;
2022-08-19 05:04:33 +08:00
NotNull<Scope> scope; // const Scope maybe
TxnLog log;
2023-03-17 22:59:30 +08:00
bool failure = false;
ErrorVec errors;
Location location;
Variance variance = Covariant;
2023-03-03 21:45:38 +08:00
bool normalize = true; // Normalize unions and intersections if necessary
bool checkInhabited = true; // Normalize types to check if they are inhabited
CountMismatch::Context ctx = CountMismatch::Arg;
2023-05-12 20:15:01 +08:00
// If true, generics act as free types when unifying.
bool hideousFixMeGenericsAreActuallyFree = false;
UnifierSharedState& sharedState;
2023-02-25 02:24:22 +08:00
// When the Unifier is forced to unify two blocked types (or packs), they
// get added to these vectors. The ConstraintSolver can use this to know
// when it is safe to reattempt dispatching a constraint.
std::vector<TypeId> blockedTypes;
std::vector<TypePackId> blockedTypePacks;
2023-07-14 23:57:16 +08:00
Unifier(NotNull<Normalizer> normalizer, NotNull<Scope> scope, const Location& location, Variance variance, TxnLog* parentLog = nullptr);
2023-05-12 20:15:01 +08:00
// Configure the Unifier to test for scope subsumption via embedded Scope
// pointers rather than TypeLevels.
2023-07-28 19:37:00 +08:00
void enableNewSolver();
2023-05-12 20:15:01 +08:00
// Test whether the two type vars unify. Never commits the result.
2022-01-07 06:10:07 +08:00
ErrorVec canUnify(TypeId subTy, TypeId superTy);
ErrorVec canUnify(TypePackId subTy, TypePackId superTy, bool isFunctionCall = false);
2022-01-07 06:10:07 +08:00
/** Attempt to unify.
* 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.
*/
2023-09-16 00:27:45 +08:00
void tryUnify(
TypeId subTy, TypeId superTy, bool isFunctionCall = false, bool isIntersection = false, const LiteralProperties* aliasableMap = nullptr);
private:
2023-09-16 00:27:45 +08:00
void tryUnify_(
TypeId subTy, TypeId superTy, bool isFunctionCall = false, bool isIntersection = false, const LiteralProperties* aliasableMap = nullptr);
2023-01-04 01:33:19 +08:00
void tryUnifyUnionWithType(TypeId subTy, const UnionType* uv, TypeId superTy);
2023-03-11 03:20:04 +08:00
// Traverse the two types provided and block on any BlockedTypes we find.
// Returns true if any types were blocked on.
2023-03-17 22:59:30 +08:00
bool DEPRECATED_blockOnBlockedTypes(TypeId subTy, TypeId superTy);
2023-03-11 03:20:04 +08:00
2023-01-04 01:33:19 +08:00
void tryUnifyTypeWithUnion(TypeId subTy, TypeId superTy, const UnionType* uv, bool cacheEnabled, bool isFunctionCall);
void tryUnifyTypeWithIntersection(TypeId subTy, TypeId superTy, const IntersectionType* uv);
void tryUnifyIntersectionWithType(TypeId subTy, const IntersectionType* uv, TypeId superTy, bool cacheEnabled, bool isFunctionCall);
2022-10-14 06:59:53 +08:00
void tryUnifyNormalizedTypes(TypeId subTy, TypeId superTy, const NormalizedType& subNorm, const NormalizedType& superNorm, std::string reason,
std::optional<TypeError> error = std::nullopt);
2022-01-07 06:10:07 +08:00
void tryUnifyPrimitives(TypeId subTy, TypeId superTy);
void tryUnifySingletons(TypeId subTy, TypeId superTy);
void tryUnifyFunctions(TypeId subTy, TypeId superTy, bool isFunctionCall = false);
2023-07-28 19:37:00 +08:00
void tryUnifyTables(TypeId subTy, TypeId superTy, bool isIntersection = false, const LiteralProperties* aliasableMap = nullptr);
2022-07-15 06:39:35 +08:00
void tryUnifyScalarShape(TypeId subTy, TypeId superTy, bool reversed);
2022-01-07 06:10:07 +08:00
void tryUnifyWithMetatable(TypeId subTy, TypeId superTy, bool reversed);
void tryUnifyWithClass(TypeId subTy, TypeId superTy, bool reversed);
2023-02-03 20:34:12 +08:00
void tryUnifyNegations(TypeId subTy, TypeId superTy);
2022-02-25 07:15:41 +08:00
2022-10-07 07:55:58 +08:00
TypePackId tryApplyOverloadedFunction(TypeId function, const NormalizedFunctionType& overloads, TypePackId args);
2022-02-25 07:15:41 +08:00
TypeId widen(TypeId ty);
2022-03-18 08:06:25 +08:00
TypePackId widen(TypePackId tp);
TypeId deeplyOptional(TypeId ty, std::unordered_map<TypeId, TypeId> seen = {});
2022-02-25 07:15:41 +08:00
2022-03-25 05:49:08 +08:00
bool canCacheResult(TypeId subTy, TypeId superTy);
void cacheResult(TypeId subTy, TypeId superTy, size_t prevErrorCount);
public:
2022-01-07 06:10:07 +08:00
void tryUnify(TypePackId subTy, TypePackId superTy, bool isFunctionCall = false);
private:
2022-01-07 06:10:07 +08:00
void tryUnify_(TypePackId subTy, TypePackId superTy, bool isFunctionCall = false);
void tryUnifyVariadics(TypePackId subTy, TypePackId superTy, bool reversed, int subOffset = 0);
2022-01-07 06:10:07 +08:00
void tryUnifyWithAny(TypeId subTy, TypeId anyTy);
void tryUnifyWithAny(TypePackId subTy, TypePackId anyTp);
std::optional<TypeId> findTablePropertyRespectingMeta(TypeId lhsType, Name name);
2022-12-02 18:46:05 +08:00
TxnLog combineLogsIntoIntersection(std::vector<TxnLog> logs);
TxnLog combineLogsIntoUnion(std::vector<TxnLog> logs);
public:
2022-08-12 04:42:54 +08:00
// Returns true if the type "needle" already occurs within "haystack" and reports an "infinite type error"
2023-04-14 20:05:27 +08:00
bool occursCheck(TypeId needle, TypeId haystack, bool reversed);
2022-08-12 04:42:54 +08:00
bool occursCheck(DenseHashSet<TypeId>& seen, TypeId needle, TypeId haystack);
2023-04-14 20:05:27 +08:00
bool occursCheck(TypePackId needle, TypePackId haystack, bool reversed);
2022-08-12 04:42:54 +08:00
bool occursCheck(DenseHashSet<TypePackId>& seen, TypePackId needle, TypePackId haystack);
Unifier makeChildUnifier();
2022-04-15 05:57:15 +08:00
void reportError(TypeError err);
2022-11-05 01:02:37 +08:00
LUAU_NOINLINE void reportError(Location location, TypeErrorData data);
2022-01-28 05:29:34 +08:00
private:
2022-12-02 18:46:05 +08:00
TypeMismatch::Context mismatchContext();
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);
[[noreturn]] void ice(const std::string& message, const Location& location);
[[noreturn]] void ice(const std::string& message);
// Available after regular type pack unification errors
std::optional<int> firstPackErrorPos;
2023-05-12 20:15:01 +08:00
2023-07-28 19:37:00 +08:00
// If true, we do a bunch of small things differently to work better with
// the new type inference engine. Most notably, we use the Scope hierarchy
// directly rather than using TypeLevels.
bool useNewSolver = false;
};
2022-09-30 06:11:54 +08:00
void promoteTypeLevels(TxnLog& log, const TypeArena* arena, TypeLevel minLevel, Scope* outerScope, bool useScope, TypePackId tp);
2023-03-03 21:45:38 +08:00
std::optional<TypeError> hasUnificationTooComplex(const ErrorVec& errors);
2023-05-06 03:57:12 +08:00
std::optional<TypeError> hasCountMismatch(const ErrorVec& errors);
2022-04-15 05:57:15 +08:00
} // namespace Luau