2021-10-29 21:25:12 +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/Location.h"
|
2023-08-11 15:42:37 +01:00
|
|
|
#include "Luau/NotNull.h"
|
2023-01-04 20:53:17 +00:00
|
|
|
#include "Luau/Type.h"
|
2021-10-29 21:25:12 +01:00
|
|
|
#include "Luau/Variant.h"
|
2023-10-21 02:10:30 +01:00
|
|
|
#include "Luau/Ast.h"
|
|
|
|
|
|
|
|
#include <set>
|
2021-10-29 21:25:12 +01:00
|
|
|
|
|
|
|
namespace Luau
|
|
|
|
{
|
|
|
|
|
2022-12-09 19:57:01 +00:00
|
|
|
struct FileResolver;
|
|
|
|
struct TypeArena;
|
|
|
|
struct TypeError;
|
2022-12-02 18:09:59 +00:00
|
|
|
|
2021-10-29 21:25:12 +01:00
|
|
|
struct TypeMismatch
|
|
|
|
{
|
2022-12-02 18:09:59 +00:00
|
|
|
enum Context
|
|
|
|
{
|
|
|
|
CovariantContext,
|
|
|
|
InvariantContext
|
|
|
|
};
|
|
|
|
|
2021-11-12 14:27:34 +00:00
|
|
|
TypeMismatch() = default;
|
|
|
|
TypeMismatch(TypeId wantedType, TypeId givenType);
|
|
|
|
TypeMismatch(TypeId wantedType, TypeId givenType, std::string reason);
|
2022-10-07 01:23:29 +01:00
|
|
|
TypeMismatch(TypeId wantedType, TypeId givenType, std::string reason, std::optional<TypeError> error);
|
2021-11-12 14:27:34 +00:00
|
|
|
|
2022-12-02 18:09:59 +00:00
|
|
|
TypeMismatch(TypeId wantedType, TypeId givenType, Context context);
|
|
|
|
TypeMismatch(TypeId wantedType, TypeId givenType, std::string reason, Context context);
|
|
|
|
TypeMismatch(TypeId wantedType, TypeId givenType, std::string reason, std::optional<TypeError> error, Context context);
|
|
|
|
|
2021-11-12 14:27:34 +00:00
|
|
|
TypeId wantedType = nullptr;
|
|
|
|
TypeId givenType = nullptr;
|
2022-12-02 18:09:59 +00:00
|
|
|
Context context = CovariantContext;
|
2021-11-12 14:27:34 +00:00
|
|
|
|
|
|
|
std::string reason;
|
|
|
|
std::shared_ptr<TypeError> error;
|
2021-10-29 21:25:12 +01:00
|
|
|
|
|
|
|
bool operator==(const TypeMismatch& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct UnknownSymbol
|
|
|
|
{
|
|
|
|
enum Context
|
|
|
|
{
|
|
|
|
Binding,
|
|
|
|
Type,
|
|
|
|
};
|
|
|
|
Name name;
|
|
|
|
Context context;
|
|
|
|
|
|
|
|
bool operator==(const UnknownSymbol& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct UnknownProperty
|
|
|
|
{
|
|
|
|
TypeId table;
|
|
|
|
Name key;
|
|
|
|
|
|
|
|
bool operator==(const UnknownProperty& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct NotATable
|
|
|
|
{
|
|
|
|
TypeId ty;
|
|
|
|
|
|
|
|
bool operator==(const NotATable& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CannotExtendTable
|
|
|
|
{
|
|
|
|
enum Context
|
|
|
|
{
|
|
|
|
Property,
|
|
|
|
Indexer,
|
|
|
|
Metatable
|
|
|
|
};
|
|
|
|
TypeId tableType;
|
|
|
|
Context context;
|
|
|
|
Name prop;
|
|
|
|
|
|
|
|
bool operator==(const CannotExtendTable& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct OnlyTablesCanHaveMethods
|
|
|
|
{
|
|
|
|
TypeId tableType;
|
|
|
|
|
|
|
|
bool operator==(const OnlyTablesCanHaveMethods& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DuplicateTypeDefinition
|
|
|
|
{
|
|
|
|
Name name;
|
2022-09-29 23:23:10 +01:00
|
|
|
std::optional<Location> previousLocation;
|
2021-10-29 21:25:12 +01:00
|
|
|
|
|
|
|
bool operator==(const DuplicateTypeDefinition& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CountMismatch
|
|
|
|
{
|
|
|
|
enum Context
|
|
|
|
{
|
|
|
|
Arg,
|
2022-09-29 23:23:10 +01:00
|
|
|
FunctionResult,
|
|
|
|
ExprListResult,
|
2021-10-29 21:25:12 +01:00
|
|
|
Return,
|
|
|
|
};
|
|
|
|
size_t expected;
|
2022-09-15 23:38:17 +01:00
|
|
|
std::optional<size_t> maximum;
|
2021-10-29 21:25:12 +01:00
|
|
|
size_t actual;
|
|
|
|
Context context = Arg;
|
2022-03-24 22:04:14 +00:00
|
|
|
bool isVariadic = false;
|
2022-09-15 23:38:17 +01:00
|
|
|
std::string function;
|
2021-10-29 21:25:12 +01:00
|
|
|
|
|
|
|
bool operator==(const CountMismatch& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct FunctionDoesNotTakeSelf
|
|
|
|
{
|
|
|
|
bool operator==(const FunctionDoesNotTakeSelf& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct FunctionRequiresSelf
|
|
|
|
{
|
|
|
|
bool operator==(const FunctionRequiresSelf& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct OccursCheckFailed
|
|
|
|
{
|
|
|
|
bool operator==(const OccursCheckFailed& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct UnknownRequire
|
|
|
|
{
|
|
|
|
std::string modulePath;
|
|
|
|
|
|
|
|
bool operator==(const UnknownRequire& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IncorrectGenericParameterCount
|
|
|
|
{
|
|
|
|
Name name;
|
|
|
|
TypeFun typeFun;
|
|
|
|
size_t actualParameters;
|
2021-11-05 02:34:35 +00:00
|
|
|
size_t actualPackParameters;
|
2021-10-29 21:25:12 +01:00
|
|
|
|
|
|
|
bool operator==(const IncorrectGenericParameterCount& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SyntaxError
|
|
|
|
{
|
|
|
|
std::string message;
|
|
|
|
|
|
|
|
bool operator==(const SyntaxError& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CodeTooComplex
|
|
|
|
{
|
|
|
|
bool operator==(const CodeTooComplex&) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct UnificationTooComplex
|
|
|
|
{
|
|
|
|
bool operator==(const UnificationTooComplex&) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Could easily be folded into UnknownProperty with an extra field, std::set<Name> candidates.
|
|
|
|
// But for telemetry purposes, we want to have this be a distinct variant.
|
|
|
|
struct UnknownPropButFoundLikeProp
|
|
|
|
{
|
|
|
|
TypeId table;
|
|
|
|
Name key;
|
|
|
|
std::set<Name> candidates;
|
|
|
|
|
|
|
|
bool operator==(const UnknownPropButFoundLikeProp& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct GenericError
|
|
|
|
{
|
|
|
|
std::string message;
|
|
|
|
|
|
|
|
bool operator==(const GenericError& rhs) const;
|
|
|
|
};
|
|
|
|
|
2022-06-24 02:56:00 +01:00
|
|
|
struct InternalError
|
|
|
|
{
|
|
|
|
std::string message;
|
|
|
|
|
|
|
|
bool operator==(const InternalError& rhs) const;
|
|
|
|
};
|
|
|
|
|
2021-10-29 21:25:12 +01:00
|
|
|
struct CannotCallNonFunction
|
|
|
|
{
|
|
|
|
TypeId ty;
|
|
|
|
|
|
|
|
bool operator==(const CannotCallNonFunction& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ExtraInformation
|
|
|
|
{
|
|
|
|
std::string message;
|
|
|
|
bool operator==(const ExtraInformation& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DeprecatedApiUsed
|
|
|
|
{
|
|
|
|
std::string symbol;
|
|
|
|
std::string useInstead;
|
|
|
|
bool operator==(const DeprecatedApiUsed& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ModuleHasCyclicDependency
|
|
|
|
{
|
|
|
|
std::vector<ModuleName> cycle;
|
|
|
|
bool operator==(const ModuleHasCyclicDependency& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct FunctionExitsWithoutReturning
|
|
|
|
{
|
|
|
|
TypePackId expectedReturnType;
|
|
|
|
bool operator==(const FunctionExitsWithoutReturning& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IllegalRequire
|
|
|
|
{
|
|
|
|
std::string moduleName;
|
|
|
|
std::string reason;
|
|
|
|
|
|
|
|
bool operator==(const IllegalRequire& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MissingProperties
|
|
|
|
{
|
|
|
|
enum Context
|
|
|
|
{
|
|
|
|
Missing,
|
|
|
|
Extra
|
|
|
|
};
|
|
|
|
TypeId superType;
|
|
|
|
TypeId subType;
|
|
|
|
std::vector<Name> properties;
|
|
|
|
Context context = Missing;
|
|
|
|
|
|
|
|
bool operator==(const MissingProperties& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DuplicateGenericParameter
|
|
|
|
{
|
|
|
|
std::string parameterName;
|
|
|
|
|
|
|
|
bool operator==(const DuplicateGenericParameter& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CannotInferBinaryOperation
|
|
|
|
{
|
|
|
|
enum OpKind
|
|
|
|
{
|
|
|
|
Operation,
|
|
|
|
Comparison,
|
|
|
|
};
|
|
|
|
|
|
|
|
AstExprBinary::Op op;
|
|
|
|
std::optional<std::string> suggestedToAnnotate;
|
|
|
|
OpKind kind;
|
|
|
|
|
|
|
|
bool operator==(const CannotInferBinaryOperation& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SwappedGenericTypeParameter
|
|
|
|
{
|
|
|
|
enum Kind
|
|
|
|
{
|
|
|
|
Type,
|
|
|
|
Pack,
|
|
|
|
};
|
|
|
|
|
|
|
|
std::string name;
|
|
|
|
// What was `name` being used as?
|
|
|
|
Kind kind;
|
|
|
|
|
|
|
|
bool operator==(const SwappedGenericTypeParameter& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct OptionalValueAccess
|
|
|
|
{
|
|
|
|
TypeId optional;
|
|
|
|
|
|
|
|
bool operator==(const OptionalValueAccess& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MissingUnionProperty
|
|
|
|
{
|
|
|
|
TypeId type;
|
|
|
|
std::vector<TypeId> missing;
|
|
|
|
Name key;
|
|
|
|
|
|
|
|
bool operator==(const MissingUnionProperty& rhs) const;
|
|
|
|
};
|
|
|
|
|
2021-12-10 22:05:05 +00:00
|
|
|
struct TypesAreUnrelated
|
|
|
|
{
|
|
|
|
TypeId left;
|
|
|
|
TypeId right;
|
|
|
|
|
|
|
|
bool operator==(const TypesAreUnrelated& rhs) const;
|
|
|
|
};
|
|
|
|
|
2022-04-15 00:57:43 +01:00
|
|
|
struct NormalizationTooComplex
|
|
|
|
{
|
|
|
|
bool operator==(const NormalizationTooComplex&) const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-10-28 11:37:29 +01:00
|
|
|
struct TypePackMismatch
|
|
|
|
{
|
|
|
|
TypePackId wantedTp;
|
|
|
|
TypePackId givenTp;
|
2023-11-10 21:10:07 +00:00
|
|
|
std::string reason;
|
2022-10-28 11:37:29 +01:00
|
|
|
|
|
|
|
bool operator==(const TypePackMismatch& rhs) const;
|
|
|
|
};
|
|
|
|
|
2022-12-02 18:09:59 +00:00
|
|
|
struct DynamicPropertyLookupOnClassesUnsafe
|
|
|
|
{
|
|
|
|
TypeId ty;
|
|
|
|
|
|
|
|
bool operator==(const DynamicPropertyLookupOnClassesUnsafe& rhs) const;
|
|
|
|
};
|
|
|
|
|
2023-05-12 18:50:47 +01:00
|
|
|
struct UninhabitedTypeFamily
|
|
|
|
{
|
|
|
|
TypeId ty;
|
|
|
|
|
|
|
|
bool operator==(const UninhabitedTypeFamily& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct UninhabitedTypePackFamily
|
|
|
|
{
|
|
|
|
TypePackId tp;
|
|
|
|
|
|
|
|
bool operator==(const UninhabitedTypePackFamily& rhs) const;
|
|
|
|
};
|
|
|
|
|
2023-05-25 22:36:34 +01:00
|
|
|
struct WhereClauseNeeded
|
|
|
|
{
|
|
|
|
TypeId ty;
|
|
|
|
|
|
|
|
bool operator==(const WhereClauseNeeded& rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PackWhereClauseNeeded
|
|
|
|
{
|
|
|
|
TypePackId tp;
|
|
|
|
|
|
|
|
bool operator==(const PackWhereClauseNeeded& rhs) const;
|
|
|
|
};
|
|
|
|
|
2023-10-13 21:20:12 +01:00
|
|
|
struct CheckedFunctionCallError
|
|
|
|
{
|
|
|
|
TypeId expected;
|
|
|
|
TypeId passed;
|
|
|
|
std::string checkedFunctionName;
|
|
|
|
// TODO: make this a vector<argumentIndices>
|
|
|
|
size_t argumentIndex;
|
|
|
|
bool operator==(const CheckedFunctionCallError& rhs) const;
|
|
|
|
};
|
|
|
|
|
2023-07-14 19:08:53 +01:00
|
|
|
using TypeErrorData = Variant<TypeMismatch, UnknownSymbol, UnknownProperty, NotATable, CannotExtendTable, OnlyTablesCanHaveMethods,
|
|
|
|
DuplicateTypeDefinition, CountMismatch, FunctionDoesNotTakeSelf, FunctionRequiresSelf, OccursCheckFailed, UnknownRequire,
|
|
|
|
IncorrectGenericParameterCount, SyntaxError, CodeTooComplex, UnificationTooComplex, UnknownPropButFoundLikeProp, GenericError, InternalError,
|
|
|
|
CannotCallNonFunction, ExtraInformation, DeprecatedApiUsed, ModuleHasCyclicDependency, IllegalRequire, FunctionExitsWithoutReturning,
|
|
|
|
DuplicateGenericParameter, CannotInferBinaryOperation, MissingProperties, SwappedGenericTypeParameter, OptionalValueAccess, MissingUnionProperty,
|
|
|
|
TypesAreUnrelated, NormalizationTooComplex, TypePackMismatch, DynamicPropertyLookupOnClassesUnsafe, UninhabitedTypeFamily,
|
2023-10-13 21:20:12 +01:00
|
|
|
UninhabitedTypePackFamily, WhereClauseNeeded, PackWhereClauseNeeded, CheckedFunctionCallError>;
|
2022-12-02 18:09:59 +00:00
|
|
|
|
|
|
|
struct TypeErrorSummary
|
|
|
|
{
|
|
|
|
Location location;
|
|
|
|
ModuleName moduleName;
|
|
|
|
int code;
|
|
|
|
|
|
|
|
TypeErrorSummary(const Location& location, const ModuleName& moduleName, int code)
|
|
|
|
: location(location)
|
|
|
|
, moduleName(moduleName)
|
|
|
|
, code(code)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
2021-10-29 21:25:12 +01:00
|
|
|
|
|
|
|
struct TypeError
|
|
|
|
{
|
|
|
|
Location location;
|
|
|
|
ModuleName moduleName;
|
|
|
|
TypeErrorData data;
|
|
|
|
|
2022-12-02 18:09:59 +00:00
|
|
|
static int minCode();
|
2021-10-29 21:25:12 +01:00
|
|
|
int code() const;
|
|
|
|
|
|
|
|
TypeError() = default;
|
|
|
|
|
|
|
|
TypeError(const Location& location, const ModuleName& moduleName, const TypeErrorData& data)
|
|
|
|
: location(location)
|
|
|
|
, moduleName(moduleName)
|
|
|
|
, data(data)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TypeError(const Location& location, const TypeErrorData& data)
|
|
|
|
: TypeError(location, {}, data)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const TypeError& rhs) const;
|
2022-12-02 18:09:59 +00:00
|
|
|
|
|
|
|
TypeErrorSummary summary() const;
|
2021-10-29 21:25:12 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
const T* get(const TypeError& e)
|
|
|
|
{
|
|
|
|
return get_if<T>(&e.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
T* get(TypeError& e)
|
|
|
|
{
|
|
|
|
return get_if<T>(&e.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
using ErrorVec = std::vector<TypeError>;
|
|
|
|
|
2022-06-24 02:56:00 +01:00
|
|
|
struct TypeErrorToStringOptions
|
|
|
|
{
|
|
|
|
FileResolver* fileResolver = nullptr;
|
|
|
|
};
|
|
|
|
|
2021-10-29 21:25:12 +01:00
|
|
|
std::string toString(const TypeError& error);
|
2022-06-24 02:56:00 +01:00
|
|
|
std::string toString(const TypeError& error, TypeErrorToStringOptions options);
|
2021-10-29 21:25:12 +01:00
|
|
|
|
|
|
|
bool containsParseErrorName(const TypeError& error);
|
|
|
|
|
|
|
|
// Copy any types named in the error into destArena.
|
2023-08-11 15:42:37 +01:00
|
|
|
void copyErrors(ErrorVec& errors, struct TypeArena& destArena, NotNull<BuiltinTypes> builtinTypes);
|
2021-10-29 21:25:12 +01:00
|
|
|
|
|
|
|
// Internal Compiler Error
|
|
|
|
struct InternalErrorReporter
|
|
|
|
{
|
|
|
|
std::function<void(const char*)> onInternalError;
|
|
|
|
std::string moduleName;
|
|
|
|
|
2023-03-10 20:21:07 +00:00
|
|
|
[[noreturn]] void ice(const std::string& message, const Location& location) const;
|
|
|
|
[[noreturn]] void ice(const std::string& message) const;
|
2021-10-29 21:25:12 +01:00
|
|
|
};
|
|
|
|
|
2022-07-01 00:52:43 +01:00
|
|
|
class InternalCompilerError : public std::exception
|
|
|
|
{
|
2022-06-24 02:56:00 +01:00
|
|
|
public:
|
2022-10-28 11:37:29 +01:00
|
|
|
explicit InternalCompilerError(const std::string& message)
|
|
|
|
: message(message)
|
|
|
|
{
|
|
|
|
}
|
2022-07-01 00:52:43 +01:00
|
|
|
explicit InternalCompilerError(const std::string& message, const std::string& moduleName)
|
|
|
|
: message(message)
|
|
|
|
, moduleName(moduleName)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
explicit InternalCompilerError(const std::string& message, const std::string& moduleName, const Location& location)
|
|
|
|
: message(message)
|
|
|
|
, moduleName(moduleName)
|
|
|
|
, location(location)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
virtual const char* what() const throw();
|
|
|
|
|
|
|
|
const std::string message;
|
2022-10-28 11:37:29 +01:00
|
|
|
const std::optional<std::string> moduleName;
|
2022-07-01 00:52:43 +01:00
|
|
|
const std::optional<Location> location;
|
2022-06-24 02:56:00 +01:00
|
|
|
};
|
|
|
|
|
2021-10-29 21:25:12 +01:00
|
|
|
} // namespace Luau
|