2021-10-29 13:25:12 -07:00
|
|
|
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
|
|
#include "Luau/IostreamHelpers.h"
|
|
|
|
#include "Luau/ToString.h"
|
2023-10-20 18:10:30 -07:00
|
|
|
#include "Luau/TypePath.h"
|
2021-10-29 13:25:12 -07:00
|
|
|
|
|
|
|
namespace Luau
|
|
|
|
{
|
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const Position& position)
|
|
|
|
{
|
|
|
|
return stream << "{ line = " << position.line << ", col = " << position.column << " }";
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const Location& location)
|
|
|
|
{
|
|
|
|
return stream << "Location { " << location.begin << ", " << location.end << " }";
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const AstName& name)
|
|
|
|
{
|
|
|
|
if (name.value)
|
|
|
|
return stream << name.value;
|
|
|
|
else
|
|
|
|
return stream << "<empty>";
|
|
|
|
}
|
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
template<typename T>
|
|
|
|
static void errorToString(std::ostream& stream, const T& err)
|
2021-10-29 13:25:12 -07:00
|
|
|
{
|
2022-04-07 14:29:01 -07:00
|
|
|
if constexpr (false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else if constexpr (std::is_same_v<T, TypeMismatch>)
|
|
|
|
stream << "TypeMismatch { " << toString(err.wantedType) << ", " << toString(err.givenType) << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, UnknownSymbol>)
|
|
|
|
stream << "UnknownSymbol { " << err.name << " , context " << err.context << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, UnknownProperty>)
|
|
|
|
stream << "UnknownProperty { " << toString(err.table) << ", key = " << err.key << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, NotATable>)
|
|
|
|
stream << "NotATable { " << toString(err.ty) << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, CannotExtendTable>)
|
|
|
|
stream << "CannotExtendTable { " << toString(err.tableType) << ", context " << err.context << ", prop \"" << err.prop << "\" }";
|
|
|
|
else if constexpr (std::is_same_v<T, OnlyTablesCanHaveMethods>)
|
|
|
|
stream << "OnlyTablesCanHaveMethods { " << toString(err.tableType) << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, DuplicateTypeDefinition>)
|
|
|
|
stream << "DuplicateTypeDefinition { " << err.name << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, CountMismatch>)
|
|
|
|
stream << "CountMismatch { expected " << err.expected << ", got " << err.actual << ", context " << err.context << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, FunctionDoesNotTakeSelf>)
|
|
|
|
stream << "FunctionDoesNotTakeSelf { }";
|
|
|
|
else if constexpr (std::is_same_v<T, FunctionRequiresSelf>)
|
2022-05-19 17:02:24 -07:00
|
|
|
stream << "FunctionRequiresSelf { }";
|
2022-04-07 14:29:01 -07:00
|
|
|
else if constexpr (std::is_same_v<T, OccursCheckFailed>)
|
|
|
|
stream << "OccursCheckFailed { }";
|
|
|
|
else if constexpr (std::is_same_v<T, UnknownRequire>)
|
|
|
|
stream << "UnknownRequire { " << err.modulePath << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, IncorrectGenericParameterCount>)
|
|
|
|
{
|
|
|
|
stream << "IncorrectGenericParameterCount { name = " << err.name;
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
if (!err.typeFun.typeParams.empty() || !err.typeFun.typePackParams.empty())
|
|
|
|
{
|
|
|
|
stream << "<";
|
|
|
|
bool first = true;
|
|
|
|
for (auto param : err.typeFun.typeParams)
|
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
first = false;
|
|
|
|
else
|
|
|
|
stream << ", ";
|
|
|
|
|
|
|
|
stream << toString(param.ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto param : err.typeFun.typePackParams)
|
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
first = false;
|
|
|
|
else
|
|
|
|
stream << ", ";
|
|
|
|
|
|
|
|
stream << toString(param.tp);
|
|
|
|
}
|
|
|
|
|
|
|
|
stream << ">";
|
|
|
|
}
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << ", typeFun = " << toString(err.typeFun.type) << ", actualCount = " << err.actualParameters << " }";
|
|
|
|
}
|
|
|
|
else if constexpr (std::is_same_v<T, SyntaxError>)
|
|
|
|
stream << "SyntaxError { " << err.message << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, CodeTooComplex>)
|
|
|
|
stream << "CodeTooComplex {}";
|
|
|
|
else if constexpr (std::is_same_v<T, UnificationTooComplex>)
|
|
|
|
stream << "UnificationTooComplex {}";
|
|
|
|
else if constexpr (std::is_same_v<T, UnknownPropButFoundLikeProp>)
|
2021-10-29 13:25:12 -07:00
|
|
|
{
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << "UnknownPropButFoundLikeProp { key = '" << err.key << "', suggested = { ";
|
|
|
|
|
2021-10-29 13:25:12 -07:00
|
|
|
bool first = true;
|
2022-04-07 14:29:01 -07:00
|
|
|
for (Name name : err.candidates)
|
2021-10-29 13:25:12 -07:00
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
first = false;
|
|
|
|
else
|
|
|
|
stream << ", ";
|
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << "'" << name << "'";
|
2021-10-29 13:25:12 -07:00
|
|
|
}
|
2021-11-04 19:34:35 -07:00
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << " }, table = " << toString(err.table) << " } ";
|
|
|
|
}
|
|
|
|
else if constexpr (std::is_same_v<T, GenericError>)
|
|
|
|
stream << "GenericError { " << err.message << " }";
|
2022-06-23 18:56:00 -07:00
|
|
|
else if constexpr (std::is_same_v<T, InternalError>)
|
|
|
|
stream << "InternalError { " << err.message << " }";
|
2022-04-07 14:29:01 -07:00
|
|
|
else if constexpr (std::is_same_v<T, CannotCallNonFunction>)
|
|
|
|
stream << "CannotCallNonFunction { " << toString(err.ty) << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, ExtraInformation>)
|
|
|
|
stream << "ExtraInformation { " << err.message << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, DeprecatedApiUsed>)
|
|
|
|
stream << "DeprecatedApiUsed { " << err.symbol << ", useInstead = " << err.useInstead << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, ModuleHasCyclicDependency>)
|
|
|
|
{
|
|
|
|
stream << "ModuleHasCyclicDependency {";
|
|
|
|
|
|
|
|
bool first = true;
|
|
|
|
for (const ModuleName& name : err.cycle)
|
2021-11-04 19:34:35 -07:00
|
|
|
{
|
2021-12-02 22:41:04 -08:00
|
|
|
if (first)
|
|
|
|
first = false;
|
|
|
|
else
|
|
|
|
stream << ", ";
|
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << name;
|
2021-11-04 19:34:35 -07:00
|
|
|
}
|
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << "}";
|
2021-10-29 13:25:12 -07:00
|
|
|
}
|
2022-04-07 14:29:01 -07:00
|
|
|
else if constexpr (std::is_same_v<T, IllegalRequire>)
|
|
|
|
stream << "IllegalRequire { " << err.moduleName << ", reason = " << err.reason << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, FunctionExitsWithoutReturning>)
|
|
|
|
stream << "FunctionExitsWithoutReturning {" << toString(err.expectedReturnType) << "}";
|
|
|
|
else if constexpr (std::is_same_v<T, DuplicateGenericParameter>)
|
|
|
|
stream << "DuplicateGenericParameter { " + err.parameterName + " }";
|
|
|
|
else if constexpr (std::is_same_v<T, CannotInferBinaryOperation>)
|
|
|
|
stream << "CannotInferBinaryOperation { op = " + toString(err.op) + ", suggested = '" +
|
|
|
|
(err.suggestedToAnnotate ? *err.suggestedToAnnotate : "") + "', kind "
|
|
|
|
<< err.kind << "}";
|
|
|
|
else if constexpr (std::is_same_v<T, MissingProperties>)
|
2021-10-29 13:25:12 -07:00
|
|
|
{
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << "MissingProperties { superType = '" << toString(err.superType) << "', subType = '" << toString(err.subType) << "', properties = { ";
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
bool first = true;
|
|
|
|
for (Name name : err.properties)
|
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
first = false;
|
|
|
|
else
|
|
|
|
stream << ", ";
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << "'" << name << "'";
|
|
|
|
}
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << " }, context " << err.context << " } ";
|
2021-10-29 13:25:12 -07:00
|
|
|
}
|
2022-04-07 14:29:01 -07:00
|
|
|
else if constexpr (std::is_same_v<T, SwappedGenericTypeParameter>)
|
|
|
|
stream << "SwappedGenericTypeParameter { name = '" + err.name + "', kind = " + std::to_string(err.kind) + " }";
|
|
|
|
else if constexpr (std::is_same_v<T, OptionalValueAccess>)
|
|
|
|
stream << "OptionalValueAccess { optional = '" + toString(err.optional) + "' }";
|
|
|
|
else if constexpr (std::is_same_v<T, MissingUnionProperty>)
|
2021-10-29 13:25:12 -07:00
|
|
|
{
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << "MissingUnionProperty { type = '" + toString(err.type) + "', missing = { ";
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
bool first = true;
|
|
|
|
for (auto ty : err.missing)
|
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
first = false;
|
|
|
|
else
|
|
|
|
stream << ", ";
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << "'" << toString(ty) << "'";
|
|
|
|
}
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
stream << " }, key = '" + err.key + "' }";
|
|
|
|
}
|
|
|
|
else if constexpr (std::is_same_v<T, TypesAreUnrelated>)
|
|
|
|
stream << "TypesAreUnrelated { left = '" + toString(err.left) + "', right = '" + toString(err.right) + "' }";
|
2022-04-14 16:57:43 -07:00
|
|
|
else if constexpr (std::is_same_v<T, NormalizationTooComplex>)
|
|
|
|
stream << "NormalizationTooComplex { }";
|
2022-10-28 03:37:29 -07:00
|
|
|
else if constexpr (std::is_same_v<T, TypePackMismatch>)
|
|
|
|
stream << "TypePackMismatch { wanted = '" + toString(err.wantedTp) + "', given = '" + toString(err.givenTp) + "' }";
|
2022-12-02 10:09:59 -08:00
|
|
|
else if constexpr (std::is_same_v<T, DynamicPropertyLookupOnClassesUnsafe>)
|
|
|
|
stream << "DynamicPropertyLookupOnClassesUnsafe { " << toString(err.ty) << " }";
|
2024-07-12 10:03:36 -07:00
|
|
|
else if constexpr (std::is_same_v<T, UninhabitedTypeFunction>)
|
|
|
|
stream << "UninhabitedTypeFunction { " << toString(err.ty) << " }";
|
2024-03-08 16:47:53 -08:00
|
|
|
else if constexpr (std::is_same_v<T, ExplicitFunctionAnnotationRecommended>)
|
|
|
|
{
|
|
|
|
std::string recArgs = "[";
|
|
|
|
for (auto [s, t] : err.recommendedArgs)
|
|
|
|
recArgs += " " + s + ": " + toString(t);
|
|
|
|
recArgs += " ]";
|
|
|
|
stream << "ExplicitFunctionAnnotationRecommended { recommmendedReturn = '" + toString(err.recommendedReturn) +
|
|
|
|
"', recommmendedArgs = " + recArgs + "}";
|
|
|
|
}
|
2024-07-12 10:03:36 -07:00
|
|
|
else if constexpr (std::is_same_v<T, UninhabitedTypePackFunction>)
|
|
|
|
stream << "UninhabitedTypePackFunction { " << toString(err.tp) << " }";
|
2023-05-26 00:36:34 +03:00
|
|
|
else if constexpr (std::is_same_v<T, WhereClauseNeeded>)
|
|
|
|
stream << "WhereClauseNeeded { " << toString(err.ty) << " }";
|
|
|
|
else if constexpr (std::is_same_v<T, PackWhereClauseNeeded>)
|
|
|
|
stream << "PackWhereClauseNeeded { " << toString(err.tp) << " }";
|
2023-10-13 13:20:12 -07:00
|
|
|
else if constexpr (std::is_same_v<T, CheckedFunctionCallError>)
|
|
|
|
stream << "CheckedFunctionCallError { expected = '" << toString(err.expected) << "', passed = '" << toString(err.passed)
|
|
|
|
<< "', checkedFunctionName = " << err.checkedFunctionName << ", argumentIndex = " << std::to_string(err.argumentIndex) << " }";
|
2023-12-01 23:46:57 -08:00
|
|
|
else if constexpr (std::is_same_v<T, NonStrictFunctionDefinitionError>)
|
|
|
|
stream << "NonStrictFunctionDefinitionError { functionName = '" + err.functionName + "', argument = '" + err.argument +
|
|
|
|
"', argumentType = '" + toString(err.argumentType) + "' }";
|
2024-02-23 12:08:34 -08:00
|
|
|
else if constexpr (std::is_same_v<T, PropertyAccessViolation>)
|
|
|
|
stream << "PropertyAccessViolation { table = " << toString(err.table) << ", prop = '" << err.key << "', context = " << err.context << " }";
|
2024-02-02 13:32:42 -08:00
|
|
|
else if constexpr (std::is_same_v<T, CheckedFunctionIncorrectArgs>)
|
|
|
|
stream << "CheckedFunction { functionName = '" + err.functionName + ", expected = " + std::to_string(err.expected) +
|
|
|
|
", actual = " + std::to_string(err.actual) + "}";
|
2024-02-23 12:08:34 -08:00
|
|
|
else if constexpr (std::is_same_v<T, UnexpectedTypeInSubtyping>)
|
|
|
|
stream << "UnexpectedTypeInSubtyping { ty = '" + toString(err.ty) + "' }";
|
|
|
|
else if constexpr (std::is_same_v<T, UnexpectedTypePackInSubtyping>)
|
|
|
|
stream << "UnexpectedTypePackInSubtyping { tp = '" + toString(err.tp) + "' }";
|
2024-04-12 10:18:49 -07:00
|
|
|
else if constexpr (std::is_same_v<T, CannotAssignToNever>)
|
|
|
|
{
|
|
|
|
stream << "CannotAssignToNever { rvalueType = '" << toString(err.rhsType) << "', reason = '" << err.reason << "', cause = { ";
|
|
|
|
|
|
|
|
bool first = true;
|
|
|
|
for (TypeId ty : err.cause)
|
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
first = false;
|
|
|
|
else
|
|
|
|
stream << ", ";
|
|
|
|
|
|
|
|
stream << "'" << toString(ty) << "'";
|
|
|
|
}
|
|
|
|
|
|
|
|
stream << " } } ";
|
|
|
|
}
|
2022-04-07 14:29:01 -07:00
|
|
|
else
|
|
|
|
static_assert(always_false_v<T>, "Non-exhaustive type switch");
|
2021-10-29 13:25:12 -07:00
|
|
|
}
|
|
|
|
|
2024-04-12 10:18:49 -07:00
|
|
|
std::ostream& operator<<(std::ostream& stream, const CannotAssignToNever::Reason& reason)
|
|
|
|
{
|
|
|
|
switch (reason)
|
|
|
|
{
|
|
|
|
case CannotAssignToNever::Reason::PropertyNarrowed:
|
|
|
|
return stream << "PropertyNarrowed";
|
|
|
|
default:
|
|
|
|
return stream << "UnknownReason";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
std::ostream& operator<<(std::ostream& stream, const TypeErrorData& data)
|
2021-10-29 13:25:12 -07:00
|
|
|
{
|
2022-04-07 14:29:01 -07:00
|
|
|
auto cb = [&](const auto& e) {
|
|
|
|
return errorToString(stream, e);
|
|
|
|
};
|
|
|
|
visit(cb, data);
|
|
|
|
return stream;
|
2021-10-29 13:25:12 -07:00
|
|
|
}
|
|
|
|
|
2022-04-07 14:29:01 -07:00
|
|
|
std::ostream& operator<<(std::ostream& stream, const TypeError& error)
|
2021-12-10 14:05:05 -08:00
|
|
|
{
|
2022-04-07 14:29:01 -07:00
|
|
|
return stream << "TypeError { \"" << error.moduleName << "\", " << error.location << ", " << error.data << " }";
|
2021-12-10 14:05:05 -08:00
|
|
|
}
|
|
|
|
|
2021-10-29 13:25:12 -07:00
|
|
|
std::ostream& operator<<(std::ostream& stream, const TableState& tv)
|
|
|
|
{
|
|
|
|
return stream << static_cast<std::underlying_type<TableState>::type>(tv);
|
|
|
|
}
|
|
|
|
|
2023-01-04 12:53:17 -08:00
|
|
|
std::ostream& operator<<(std::ostream& stream, const Type& tv)
|
2021-10-29 13:25:12 -07:00
|
|
|
{
|
|
|
|
return stream << toString(tv);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const TypePackVar& tv)
|
|
|
|
{
|
|
|
|
return stream << toString(tv);
|
|
|
|
}
|
|
|
|
|
2023-10-20 18:10:30 -07:00
|
|
|
std::ostream& operator<<(std::ostream& stream, TypeId ty)
|
|
|
|
{
|
|
|
|
// we commonly use a null pointer when a type may not be present; we need to
|
|
|
|
// account for that here.
|
|
|
|
if (!ty)
|
|
|
|
return stream << "<nullptr>";
|
|
|
|
|
|
|
|
return stream << toString(ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& stream, TypePackId tp)
|
|
|
|
{
|
|
|
|
// we commonly use a null pointer when a type may not be present; we need to
|
|
|
|
// account for that here.
|
|
|
|
if (!tp)
|
|
|
|
return stream << "<nullptr>";
|
|
|
|
|
|
|
|
return stream << toString(tp);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace TypePath
|
|
|
|
{
|
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const Path& path)
|
|
|
|
{
|
|
|
|
return stream << toString(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace TypePath
|
|
|
|
|
2021-10-29 13:25:12 -07:00
|
|
|
} // namespace Luau
|