mirror of
https://github.com/luau-lang/luau.git
synced 2024-11-15 22:35:43 +08:00
Merge branch 'upstream' into merge
This commit is contained in:
commit
2c0be898a1
@ -2,12 +2,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
|
||||||
class AstNode;
|
class AstNode;
|
||||||
|
struct Comment;
|
||||||
|
|
||||||
std::string toJson(AstNode* node);
|
std::string toJson(AstNode* node);
|
||||||
|
std::string toJson(AstNode* node, const std::vector<Comment>& commentLocations);
|
||||||
|
|
||||||
} // namespace Luau
|
} // namespace Luau
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
LUAU_FASTINT(LuauVisitRecursionLimit)
|
LUAU_FASTINT(LuauVisitRecursionLimit)
|
||||||
LUAU_FASTFLAG(LuauNormalizeFlagIsConservative)
|
LUAU_FASTFLAG(LuauNormalizeFlagIsConservative)
|
||||||
|
LUAU_FASTFLAG(LuauCompleteVisitor);
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
@ -129,11 +130,11 @@ struct GenericTypeVarVisitor
|
|||||||
{
|
{
|
||||||
return visit(ty);
|
return visit(ty);
|
||||||
}
|
}
|
||||||
virtual bool visit(TypeId ty, const UnknownTypeVar& atv)
|
virtual bool visit(TypeId ty, const UnknownTypeVar& utv)
|
||||||
{
|
{
|
||||||
return visit(ty);
|
return visit(ty);
|
||||||
}
|
}
|
||||||
virtual bool visit(TypeId ty, const NeverTypeVar& atv)
|
virtual bool visit(TypeId ty, const NeverTypeVar& ntv)
|
||||||
{
|
{
|
||||||
return visit(ty);
|
return visit(ty);
|
||||||
}
|
}
|
||||||
@ -145,6 +146,14 @@ struct GenericTypeVarVisitor
|
|||||||
{
|
{
|
||||||
return visit(ty);
|
return visit(ty);
|
||||||
}
|
}
|
||||||
|
virtual bool visit(TypeId ty, const BlockedTypeVar& btv)
|
||||||
|
{
|
||||||
|
return visit(ty);
|
||||||
|
}
|
||||||
|
virtual bool visit(TypeId ty, const SingletonTypeVar& stv)
|
||||||
|
{
|
||||||
|
return visit(ty);
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool visit(TypePackId tp)
|
virtual bool visit(TypePackId tp)
|
||||||
{
|
{
|
||||||
@ -190,16 +199,12 @@ struct GenericTypeVarVisitor
|
|||||||
if (visit(ty, *btv))
|
if (visit(ty, *btv))
|
||||||
traverse(btv->boundTo);
|
traverse(btv->boundTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (auto ftv = get<FreeTypeVar>(ty))
|
else if (auto ftv = get<FreeTypeVar>(ty))
|
||||||
visit(ty, *ftv);
|
visit(ty, *ftv);
|
||||||
|
|
||||||
else if (auto gtv = get<GenericTypeVar>(ty))
|
else if (auto gtv = get<GenericTypeVar>(ty))
|
||||||
visit(ty, *gtv);
|
visit(ty, *gtv);
|
||||||
|
|
||||||
else if (auto etv = get<ErrorTypeVar>(ty))
|
else if (auto etv = get<ErrorTypeVar>(ty))
|
||||||
visit(ty, *etv);
|
visit(ty, *etv);
|
||||||
|
|
||||||
else if (auto ctv = get<ConstrainedTypeVar>(ty))
|
else if (auto ctv = get<ConstrainedTypeVar>(ty))
|
||||||
{
|
{
|
||||||
if (visit(ty, *ctv))
|
if (visit(ty, *ctv))
|
||||||
@ -208,10 +213,8 @@ struct GenericTypeVarVisitor
|
|||||||
traverse(part);
|
traverse(part);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (auto ptv = get<PrimitiveTypeVar>(ty))
|
else if (auto ptv = get<PrimitiveTypeVar>(ty))
|
||||||
visit(ty, *ptv);
|
visit(ty, *ptv);
|
||||||
|
|
||||||
else if (auto ftv = get<FunctionTypeVar>(ty))
|
else if (auto ftv = get<FunctionTypeVar>(ty))
|
||||||
{
|
{
|
||||||
if (visit(ty, *ftv))
|
if (visit(ty, *ftv))
|
||||||
@ -220,7 +223,6 @@ struct GenericTypeVarVisitor
|
|||||||
traverse(ftv->retTypes);
|
traverse(ftv->retTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (auto ttv = get<TableTypeVar>(ty))
|
else if (auto ttv = get<TableTypeVar>(ty))
|
||||||
{
|
{
|
||||||
// Some visitors want to see bound tables, that's why we traverse the original type
|
// Some visitors want to see bound tables, that's why we traverse the original type
|
||||||
@ -243,7 +245,6 @@ struct GenericTypeVarVisitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (auto mtv = get<MetatableTypeVar>(ty))
|
else if (auto mtv = get<MetatableTypeVar>(ty))
|
||||||
{
|
{
|
||||||
if (visit(ty, *mtv))
|
if (visit(ty, *mtv))
|
||||||
@ -252,7 +253,6 @@ struct GenericTypeVarVisitor
|
|||||||
traverse(mtv->metatable);
|
traverse(mtv->metatable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (auto ctv = get<ClassTypeVar>(ty))
|
else if (auto ctv = get<ClassTypeVar>(ty))
|
||||||
{
|
{
|
||||||
if (visit(ty, *ctv))
|
if (visit(ty, *ctv))
|
||||||
@ -267,10 +267,8 @@ struct GenericTypeVarVisitor
|
|||||||
traverse(*ctv->metatable);
|
traverse(*ctv->metatable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (auto atv = get<AnyTypeVar>(ty))
|
else if (auto atv = get<AnyTypeVar>(ty))
|
||||||
visit(ty, *atv);
|
visit(ty, *atv);
|
||||||
|
|
||||||
else if (auto utv = get<UnionTypeVar>(ty))
|
else if (auto utv = get<UnionTypeVar>(ty))
|
||||||
{
|
{
|
||||||
if (visit(ty, *utv))
|
if (visit(ty, *utv))
|
||||||
@ -279,7 +277,6 @@ struct GenericTypeVarVisitor
|
|||||||
traverse(optTy);
|
traverse(optTy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (auto itv = get<IntersectionTypeVar>(ty))
|
else if (auto itv = get<IntersectionTypeVar>(ty))
|
||||||
{
|
{
|
||||||
if (visit(ty, *itv))
|
if (visit(ty, *itv))
|
||||||
@ -288,6 +285,24 @@ struct GenericTypeVarVisitor
|
|||||||
traverse(partTy);
|
traverse(partTy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!FFlag::LuauCompleteVisitor)
|
||||||
|
return visit_detail::unsee(seen, ty);
|
||||||
|
else if (get<LazyTypeVar>(ty))
|
||||||
|
{
|
||||||
|
// Visiting into LazyTypeVar may necessarily cause infinite expansion, so we don't do that on purpose.
|
||||||
|
// Asserting also makes no sense, because the type _will_ happen here, most likely as a property of some ClassTypeVar
|
||||||
|
// that doesn't need to be expanded.
|
||||||
|
}
|
||||||
|
else if (auto stv = get<SingletonTypeVar>(ty))
|
||||||
|
visit(ty, *stv);
|
||||||
|
else if (auto btv = get<BlockedTypeVar>(ty))
|
||||||
|
visit(ty, *btv);
|
||||||
|
else if (auto utv = get<UnknownTypeVar>(ty))
|
||||||
|
visit(ty, *utv);
|
||||||
|
else if (auto ntv = get<NeverTypeVar>(ty))
|
||||||
|
visit(ty, *ntv);
|
||||||
|
else
|
||||||
|
LUAU_ASSERT(!"GenericTypeVarVisitor::traverse(TypeId) is not exhaustive!");
|
||||||
|
|
||||||
visit_detail::unsee(seen, ty);
|
visit_detail::unsee(seen, ty);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "Luau/JsonEncoder.h"
|
#include "Luau/JsonEncoder.h"
|
||||||
|
|
||||||
#include "Luau/Ast.h"
|
#include "Luau/Ast.h"
|
||||||
|
#include "Luau/ParseResult.h"
|
||||||
#include "Luau/StringUtils.h"
|
#include "Luau/StringUtils.h"
|
||||||
#include "Luau/Common.h"
|
#include "Luau/Common.h"
|
||||||
|
|
||||||
@ -75,6 +76,11 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
writeRaw(std::string_view{&c, 1});
|
writeRaw(std::string_view{&c, 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeType(std::string_view propValue)
|
||||||
|
{
|
||||||
|
write("type", propValue);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void write(std::string_view propName, const T& value)
|
void write(std::string_view propName, const T& value)
|
||||||
{
|
{
|
||||||
@ -98,7 +104,7 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
void write(double d)
|
void write(double d)
|
||||||
{
|
{
|
||||||
char b[256];
|
char b[256];
|
||||||
sprintf(b, "%g", d);
|
sprintf(b, "%.17g", d);
|
||||||
writeRaw(b);
|
writeRaw(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,8 +117,12 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
{
|
{
|
||||||
if (c == '"')
|
if (c == '"')
|
||||||
writeRaw("\\\"");
|
writeRaw("\\\"");
|
||||||
else if (c == '\0')
|
else if (c == '\\')
|
||||||
writeRaw("\\\0");
|
writeRaw("\\\\");
|
||||||
|
else if (c < ' ')
|
||||||
|
writeRaw(format("\\u%04x", c));
|
||||||
|
else if (c == '\n')
|
||||||
|
writeRaw("\\n");
|
||||||
else
|
else
|
||||||
writeRaw(c);
|
writeRaw(c);
|
||||||
}
|
}
|
||||||
@ -189,10 +199,11 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
writeRaw("{");
|
writeRaw("{");
|
||||||
bool c = pushComma();
|
bool c = pushComma();
|
||||||
if (local->annotation != nullptr)
|
if (local->annotation != nullptr)
|
||||||
write("type", local->annotation);
|
write("luauType", local->annotation);
|
||||||
else
|
else
|
||||||
write("type", nullptr);
|
write("luauType", nullptr);
|
||||||
write("name", local->name);
|
write("name", local->name);
|
||||||
|
writeType("AstLocal");
|
||||||
write("location", local->location);
|
write("location", local->location);
|
||||||
popComma(c);
|
popComma(c);
|
||||||
writeRaw("}");
|
writeRaw("}");
|
||||||
@ -208,7 +219,7 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
{
|
{
|
||||||
writeRaw("{");
|
writeRaw("{");
|
||||||
bool c = pushComma();
|
bool c = pushComma();
|
||||||
write("type", name);
|
writeType(name);
|
||||||
writeNode(node);
|
writeNode(node);
|
||||||
f();
|
f();
|
||||||
popComma(c);
|
popComma(c);
|
||||||
@ -358,6 +369,7 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
{
|
{
|
||||||
writeRaw("{");
|
writeRaw("{");
|
||||||
bool c = pushComma();
|
bool c = pushComma();
|
||||||
|
writeType("AstTypeList");
|
||||||
write("types", typeList.types);
|
write("types", typeList.types);
|
||||||
if (typeList.tailType)
|
if (typeList.tailType)
|
||||||
write("tailType", typeList.tailType);
|
write("tailType", typeList.tailType);
|
||||||
@ -369,9 +381,10 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
{
|
{
|
||||||
writeRaw("{");
|
writeRaw("{");
|
||||||
bool c = pushComma();
|
bool c = pushComma();
|
||||||
|
writeType("AstGenericType");
|
||||||
write("name", genericType.name);
|
write("name", genericType.name);
|
||||||
if (genericType.defaultValue)
|
if (genericType.defaultValue)
|
||||||
write("type", genericType.defaultValue);
|
write("luauType", genericType.defaultValue);
|
||||||
popComma(c);
|
popComma(c);
|
||||||
writeRaw("}");
|
writeRaw("}");
|
||||||
}
|
}
|
||||||
@ -380,9 +393,10 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
{
|
{
|
||||||
writeRaw("{");
|
writeRaw("{");
|
||||||
bool c = pushComma();
|
bool c = pushComma();
|
||||||
|
writeType("AstGenericTypePack");
|
||||||
write("name", genericTypePack.name);
|
write("name", genericTypePack.name);
|
||||||
if (genericTypePack.defaultValue)
|
if (genericTypePack.defaultValue)
|
||||||
write("type", genericTypePack.defaultValue);
|
write("luauType", genericTypePack.defaultValue);
|
||||||
popComma(c);
|
popComma(c);
|
||||||
writeRaw("}");
|
writeRaw("}");
|
||||||
}
|
}
|
||||||
@ -404,6 +418,7 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
{
|
{
|
||||||
writeRaw("{");
|
writeRaw("{");
|
||||||
bool c = pushComma();
|
bool c = pushComma();
|
||||||
|
writeType("AstExprTableItem");
|
||||||
write("kind", item.kind);
|
write("kind", item.kind);
|
||||||
switch (item.kind)
|
switch (item.kind)
|
||||||
{
|
{
|
||||||
@ -419,6 +434,17 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
writeRaw("}");
|
writeRaw("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write(class AstExprIfElse* node)
|
||||||
|
{
|
||||||
|
writeNode(node, "AstExprIfElse", [&]() {
|
||||||
|
PROP(condition);
|
||||||
|
PROP(hasThen);
|
||||||
|
PROP(trueExpr);
|
||||||
|
PROP(hasElse);
|
||||||
|
PROP(falseExpr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void write(class AstExprTable* node)
|
void write(class AstExprTable* node)
|
||||||
{
|
{
|
||||||
writeNode(node, "AstExprTable", [&]() {
|
writeNode(node, "AstExprTable", [&]() {
|
||||||
@ -431,11 +457,11 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case AstExprUnary::Not:
|
case AstExprUnary::Not:
|
||||||
return writeString("not");
|
return writeString("Not");
|
||||||
case AstExprUnary::Minus:
|
case AstExprUnary::Minus:
|
||||||
return writeString("minus");
|
return writeString("Minus");
|
||||||
case AstExprUnary::Len:
|
case AstExprUnary::Len:
|
||||||
return writeString("len");
|
return writeString("Len");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,7 +567,7 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
|
|
||||||
void write(class AstStatWhile* node)
|
void write(class AstStatWhile* node)
|
||||||
{
|
{
|
||||||
writeNode(node, "AtStatWhile", [&]() {
|
writeNode(node, "AstStatWhile", [&]() {
|
||||||
PROP(condition);
|
PROP(condition);
|
||||||
PROP(body);
|
PROP(body);
|
||||||
PROP(hasDo);
|
PROP(hasDo);
|
||||||
@ -684,7 +710,8 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
writeRaw("{");
|
writeRaw("{");
|
||||||
bool c = pushComma();
|
bool c = pushComma();
|
||||||
write("name", prop.name);
|
write("name", prop.name);
|
||||||
write("type", prop.ty);
|
writeType("AstDeclaredClassProp");
|
||||||
|
write("luauType", prop.ty);
|
||||||
popComma(c);
|
popComma(c);
|
||||||
writeRaw("}");
|
writeRaw("}");
|
||||||
}
|
}
|
||||||
@ -731,8 +758,9 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
bool c = pushComma();
|
bool c = pushComma();
|
||||||
|
|
||||||
write("name", prop.name);
|
write("name", prop.name);
|
||||||
|
writeType("AstTableProp");
|
||||||
write("location", prop.location);
|
write("location", prop.location);
|
||||||
write("type", prop.type);
|
write("propType", prop.type);
|
||||||
|
|
||||||
popComma(c);
|
popComma(c);
|
||||||
writeRaw("}");
|
writeRaw("}");
|
||||||
@ -746,6 +774,24 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write(struct AstTableIndexer* indexer)
|
||||||
|
{
|
||||||
|
if (indexer)
|
||||||
|
{
|
||||||
|
writeRaw("{");
|
||||||
|
bool c = pushComma();
|
||||||
|
write("location", indexer->location);
|
||||||
|
write("indexType", indexer->indexType);
|
||||||
|
write("resultType", indexer->resultType);
|
||||||
|
popComma(c);
|
||||||
|
writeRaw("}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeRaw("null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void write(class AstTypeFunction* node)
|
void write(class AstTypeFunction* node)
|
||||||
{
|
{
|
||||||
writeNode(node, "AstTypeFunction", [&]() {
|
writeNode(node, "AstTypeFunction", [&]() {
|
||||||
@ -836,6 +882,12 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool visit(class AstExprIfElse* node) override
|
||||||
|
{
|
||||||
|
write(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool visit(class AstExprLocal* node) override
|
bool visit(class AstExprLocal* node) override
|
||||||
{
|
{
|
||||||
write(node);
|
write(node);
|
||||||
@ -1093,6 +1145,42 @@ struct AstJsonEncoder : public AstVisitor
|
|||||||
write(node);
|
write(node);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeComments(std::vector<Comment> commentLocations)
|
||||||
|
{
|
||||||
|
bool commentComma = false;
|
||||||
|
for (Comment comment : commentLocations)
|
||||||
|
{
|
||||||
|
if (commentComma)
|
||||||
|
{
|
||||||
|
writeRaw(",");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
commentComma = true;
|
||||||
|
}
|
||||||
|
writeRaw("{");
|
||||||
|
bool c = pushComma();
|
||||||
|
switch (comment.type)
|
||||||
|
{
|
||||||
|
case Lexeme::Comment:
|
||||||
|
writeType("Comment");
|
||||||
|
break;
|
||||||
|
case Lexeme::BlockComment:
|
||||||
|
writeType("BlockComment");
|
||||||
|
break;
|
||||||
|
case Lexeme::BrokenComment:
|
||||||
|
writeType("BrokenComment");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
write("location", comment.location);
|
||||||
|
popComma(c);
|
||||||
|
writeRaw("}");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string toJson(AstNode* node)
|
std::string toJson(AstNode* node)
|
||||||
@ -1102,4 +1190,15 @@ std::string toJson(AstNode* node)
|
|||||||
return encoder.str();
|
return encoder.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string toJson(AstNode* node, const std::vector<Comment>& commentLocations)
|
||||||
|
{
|
||||||
|
AstJsonEncoder encoder;
|
||||||
|
encoder.writeRaw(R"({"root":)");
|
||||||
|
node->visit(&encoder);
|
||||||
|
encoder.writeRaw(R"(,"commentLocations":[)");
|
||||||
|
encoder.writeComments(commentLocations);
|
||||||
|
encoder.writeRaw("]}");
|
||||||
|
return encoder.str();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Luau
|
} // namespace Luau
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
LUAU_FASTFLAG(LuauLowerBoundsCalculation);
|
LUAU_FASTFLAG(LuauLowerBoundsCalculation);
|
||||||
LUAU_FASTFLAG(LuauNormalizeFlagIsConservative);
|
LUAU_FASTFLAG(LuauNormalizeFlagIsConservative);
|
||||||
LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution);
|
LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution);
|
||||||
|
LUAU_FASTFLAGVARIABLE(LuauForceExportSurfacesToBeNormal, false);
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
@ -124,15 +125,21 @@ void Module::clonePublicInterface(InternalErrorReporter& ice)
|
|||||||
moduleScope2->returnType = returnType; // TODO varargPack
|
moduleScope2->returnType = returnType; // TODO varargPack
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ForceNormal forceNormal{&interfaceTypes};
|
||||||
|
|
||||||
if (FFlag::LuauLowerBoundsCalculation)
|
if (FFlag::LuauLowerBoundsCalculation)
|
||||||
{
|
{
|
||||||
normalize(returnType, interfaceTypes, ice);
|
normalize(returnType, interfaceTypes, ice);
|
||||||
|
if (FFlag::LuauForceExportSurfacesToBeNormal)
|
||||||
|
forceNormal.traverse(returnType);
|
||||||
if (varargPack)
|
if (varargPack)
|
||||||
|
{
|
||||||
normalize(*varargPack, interfaceTypes, ice);
|
normalize(*varargPack, interfaceTypes, ice);
|
||||||
|
if (FFlag::LuauForceExportSurfacesToBeNormal)
|
||||||
|
forceNormal.traverse(*varargPack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ForceNormal forceNormal{&interfaceTypes};
|
|
||||||
|
|
||||||
if (exportedTypeBindings)
|
if (exportedTypeBindings)
|
||||||
{
|
{
|
||||||
for (auto& [name, tf] : *exportedTypeBindings)
|
for (auto& [name, tf] : *exportedTypeBindings)
|
||||||
@ -147,6 +154,16 @@ void Module::clonePublicInterface(InternalErrorReporter& ice)
|
|||||||
// We're about to freeze the memory. We know that the flag is conservative by design. Cyclic tables
|
// We're about to freeze the memory. We know that the flag is conservative by design. Cyclic tables
|
||||||
// won't be marked normal. If the types aren't normal by now, they never will be.
|
// won't be marked normal. If the types aren't normal by now, they never will be.
|
||||||
forceNormal.traverse(tf.type);
|
forceNormal.traverse(tf.type);
|
||||||
|
for (GenericTypeDefinition param : tf.typeParams)
|
||||||
|
{
|
||||||
|
forceNormal.traverse(param.ty);
|
||||||
|
|
||||||
|
if (param.defaultValue)
|
||||||
|
{
|
||||||
|
normalize(*param.defaultValue, interfaceTypes, ice);
|
||||||
|
forceNormal.traverse(*param.defaultValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,7 +183,12 @@ void Module::clonePublicInterface(InternalErrorReporter& ice)
|
|||||||
{
|
{
|
||||||
ty = clone(ty, interfaceTypes, cloneState);
|
ty = clone(ty, interfaceTypes, cloneState);
|
||||||
if (FFlag::LuauLowerBoundsCalculation)
|
if (FFlag::LuauLowerBoundsCalculation)
|
||||||
|
{
|
||||||
normalize(ty, interfaceTypes, ice);
|
normalize(ty, interfaceTypes, ice);
|
||||||
|
|
||||||
|
if (FFlag::LuauForceExportSurfacesToBeNormal)
|
||||||
|
forceNormal.traverse(ty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
freeze(internalTypes);
|
freeze(internalTypes);
|
||||||
|
@ -31,6 +31,7 @@ LUAU_FASTINTVARIABLE(LuauCheckRecursionLimit, 300)
|
|||||||
LUAU_FASTINTVARIABLE(LuauVisitRecursionLimit, 500)
|
LUAU_FASTINTVARIABLE(LuauVisitRecursionLimit, 500)
|
||||||
LUAU_FASTFLAG(LuauKnowsTheDataModel3)
|
LUAU_FASTFLAG(LuauKnowsTheDataModel3)
|
||||||
LUAU_FASTFLAG(LuauAutocompleteDynamicLimits)
|
LUAU_FASTFLAG(LuauAutocompleteDynamicLimits)
|
||||||
|
LUAU_FASTFLAGVARIABLE(LuauExpectedTableUnionIndexerType, false)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauIndexSilenceErrors, false)
|
LUAU_FASTFLAGVARIABLE(LuauIndexSilenceErrors, false)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauLowerBoundsCalculation, false)
|
LUAU_FASTFLAGVARIABLE(LuauLowerBoundsCalculation, false)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauFreezeDuringUnification, false)
|
LUAU_FASTFLAGVARIABLE(DebugLuauFreezeDuringUnification, false)
|
||||||
@ -38,7 +39,6 @@ LUAU_FASTFLAGVARIABLE(LuauSelfCallAutocompleteFix2, false)
|
|||||||
LUAU_FASTFLAGVARIABLE(LuauReduceUnionRecursion, false)
|
LUAU_FASTFLAGVARIABLE(LuauReduceUnionRecursion, false)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauReturnAnyInsteadOfICE, false) // Eventually removed as false.
|
LUAU_FASTFLAGVARIABLE(LuauReturnAnyInsteadOfICE, false) // Eventually removed as false.
|
||||||
LUAU_FASTFLAG(LuauNormalizeFlagIsConservative)
|
LUAU_FASTFLAG(LuauNormalizeFlagIsConservative)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauReturnTypeInferenceInNonstrict, false)
|
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauSharedSelf, false);
|
LUAU_FASTFLAGVARIABLE(DebugLuauSharedSelf, false);
|
||||||
LUAU_FASTFLAGVARIABLE(LuauAlwaysQuantify, false);
|
LUAU_FASTFLAGVARIABLE(LuauAlwaysQuantify, false);
|
||||||
LUAU_FASTFLAGVARIABLE(LuauReportErrorsOnIndexerKeyMismatch, false)
|
LUAU_FASTFLAGVARIABLE(LuauReportErrorsOnIndexerKeyMismatch, false)
|
||||||
@ -50,6 +50,7 @@ LUAU_FASTFLAGVARIABLE(LuauCheckGenericHOFTypes, false)
|
|||||||
LUAU_FASTFLAGVARIABLE(LuauBinaryNeedsExpectedTypesToo, false)
|
LUAU_FASTFLAGVARIABLE(LuauBinaryNeedsExpectedTypesToo, false)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauNeverTypesAndOperatorsInference, false)
|
LUAU_FASTFLAGVARIABLE(LuauNeverTypesAndOperatorsInference, false)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauReturnsFromCallsitesAreNotWidened, false)
|
LUAU_FASTFLAGVARIABLE(LuauReturnsFromCallsitesAreNotWidened, false)
|
||||||
|
LUAU_FASTFLAGVARIABLE(LuauCompleteVisitor, false)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
@ -890,7 +891,7 @@ void TypeChecker::check(const ScopePtr& scope, const AstStatReturn& return_)
|
|||||||
|
|
||||||
TypePackId retPack = checkExprList(scope, return_.location, return_.list, false, {}, expectedTypes).type;
|
TypePackId retPack = checkExprList(scope, return_.location, return_.list, false, {}, expectedTypes).type;
|
||||||
|
|
||||||
if (FFlag::LuauReturnTypeInferenceInNonstrict ? FFlag::LuauLowerBoundsCalculation : useConstrainedIntersections())
|
if (useConstrainedIntersections())
|
||||||
{
|
{
|
||||||
unifyLowerBound(retPack, scope->returnType, demoter.demotedLevel(scope->level), return_.location);
|
unifyLowerBound(retPack, scope->returnType, demoter.demotedLevel(scope->level), return_.location);
|
||||||
return;
|
return;
|
||||||
@ -1292,6 +1293,11 @@ void TypeChecker::check(const ScopePtr& scope, const AstStatForIn& forin)
|
|||||||
for (size_t i = 2; i < varTypes.size(); ++i)
|
for (size_t i = 2; i < varTypes.size(); ++i)
|
||||||
unify(nilType, varTypes[i], forin.location);
|
unify(nilType, varTypes[i], forin.location);
|
||||||
}
|
}
|
||||||
|
else if (isNonstrictMode())
|
||||||
|
{
|
||||||
|
for (TypeId var : varTypes)
|
||||||
|
unify(anyType, var, forin.location);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TypeId varTy = errorRecoveryType(loopScope);
|
TypeId varTy = errorRecoveryType(loopScope);
|
||||||
@ -1385,12 +1391,7 @@ void TypeChecker::check(const ScopePtr& scope, TypeId ty, const ScopePtr& funSco
|
|||||||
// If in nonstrict mode and allowing redefinition of global function, restore the previous definition type
|
// If in nonstrict mode and allowing redefinition of global function, restore the previous definition type
|
||||||
// in case this function has a differing signature. The signature discrepancy will be caught in checkBlock.
|
// in case this function has a differing signature. The signature discrepancy will be caught in checkBlock.
|
||||||
if (previouslyDefined)
|
if (previouslyDefined)
|
||||||
{
|
|
||||||
if (FFlag::LuauReturnTypeInferenceInNonstrict && FFlag::LuauLowerBoundsCalculation)
|
|
||||||
quantify(funScope, ty, exprName->location);
|
|
||||||
|
|
||||||
globalBindings[name] = oldBinding;
|
globalBindings[name] = oldBinding;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
globalBindings[name] = {quantify(funScope, ty, exprName->location), exprName->location};
|
globalBindings[name] = {quantify(funScope, ty, exprName->location), exprName->location};
|
||||||
|
|
||||||
@ -2365,9 +2366,16 @@ WithPredicate<TypeId> TypeChecker::checkExpr(const ScopePtr& scope, const AstExp
|
|||||||
{
|
{
|
||||||
std::vector<TypeId> expectedResultTypes;
|
std::vector<TypeId> expectedResultTypes;
|
||||||
for (TypeId expectedOption : expectedUnion)
|
for (TypeId expectedOption : expectedUnion)
|
||||||
|
{
|
||||||
if (const TableTypeVar* ttv = get<TableTypeVar>(follow(expectedOption)))
|
if (const TableTypeVar* ttv = get<TableTypeVar>(follow(expectedOption)))
|
||||||
|
{
|
||||||
if (auto prop = ttv->props.find(key->value.data); prop != ttv->props.end())
|
if (auto prop = ttv->props.find(key->value.data); prop != ttv->props.end())
|
||||||
expectedResultTypes.push_back(prop->second.type);
|
expectedResultTypes.push_back(prop->second.type);
|
||||||
|
else if (FFlag::LuauExpectedTableUnionIndexerType && ttv->indexer && maybeString(ttv->indexer->indexType))
|
||||||
|
expectedResultTypes.push_back(ttv->indexer->indexResultType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (expectedResultTypes.size() == 1)
|
if (expectedResultTypes.size() == 1)
|
||||||
expectedResultType = expectedResultTypes[0];
|
expectedResultType = expectedResultTypes[0];
|
||||||
else if (expectedResultTypes.size() > 1)
|
else if (expectedResultTypes.size() > 1)
|
||||||
@ -3367,7 +3375,7 @@ std::pair<TypeId, ScopePtr> TypeChecker::checkFunctionSignature(const ScopePtr&
|
|||||||
TypePackId retPack;
|
TypePackId retPack;
|
||||||
if (expr.returnAnnotation)
|
if (expr.returnAnnotation)
|
||||||
retPack = resolveTypePack(funScope, *expr.returnAnnotation);
|
retPack = resolveTypePack(funScope, *expr.returnAnnotation);
|
||||||
else if (FFlag::LuauReturnTypeInferenceInNonstrict ? (!FFlag::LuauLowerBoundsCalculation && isNonstrictMode()) : isNonstrictMode())
|
else if (isNonstrictMode())
|
||||||
retPack = anyTypePack;
|
retPack = anyTypePack;
|
||||||
else if (expectedFunctionType &&
|
else if (expectedFunctionType &&
|
||||||
(!FFlag::LuauCheckGenericHOFTypes || (expectedFunctionType->generics.empty() && expectedFunctionType->genericPacks.empty())))
|
(!FFlag::LuauCheckGenericHOFTypes || (expectedFunctionType->generics.empty() && expectedFunctionType->genericPacks.empty())))
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "Luau/Transpiler.h"
|
#include "Luau/Transpiler.h"
|
||||||
|
|
||||||
#include "FileUtils.h"
|
#include "FileUtils.h"
|
||||||
|
#include "Flags.h"
|
||||||
|
|
||||||
#ifdef CALLGRIND
|
#ifdef CALLGRIND
|
||||||
#include <valgrind/callgrind.h>
|
#include <valgrind/callgrind.h>
|
||||||
@ -223,9 +224,7 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
Luau::assertHandler() = assertionHandler;
|
Luau::assertHandler() = assertionHandler;
|
||||||
|
|
||||||
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
setLuauFlagsDefault();
|
||||||
if (strncmp(flag->name, "Luau", 4) == 0)
|
|
||||||
flag->value = true;
|
|
||||||
|
|
||||||
if (argc >= 2 && strcmp(argv[1], "--help") == 0)
|
if (argc >= 2 && strcmp(argv[1], "--help") == 0)
|
||||||
{
|
{
|
||||||
@ -252,12 +251,14 @@ int main(int argc, char** argv)
|
|||||||
annotate = true;
|
annotate = true;
|
||||||
else if (strcmp(argv[i], "--timetrace") == 0)
|
else if (strcmp(argv[i], "--timetrace") == 0)
|
||||||
FFlag::DebugLuauTimeTracing.value = true;
|
FFlag::DebugLuauTimeTracing.value = true;
|
||||||
|
else if (strncmp(argv[i], "--fflags=", 9) == 0)
|
||||||
|
setLuauFlags(argv[i] + 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(LUAU_ENABLE_TIME_TRACE)
|
#if !defined(LUAU_ENABLE_TIME_TRACE)
|
||||||
if (FFlag::DebugLuauTimeTracing)
|
if (FFlag::DebugLuauTimeTracing)
|
||||||
{
|
{
|
||||||
printf("To run with --timetrace, Luau has to be built with LUAU_ENABLE_TIME_TRACE enabled\n");
|
fprintf(stderr, "To run with --timetrace, Luau has to be built with LUAU_ENABLE_TIME_TRACE enabled\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -62,6 +62,7 @@ int main(int argc, char** argv)
|
|||||||
Luau::AstNameTable names(allocator);
|
Luau::AstNameTable names(allocator);
|
||||||
|
|
||||||
Luau::ParseOptions options;
|
Luau::ParseOptions options;
|
||||||
|
options.captureComments = true;
|
||||||
options.supportContinueStatement = true;
|
options.supportContinueStatement = true;
|
||||||
options.allowTypeAnnotations = true;
|
options.allowTypeAnnotations = true;
|
||||||
options.allowDeclarationSyntax = true;
|
options.allowDeclarationSyntax = true;
|
||||||
@ -78,7 +79,7 @@ int main(int argc, char** argv)
|
|||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s", Luau::toJson(parseResult.root).c_str());
|
printf("%s", Luau::toJson(parseResult.root, parseResult.commentLocations).c_str());
|
||||||
|
|
||||||
return parseResult.errors.size() > 0 ? 1 : 0;
|
return parseResult.errors.size() > 0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
75
CLI/Flags.cpp
Normal file
75
CLI/Flags.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||||
|
#include "Luau/Common.h"
|
||||||
|
#include "Luau/ExperimentalFlags.h"
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static void setLuauFlag(std::string_view name, bool state)
|
||||||
|
{
|
||||||
|
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
||||||
|
{
|
||||||
|
if (name == flag->name)
|
||||||
|
{
|
||||||
|
flag->value = state;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Warning: unrecognized flag '%.*s'.\n", int(name.length()), name.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setLuauFlags(bool state)
|
||||||
|
{
|
||||||
|
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
||||||
|
if (strncmp(flag->name, "Luau", 4) == 0)
|
||||||
|
flag->value = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLuauFlagsDefault()
|
||||||
|
{
|
||||||
|
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
||||||
|
if (strncmp(flag->name, "Luau", 4) == 0 && !Luau::isFlagExperimental(flag->name))
|
||||||
|
flag->value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLuauFlags(const char* list)
|
||||||
|
{
|
||||||
|
std::string_view rest = list;
|
||||||
|
|
||||||
|
while (!rest.empty())
|
||||||
|
{
|
||||||
|
size_t ending = rest.find(",");
|
||||||
|
std::string_view element = rest.substr(0, ending);
|
||||||
|
|
||||||
|
if (size_t separator = element.find('='); separator != std::string_view::npos)
|
||||||
|
{
|
||||||
|
std::string_view key = element.substr(0, separator);
|
||||||
|
std::string_view value = element.substr(separator + 1);
|
||||||
|
|
||||||
|
if (value == "true" || value == "True")
|
||||||
|
setLuauFlag(key, true);
|
||||||
|
else if (value == "false" || value == "False")
|
||||||
|
setLuauFlag(key, false);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "Warning: unrecognized value '%.*s' for flag '%.*s'.\n", int(value.length()), value.data(), int(key.length()),
|
||||||
|
key.data());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (element == "true" || element == "True")
|
||||||
|
setLuauFlags(true);
|
||||||
|
else if (element == "false" || element == "False")
|
||||||
|
setLuauFlags(false);
|
||||||
|
else
|
||||||
|
setLuauFlag(element, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ending != std::string_view::npos)
|
||||||
|
rest.remove_prefix(ending + 1);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
5
CLI/Flags.h
Normal file
5
CLI/Flags.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
void setLuauFlagsDefault();
|
||||||
|
void setLuauFlags(const char* list);
|
91
CLI/Repl.cpp
91
CLI/Repl.cpp
@ -8,9 +8,10 @@
|
|||||||
#include "Luau/BytecodeBuilder.h"
|
#include "Luau/BytecodeBuilder.h"
|
||||||
#include "Luau/Parser.h"
|
#include "Luau/Parser.h"
|
||||||
|
|
||||||
#include "FileUtils.h"
|
|
||||||
#include "Profiler.h"
|
|
||||||
#include "Coverage.h"
|
#include "Coverage.h"
|
||||||
|
#include "FileUtils.h"
|
||||||
|
#include "Flags.h"
|
||||||
|
#include "Profiler.h"
|
||||||
|
|
||||||
#include "isocline.h"
|
#include "isocline.h"
|
||||||
|
|
||||||
@ -97,7 +98,11 @@ static int lua_require(lua_State* L)
|
|||||||
// return the module from the cache
|
// return the module from the cache
|
||||||
lua_getfield(L, -1, name.c_str());
|
lua_getfield(L, -1, name.c_str());
|
||||||
if (!lua_isnil(L, -1))
|
if (!lua_isnil(L, -1))
|
||||||
|
{
|
||||||
|
// L stack: _MODULES result
|
||||||
return finishrequire(L);
|
return finishrequire(L);
|
||||||
|
}
|
||||||
|
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
std::optional<std::string> source = readFile(name + ".luau");
|
std::optional<std::string> source = readFile(name + ".luau");
|
||||||
@ -109,6 +114,7 @@ static int lua_require(lua_State* L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// module needs to run in a new thread, isolated from the rest
|
// module needs to run in a new thread, isolated from the rest
|
||||||
|
// note: we create ML on main thread so that it doesn't inherit environment of L
|
||||||
lua_State* GL = lua_mainthread(L);
|
lua_State* GL = lua_mainthread(L);
|
||||||
lua_State* ML = lua_newthread(GL);
|
lua_State* ML = lua_newthread(GL);
|
||||||
lua_xmove(GL, L, 1);
|
lua_xmove(GL, L, 1);
|
||||||
@ -142,11 +148,12 @@ static int lua_require(lua_State* L)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// there's now a return value on top of ML; stack of L is MODULES thread
|
// there's now a return value on top of ML; L stack: _MODULES ML
|
||||||
lua_xmove(ML, L, 1);
|
lua_xmove(ML, L, 1);
|
||||||
lua_pushvalue(L, -1);
|
lua_pushvalue(L, -1);
|
||||||
lua_setfield(L, -4, name.c_str());
|
lua_setfield(L, -4, name.c_str());
|
||||||
|
|
||||||
|
// L stack: _MODULES ML result
|
||||||
return finishrequire(L);
|
return finishrequire(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -682,60 +689,11 @@ static int assertionHandler(const char* expr, const char* file, int line, const
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setLuauFlags(bool state)
|
|
||||||
{
|
|
||||||
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
|
||||||
{
|
|
||||||
if (strncmp(flag->name, "Luau", 4) == 0)
|
|
||||||
flag->value = state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setFlag(std::string_view name, bool state)
|
|
||||||
{
|
|
||||||
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
|
||||||
{
|
|
||||||
if (name == flag->name)
|
|
||||||
{
|
|
||||||
flag->value = state;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "Warning: --fflag unrecognized flag '%.*s'.\n\n", int(name.length()), name.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void applyFlagKeyValue(std::string_view element)
|
|
||||||
{
|
|
||||||
if (size_t separator = element.find('='); separator != std::string_view::npos)
|
|
||||||
{
|
|
||||||
std::string_view key = element.substr(0, separator);
|
|
||||||
std::string_view value = element.substr(separator + 1);
|
|
||||||
|
|
||||||
if (value == "true")
|
|
||||||
setFlag(key, true);
|
|
||||||
else if (value == "false")
|
|
||||||
setFlag(key, false);
|
|
||||||
else
|
|
||||||
fprintf(stderr, "Warning: --fflag unrecognized value '%.*s' for flag '%.*s'.\n\n", int(value.length()), value.data(), int(key.length()),
|
|
||||||
key.data());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (element == "true")
|
|
||||||
setLuauFlags(true);
|
|
||||||
else if (element == "false")
|
|
||||||
setLuauFlags(false);
|
|
||||||
else
|
|
||||||
setFlag(element, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int replMain(int argc, char** argv)
|
int replMain(int argc, char** argv)
|
||||||
{
|
{
|
||||||
Luau::assertHandler() = assertionHandler;
|
Luau::assertHandler() = assertionHandler;
|
||||||
|
|
||||||
setLuauFlags(true);
|
setLuauFlagsDefault();
|
||||||
|
|
||||||
CliMode mode = CliMode::Unknown;
|
CliMode mode = CliMode::Unknown;
|
||||||
CompileFormat compileFormat{};
|
CompileFormat compileFormat{};
|
||||||
@ -818,27 +776,10 @@ int replMain(int argc, char** argv)
|
|||||||
else if (strcmp(argv[i], "--timetrace") == 0)
|
else if (strcmp(argv[i], "--timetrace") == 0)
|
||||||
{
|
{
|
||||||
FFlag::DebugLuauTimeTracing.value = true;
|
FFlag::DebugLuauTimeTracing.value = true;
|
||||||
|
|
||||||
#if !defined(LUAU_ENABLE_TIME_TRACE)
|
|
||||||
printf("To run with --timetrace, Luau has to be built with LUAU_ENABLE_TIME_TRACE enabled\n");
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (strncmp(argv[i], "--fflags=", 9) == 0)
|
else if (strncmp(argv[i], "--fflags=", 9) == 0)
|
||||||
{
|
{
|
||||||
std::string_view list = argv[i] + 9;
|
setLuauFlags(argv[i] + 9);
|
||||||
|
|
||||||
while (!list.empty())
|
|
||||||
{
|
|
||||||
size_t ending = list.find(",");
|
|
||||||
|
|
||||||
applyFlagKeyValue(list.substr(0, ending));
|
|
||||||
|
|
||||||
if (ending != std::string_view::npos)
|
|
||||||
list.remove_prefix(ending + 1);
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (argv[i][0] == '-')
|
else if (argv[i][0] == '-')
|
||||||
{
|
{
|
||||||
@ -848,6 +789,14 @@ int replMain(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(LUAU_ENABLE_TIME_TRACE)
|
||||||
|
if (FFlag::DebugLuauTimeTracing)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "To run with --timetrace, Luau has to be built with LUAU_ENABLE_TIME_TRACE enabled\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
const std::vector<std::string> files = getSourceFiles(argc, argv);
|
const std::vector<std::string> files = getSourceFiles(argc, argv);
|
||||||
if (mode == CliMode::Unknown)
|
if (mode == CliMode::Unknown)
|
||||||
{
|
{
|
||||||
|
@ -61,12 +61,22 @@ public:
|
|||||||
void call(Label& label);
|
void call(Label& label);
|
||||||
void call(OperandX64 op);
|
void call(OperandX64 op);
|
||||||
|
|
||||||
|
void int3();
|
||||||
|
|
||||||
// AVX
|
// AVX
|
||||||
void vaddpd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
void vaddpd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||||
void vaddps(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
void vaddps(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||||
void vaddsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
void vaddsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||||
void vaddss(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
void vaddss(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||||
|
|
||||||
|
void vsubsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||||
|
void vmulsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||||
|
void vdivsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||||
|
|
||||||
|
void vxorpd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||||
|
|
||||||
|
void vcomisd(OperandX64 src1, OperandX64 src2);
|
||||||
|
|
||||||
void vsqrtpd(OperandX64 dst, OperandX64 src);
|
void vsqrtpd(OperandX64 dst, OperandX64 src);
|
||||||
void vsqrtps(OperandX64 dst, OperandX64 src);
|
void vsqrtps(OperandX64 dst, OperandX64 src);
|
||||||
void vsqrtsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
void vsqrtsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||||
|
@ -37,8 +37,6 @@ enum class Condition
|
|||||||
Zero,
|
Zero,
|
||||||
NotZero,
|
NotZero,
|
||||||
|
|
||||||
// TODO: ordered and unordered floating-point conditions
|
|
||||||
|
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -231,6 +231,7 @@ void AssemblyBuilderX64::lea(OperandX64 lhs, OperandX64 rhs)
|
|||||||
if (logText)
|
if (logText)
|
||||||
log("lea", lhs, rhs);
|
log("lea", lhs, rhs);
|
||||||
|
|
||||||
|
LUAU_ASSERT(rhs.cat == CategoryX64::mem);
|
||||||
placeBinaryRegAndRegMem(lhs, rhs, 0x8d, 0x8d);
|
placeBinaryRegAndRegMem(lhs, rhs, 0x8d, 0x8d);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,6 +315,14 @@ void AssemblyBuilderX64::call(OperandX64 op)
|
|||||||
commit();
|
commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssemblyBuilderX64::int3()
|
||||||
|
{
|
||||||
|
if (logText)
|
||||||
|
log("int3");
|
||||||
|
|
||||||
|
place(0xcc);
|
||||||
|
}
|
||||||
|
|
||||||
void AssemblyBuilderX64::vaddpd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
|
void AssemblyBuilderX64::vaddpd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
|
||||||
{
|
{
|
||||||
placeAvx("vaddpd", dst, src1, src2, 0x58, false, AVX_0F, AVX_66);
|
placeAvx("vaddpd", dst, src1, src2, 0x58, false, AVX_0F, AVX_66);
|
||||||
@ -334,6 +343,31 @@ void AssemblyBuilderX64::vaddss(OperandX64 dst, OperandX64 src1, OperandX64 src2
|
|||||||
placeAvx("vaddss", dst, src1, src2, 0x58, false, AVX_0F, AVX_F3);
|
placeAvx("vaddss", dst, src1, src2, 0x58, false, AVX_0F, AVX_F3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssemblyBuilderX64::vsubsd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
|
||||||
|
{
|
||||||
|
placeAvx("vsubsd", dst, src1, src2, 0x5c, false, AVX_0F, AVX_F2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssemblyBuilderX64::vmulsd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
|
||||||
|
{
|
||||||
|
placeAvx("vmulsd", dst, src1, src2, 0x59, false, AVX_0F, AVX_F2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssemblyBuilderX64::vdivsd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
|
||||||
|
{
|
||||||
|
placeAvx("vdivsd", dst, src1, src2, 0x5e, false, AVX_0F, AVX_F2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssemblyBuilderX64::vxorpd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
|
||||||
|
{
|
||||||
|
placeAvx("vxorpd", dst, src1, src2, 0x57, false, AVX_0F, AVX_66);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssemblyBuilderX64::vcomisd(OperandX64 src1, OperandX64 src2)
|
||||||
|
{
|
||||||
|
placeAvx("vcomisd", src1, src2, 0x2f, false, AVX_0F, AVX_66);
|
||||||
|
}
|
||||||
|
|
||||||
void AssemblyBuilderX64::vsqrtpd(OperandX64 dst, OperandX64 src)
|
void AssemblyBuilderX64::vsqrtpd(OperandX64 dst, OperandX64 src)
|
||||||
{
|
{
|
||||||
placeAvx("vsqrtpd", dst, src, 0x51, false, AVX_0F, AVX_66);
|
placeAvx("vsqrtpd", dst, src, 0x51, false, AVX_0F, AVX_66);
|
||||||
@ -494,9 +528,10 @@ void AssemblyBuilderX64::placeBinaryRegMemAndImm(OperandX64 lhs, OperandX64 rhs,
|
|||||||
LUAU_ASSERT(lhs.cat == CategoryX64::reg || lhs.cat == CategoryX64::mem);
|
LUAU_ASSERT(lhs.cat == CategoryX64::reg || lhs.cat == CategoryX64::mem);
|
||||||
LUAU_ASSERT(rhs.cat == CategoryX64::imm);
|
LUAU_ASSERT(rhs.cat == CategoryX64::imm);
|
||||||
|
|
||||||
SizeX64 size = lhs.base.size;
|
SizeX64 size = lhs.cat == CategoryX64::reg ? lhs.base.size : lhs.memSize;
|
||||||
|
LUAU_ASSERT(size == SizeX64::byte || size == SizeX64::dword || size == SizeX64::qword);
|
||||||
|
|
||||||
placeRex(lhs.base);
|
placeRex(lhs);
|
||||||
|
|
||||||
if (size == SizeX64::byte)
|
if (size == SizeX64::byte)
|
||||||
{
|
{
|
||||||
|
26
Common/include/Luau/ExperimentalFlags.h
Normal file
26
Common/include/Luau/ExperimentalFlags.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace Luau
|
||||||
|
{
|
||||||
|
|
||||||
|
inline bool isFlagExperimental(const char* flag)
|
||||||
|
{
|
||||||
|
// Flags in this list are disabled by default in various command-line tools. They may have behavior that is not fully final,
|
||||||
|
// or critical bugs that are found after the code has been submitted.
|
||||||
|
static const char* kList[] =
|
||||||
|
{
|
||||||
|
"LuauLowerBoundsCalculation",
|
||||||
|
nullptr, // makes sure we always have at least one entry
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const char* item: kList)
|
||||||
|
if (item && strcmp(item, flag) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -27,6 +27,7 @@ LUAU_FASTFLAGVARIABLE(LuauCompileNoIpairs, false)
|
|||||||
|
|
||||||
LUAU_FASTFLAGVARIABLE(LuauCompileFoldBuiltins, false)
|
LUAU_FASTFLAGVARIABLE(LuauCompileFoldBuiltins, false)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauCompileBetterMultret, false)
|
LUAU_FASTFLAGVARIABLE(LuauCompileBetterMultret, false)
|
||||||
|
LUAU_FASTFLAGVARIABLE(LuauCompileFreeReassign, false)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
@ -616,7 +617,7 @@ struct Compiler
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AstExprLocal* le = arg->as<AstExprLocal>();
|
AstExprLocal* le = FFlag::LuauCompileFreeReassign ? getExprLocal(arg) : arg->as<AstExprLocal>();
|
||||||
Variable* lv = le ? variables.find(le->local) : nullptr;
|
Variable* lv = le ? variables.find(le->local) : nullptr;
|
||||||
|
|
||||||
// if the argument is a local that isn't mutated, we will simply reuse the existing register
|
// if the argument is a local that isn't mutated, we will simply reuse the existing register
|
||||||
@ -2200,19 +2201,27 @@ struct Compiler
|
|||||||
compileLValueUse(lv, source, /* set= */ true);
|
compileLValueUse(lv, source, /* set= */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getExprLocalReg(AstExpr* node)
|
AstExprLocal* getExprLocal(AstExpr* node)
|
||||||
{
|
{
|
||||||
if (AstExprLocal* expr = node->as<AstExprLocal>())
|
if (AstExprLocal* expr = node->as<AstExprLocal>())
|
||||||
|
return expr;
|
||||||
|
else if (AstExprGroup* expr = node->as<AstExprGroup>())
|
||||||
|
return getExprLocal(expr->expr);
|
||||||
|
else if (AstExprTypeAssertion* expr = node->as<AstExprTypeAssertion>())
|
||||||
|
return getExprLocal(expr->expr);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getExprLocalReg(AstExpr* node)
|
||||||
|
{
|
||||||
|
if (AstExprLocal* expr = getExprLocal(node))
|
||||||
{
|
{
|
||||||
// note: this can't check expr->upvalue because upvalues may be upgraded to locals during inlining
|
// note: this can't check expr->upvalue because upvalues may be upgraded to locals during inlining
|
||||||
Local* l = locals.find(expr->local);
|
Local* l = locals.find(expr->local);
|
||||||
|
|
||||||
return l && l->allocated ? l->reg : -1;
|
return l && l->allocated ? l->reg : -1;
|
||||||
}
|
}
|
||||||
else if (AstExprGroup* expr = node->as<AstExprGroup>())
|
|
||||||
return getExprLocalReg(expr->expr);
|
|
||||||
else if (AstExprTypeAssertion* expr = node->as<AstExprTypeAssertion>())
|
|
||||||
return getExprLocalReg(expr->expr);
|
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -2498,6 +2507,22 @@ struct Compiler
|
|||||||
if (options.optimizationLevel >= 1 && options.debugLevel <= 1 && areLocalsRedundant(stat))
|
if (options.optimizationLevel >= 1 && options.debugLevel <= 1 && areLocalsRedundant(stat))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Optimization: for 1-1 local assignments, we can reuse the register *if* neither local is mutated
|
||||||
|
if (FFlag::LuauCompileFreeReassign && options.optimizationLevel >= 1 && stat->vars.size == 1 && stat->values.size == 1)
|
||||||
|
{
|
||||||
|
if (AstExprLocal* re = getExprLocal(stat->values.data[0]))
|
||||||
|
{
|
||||||
|
Variable* lv = variables.find(stat->vars.data[0]);
|
||||||
|
Variable* rv = variables.find(re->local);
|
||||||
|
|
||||||
|
if (int reg = getExprLocalReg(re); reg >= 0 && (!lv || !lv->written) && (!rv || !rv->written))
|
||||||
|
{
|
||||||
|
pushLocal(stat->vars.data[0], uint8_t(reg));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// note: allocReg in this case allocates into parent block register - note that we don't have RegScope here
|
// note: allocReg in this case allocates into parent block register - note that we don't have RegScope here
|
||||||
uint8_t vars = allocReg(stat, unsigned(stat->vars.size));
|
uint8_t vars = allocReg(stat, unsigned(stat->vars.size));
|
||||||
|
|
||||||
|
13
Makefile
13
Makefile
@ -31,15 +31,15 @@ ISOCLINE_SOURCES=extern/isocline/src/isocline.c
|
|||||||
ISOCLINE_OBJECTS=$(ISOCLINE_SOURCES:%=$(BUILD)/%.o)
|
ISOCLINE_OBJECTS=$(ISOCLINE_SOURCES:%=$(BUILD)/%.o)
|
||||||
ISOCLINE_TARGET=$(BUILD)/libisocline.a
|
ISOCLINE_TARGET=$(BUILD)/libisocline.a
|
||||||
|
|
||||||
TESTS_SOURCES=$(wildcard tests/*.cpp) CLI/FileUtils.cpp CLI/Profiler.cpp CLI/Coverage.cpp CLI/Repl.cpp
|
TESTS_SOURCES=$(wildcard tests/*.cpp) CLI/FileUtils.cpp CLI/Flags.cpp CLI/Profiler.cpp CLI/Coverage.cpp CLI/Repl.cpp
|
||||||
TESTS_OBJECTS=$(TESTS_SOURCES:%=$(BUILD)/%.o)
|
TESTS_OBJECTS=$(TESTS_SOURCES:%=$(BUILD)/%.o)
|
||||||
TESTS_TARGET=$(BUILD)/luau-tests
|
TESTS_TARGET=$(BUILD)/luau-tests
|
||||||
|
|
||||||
REPL_CLI_SOURCES=CLI/FileUtils.cpp CLI/Profiler.cpp CLI/Coverage.cpp CLI/Repl.cpp CLI/ReplEntry.cpp
|
REPL_CLI_SOURCES=CLI/FileUtils.cpp CLI/Flags.cpp CLI/Profiler.cpp CLI/Coverage.cpp CLI/Repl.cpp CLI/ReplEntry.cpp
|
||||||
REPL_CLI_OBJECTS=$(REPL_CLI_SOURCES:%=$(BUILD)/%.o)
|
REPL_CLI_OBJECTS=$(REPL_CLI_SOURCES:%=$(BUILD)/%.o)
|
||||||
REPL_CLI_TARGET=$(BUILD)/luau
|
REPL_CLI_TARGET=$(BUILD)/luau
|
||||||
|
|
||||||
ANALYZE_CLI_SOURCES=CLI/FileUtils.cpp CLI/Analyze.cpp
|
ANALYZE_CLI_SOURCES=CLI/FileUtils.cpp CLI/Flags.cpp CLI/Analyze.cpp
|
||||||
ANALYZE_CLI_OBJECTS=$(ANALYZE_CLI_SOURCES:%=$(BUILD)/%.o)
|
ANALYZE_CLI_OBJECTS=$(ANALYZE_CLI_SOURCES:%=$(BUILD)/%.o)
|
||||||
ANALYZE_CLI_TARGET=$(BUILD)/luau-analyze
|
ANALYZE_CLI_TARGET=$(BUILD)/luau-analyze
|
||||||
|
|
||||||
@ -117,15 +117,18 @@ $(REPL_CLI_TARGET): LDFLAGS+=-lpthread
|
|||||||
fuzz-proto fuzz-prototest: LDFLAGS+=build/libprotobuf-mutator/src/libfuzzer/libprotobuf-mutator-libfuzzer.a build/libprotobuf-mutator/src/libprotobuf-mutator.a build/libprotobuf-mutator/external.protobuf/lib/libprotobuf.a
|
fuzz-proto fuzz-prototest: LDFLAGS+=build/libprotobuf-mutator/src/libfuzzer/libprotobuf-mutator-libfuzzer.a build/libprotobuf-mutator/src/libprotobuf-mutator.a build/libprotobuf-mutator/external.protobuf/lib/libprotobuf.a
|
||||||
|
|
||||||
# pseudo targets
|
# pseudo targets
|
||||||
.PHONY: all test clean coverage format luau-size
|
.PHONY: all test clean coverage format luau-size aliases
|
||||||
|
|
||||||
all: $(REPL_CLI_TARGET) $(ANALYZE_CLI_TARGET) $(TESTS_TARGET)
|
all: $(REPL_CLI_TARGET) $(ANALYZE_CLI_TARGET) $(TESTS_TARGET) aliases
|
||||||
|
|
||||||
|
aliases: luau luau-analyze
|
||||||
|
|
||||||
test: $(TESTS_TARGET)
|
test: $(TESTS_TARGET)
|
||||||
$(TESTS_TARGET) $(TESTS_ARGS)
|
$(TESTS_TARGET) $(TESTS_ARGS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD)
|
rm -rf $(BUILD)
|
||||||
|
rm -rf luau luau-analyze
|
||||||
|
|
||||||
coverage: $(TESTS_TARGET)
|
coverage: $(TESTS_TARGET)
|
||||||
$(TESTS_TARGET) --fflags=true
|
$(TESTS_TARGET) --fflags=true
|
||||||
|
@ -4,6 +4,7 @@ if(NOT ${CMAKE_VERSION} VERSION_LESS "3.19")
|
|||||||
target_sources(Luau.Common PRIVATE
|
target_sources(Luau.Common PRIVATE
|
||||||
Common/include/Luau/Common.h
|
Common/include/Luau/Common.h
|
||||||
Common/include/Luau/Bytecode.h
|
Common/include/Luau/Bytecode.h
|
||||||
|
Common/include/Luau/ExperimentalFlags.h
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -220,6 +221,8 @@ if(TARGET Luau.Repl.CLI)
|
|||||||
CLI/Coverage.cpp
|
CLI/Coverage.cpp
|
||||||
CLI/FileUtils.h
|
CLI/FileUtils.h
|
||||||
CLI/FileUtils.cpp
|
CLI/FileUtils.cpp
|
||||||
|
CLI/Flags.h
|
||||||
|
CLI/Flags.cpp
|
||||||
CLI/Profiler.h
|
CLI/Profiler.h
|
||||||
CLI/Profiler.cpp
|
CLI/Profiler.cpp
|
||||||
CLI/Repl.cpp
|
CLI/Repl.cpp
|
||||||
@ -231,6 +234,8 @@ if(TARGET Luau.Analyze.CLI)
|
|||||||
target_sources(Luau.Analyze.CLI PRIVATE
|
target_sources(Luau.Analyze.CLI PRIVATE
|
||||||
CLI/FileUtils.h
|
CLI/FileUtils.h
|
||||||
CLI/FileUtils.cpp
|
CLI/FileUtils.cpp
|
||||||
|
CLI/Flags.h
|
||||||
|
CLI/Flags.cpp
|
||||||
CLI/Analyze.cpp)
|
CLI/Analyze.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -321,6 +326,8 @@ if(TARGET Luau.CLI.Test)
|
|||||||
CLI/Coverage.cpp
|
CLI/Coverage.cpp
|
||||||
CLI/FileUtils.h
|
CLI/FileUtils.h
|
||||||
CLI/FileUtils.cpp
|
CLI/FileUtils.cpp
|
||||||
|
CLI/Flags.h
|
||||||
|
CLI/Flags.cpp
|
||||||
CLI/Profiler.h
|
CLI/Profiler.h
|
||||||
CLI/Profiler.cpp
|
CLI/Profiler.cpp
|
||||||
CLI/Repl.cpp
|
CLI/Repl.cpp
|
||||||
|
@ -854,7 +854,7 @@ void lua_rawset(lua_State* L, int idx)
|
|||||||
StkId t = index2addr(L, idx);
|
StkId t = index2addr(L, idx);
|
||||||
api_check(L, ttistable(t));
|
api_check(L, ttistable(t));
|
||||||
if (hvalue(t)->readonly)
|
if (hvalue(t)->readonly)
|
||||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
luaG_readonlyerror(L);
|
||||||
setobj2t(L, luaH_set(L, hvalue(t), L->top - 2), L->top - 1);
|
setobj2t(L, luaH_set(L, hvalue(t), L->top - 2), L->top - 1);
|
||||||
luaC_barriert(L, hvalue(t), L->top - 1);
|
luaC_barriert(L, hvalue(t), L->top - 1);
|
||||||
L->top -= 2;
|
L->top -= 2;
|
||||||
@ -867,7 +867,7 @@ void lua_rawseti(lua_State* L, int idx, int n)
|
|||||||
StkId o = index2addr(L, idx);
|
StkId o = index2addr(L, idx);
|
||||||
api_check(L, ttistable(o));
|
api_check(L, ttistable(o));
|
||||||
if (hvalue(o)->readonly)
|
if (hvalue(o)->readonly)
|
||||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
luaG_readonlyerror(L);
|
||||||
setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top - 1);
|
setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top - 1);
|
||||||
luaC_barriert(L, hvalue(o), L->top - 1);
|
luaC_barriert(L, hvalue(o), L->top - 1);
|
||||||
L->top--;
|
L->top--;
|
||||||
@ -890,7 +890,7 @@ int lua_setmetatable(lua_State* L, int objindex)
|
|||||||
case LUA_TTABLE:
|
case LUA_TTABLE:
|
||||||
{
|
{
|
||||||
if (hvalue(obj)->readonly)
|
if (hvalue(obj)->readonly)
|
||||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
luaG_readonlyerror(L);
|
||||||
hvalue(obj)->metatable = mt;
|
hvalue(obj)->metatable = mt;
|
||||||
if (mt)
|
if (mt)
|
||||||
luaC_objbarrier(L, hvalue(obj), mt);
|
luaC_objbarrier(L, hvalue(obj), mt);
|
||||||
|
@ -269,6 +269,11 @@ l_noret luaG_indexerror(lua_State* L, const TValue* p1, const TValue* p2)
|
|||||||
luaG_runerror(L, "attempt to index %s with %s", t1, t2);
|
luaG_runerror(L, "attempt to index %s with %s", t1, t2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
l_noret luaG_readonlyerror(lua_State* L)
|
||||||
|
{
|
||||||
|
luaG_runerror(L, "attempt to modify a readonly table");
|
||||||
|
}
|
||||||
|
|
||||||
static void pusherror(lua_State* L, const char* msg)
|
static void pusherror(lua_State* L, const char* msg)
|
||||||
{
|
{
|
||||||
CallInfo* ci = L->ci;
|
CallInfo* ci = L->ci;
|
||||||
|
@ -19,6 +19,7 @@ LUAI_FUNC l_noret luaG_concaterror(lua_State* L, StkId p1, StkId p2);
|
|||||||
LUAI_FUNC l_noret luaG_aritherror(lua_State* L, const TValue* p1, const TValue* p2, TMS op);
|
LUAI_FUNC l_noret luaG_aritherror(lua_State* L, const TValue* p1, const TValue* p2, TMS op);
|
||||||
LUAI_FUNC l_noret luaG_ordererror(lua_State* L, const TValue* p1, const TValue* p2, TMS op);
|
LUAI_FUNC l_noret luaG_ordererror(lua_State* L, const TValue* p1, const TValue* p2, TMS op);
|
||||||
LUAI_FUNC l_noret luaG_indexerror(lua_State* L, const TValue* p1, const TValue* p2);
|
LUAI_FUNC l_noret luaG_indexerror(lua_State* L, const TValue* p1, const TValue* p2);
|
||||||
|
LUAI_FUNC l_noret luaG_readonlyerror(lua_State* L);
|
||||||
|
|
||||||
LUAI_FUNC LUA_PRINTF_ATTR(2, 3) l_noret luaG_runerrorL(lua_State* L, const char* fmt, ...);
|
LUAI_FUNC LUA_PRINTF_ATTR(2, 3) l_noret luaG_runerrorL(lua_State* L, const char* fmt, ...);
|
||||||
LUAI_FUNC void luaG_pusherror(lua_State* L, const char* error);
|
LUAI_FUNC void luaG_pusherror(lua_State* L, const char* error);
|
||||||
|
@ -79,7 +79,7 @@ static void moveelements(lua_State* L, int srct, int dstt, int f, int e, int t)
|
|||||||
Table* dst = hvalue(L->base + (dstt - 1));
|
Table* dst = hvalue(L->base + (dstt - 1));
|
||||||
|
|
||||||
if (dst->readonly)
|
if (dst->readonly)
|
||||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
luaG_readonlyerror(L);
|
||||||
|
|
||||||
int n = e - f + 1; /* number of elements to move */
|
int n = e - f + 1; /* number of elements to move */
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ static int tmove(lua_State* L)
|
|||||||
Table* dst = hvalue(L->base + (tt - 1));
|
Table* dst = hvalue(L->base + (tt - 1));
|
||||||
|
|
||||||
if (dst->readonly) /* also checked in moveelements, but this blocks resizes of r/o tables */
|
if (dst->readonly) /* also checked in moveelements, but this blocks resizes of r/o tables */
|
||||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
luaG_readonlyerror(L);
|
||||||
|
|
||||||
if (t > 0 && (t - 1) <= dst->sizearray && (t - 1 + n) > dst->sizearray)
|
if (t > 0 && (t - 1) <= dst->sizearray && (t - 1 + n) > dst->sizearray)
|
||||||
{ /* grow the destination table array */
|
{ /* grow the destination table array */
|
||||||
@ -482,7 +482,7 @@ static int tclear(lua_State* L)
|
|||||||
|
|
||||||
Table* tt = hvalue(L->base);
|
Table* tt = hvalue(L->base);
|
||||||
if (tt->readonly)
|
if (tt->readonly)
|
||||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
luaG_readonlyerror(L);
|
||||||
|
|
||||||
luaH_clear(tt);
|
luaH_clear(tt);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -128,7 +128,7 @@ void luaV_gettable(lua_State* L, const TValue* t, TValue* key, StkId val)
|
|||||||
}
|
}
|
||||||
t = tm; /* else repeat with `tm' */
|
t = tm; /* else repeat with `tm' */
|
||||||
}
|
}
|
||||||
luaG_runerror(L, "loop in gettable");
|
luaG_runerror(L, "'__index' chain too long; possible loop");
|
||||||
}
|
}
|
||||||
|
|
||||||
void luaV_settable(lua_State* L, const TValue* t, TValue* key, StkId val)
|
void luaV_settable(lua_State* L, const TValue* t, TValue* key, StkId val)
|
||||||
@ -143,7 +143,7 @@ void luaV_settable(lua_State* L, const TValue* t, TValue* key, StkId val)
|
|||||||
Table* h = hvalue(t);
|
Table* h = hvalue(t);
|
||||||
|
|
||||||
if (h->readonly)
|
if (h->readonly)
|
||||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
luaG_readonlyerror(L);
|
||||||
|
|
||||||
TValue* oldval = luaH_set(L, h, key); /* do a primitive set */
|
TValue* oldval = luaH_set(L, h, key); /* do a primitive set */
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ void luaV_settable(lua_State* L, const TValue* t, TValue* key, StkId val)
|
|||||||
setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */
|
setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */
|
||||||
t = &temp;
|
t = &temp;
|
||||||
}
|
}
|
||||||
luaG_runerror(L, "loop in settable");
|
luaG_runerror(L, "'__newindex' chain too long; possible loop");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int call_binTM(lua_State* L, const TValue* p1, const TValue* p2, StkId res, TMS event)
|
static int call_binTM(lua_State* L, const TValue* p1, const TValue* p2, StkId res, TMS event)
|
||||||
|
@ -139,7 +139,7 @@ function test()
|
|||||||
for _, curr_qdr in pairs(negaMax.index_quadruplets) do -- iterate over all index quadruplets
|
for _, curr_qdr in pairs(negaMax.index_quadruplets) do -- iterate over all index quadruplets
|
||||||
-- count the empty positions and positions occupied by the side whos move it is
|
-- count the empty positions and positions occupied by the side whos move it is
|
||||||
local player_plus_fields, player_minus_fields, empties = 0, 0, 0
|
local player_plus_fields, player_minus_fields, empties = 0, 0, 0
|
||||||
for _, index in pairs(curr_qdr) do -- iterate over all indices
|
for _, index in next, curr_qdr do -- iterate over all indices
|
||||||
if board[index] == 0 then
|
if board[index] == 0 then
|
||||||
empties = empties + 1
|
empties = empties + 1
|
||||||
elseif board[index] == 1 then
|
elseif board[index] == 1 then
|
||||||
|
@ -333,7 +333,7 @@ DEFINE_PROTO_FUZZER(const luau::ModuleSet& message)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Luau::BytecodeBuilder bcb;
|
Luau::BytecodeBuilder bcb;
|
||||||
Luau::compileOrThrow(bcb, parseResult.root, parseNameTable, compileOptions);
|
Luau::compileOrThrow(bcb, parseResult, parseNameTable, compileOptions);
|
||||||
bytecode = bcb.getBytecode();
|
bytecode = bcb.getBytecode();
|
||||||
}
|
}
|
||||||
catch (const Luau::CompileError&)
|
catch (const Luau::CompileError&)
|
||||||
|
@ -155,6 +155,13 @@ TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "BaseBinaryInstructionForms")
|
|||||||
SINGLE_COMPARE(add(qword[rax + r13 * 2 + 0x1b], rsi), 0x4a, 0x01, 0x74, 0x68, 0x1b);
|
SINGLE_COMPARE(add(qword[rax + r13 * 2 + 0x1b], rsi), 0x4a, 0x01, 0x74, 0x68, 0x1b);
|
||||||
SINGLE_COMPARE(add(qword[rbp + rbx * 2], rsi), 0x48, 0x01, 0x74, 0x5d, 0x00);
|
SINGLE_COMPARE(add(qword[rbp + rbx * 2], rsi), 0x48, 0x01, 0x74, 0x5d, 0x00);
|
||||||
SINGLE_COMPARE(add(qword[rsp + r10 * 2 + 0x1b], r10), 0x4e, 0x01, 0x54, 0x54, 0x1b);
|
SINGLE_COMPARE(add(qword[rsp + r10 * 2 + 0x1b], r10), 0x4e, 0x01, 0x54, 0x54, 0x1b);
|
||||||
|
|
||||||
|
// [addr], imm
|
||||||
|
SINGLE_COMPARE(add(byte[rax], 2), 0x80, 0x00, 0x02);
|
||||||
|
SINGLE_COMPARE(add(dword[rax], 2), 0x83, 0x00, 0x02);
|
||||||
|
SINGLE_COMPARE(add(dword[rax], 0xabcd), 0x81, 0x00, 0xcd, 0xab, 0x00, 0x00);
|
||||||
|
SINGLE_COMPARE(add(qword[rax], 2), 0x48, 0x83, 0x00, 0x02);
|
||||||
|
SINGLE_COMPARE(add(qword[rax], 0xabcd), 0x48, 0x81, 0x00, 0xcd, 0xab, 0x00, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "BaseUnaryInstructionForms")
|
TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "BaseUnaryInstructionForms")
|
||||||
@ -304,6 +311,13 @@ TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "AVXBinaryInstructionForms")
|
|||||||
SINGLE_COMPARE(vaddps(xmm9, xmm12, xmmword[r9 + r14 * 2 + 0x1c]), 0xc4, 0x01, 0x98, 0x58, 0x4c, 0x71, 0x1c);
|
SINGLE_COMPARE(vaddps(xmm9, xmm12, xmmword[r9 + r14 * 2 + 0x1c]), 0xc4, 0x01, 0x98, 0x58, 0x4c, 0x71, 0x1c);
|
||||||
SINGLE_COMPARE(vaddps(ymm1, ymm2, ymm3), 0xc4, 0xe1, 0xec, 0x58, 0xcb);
|
SINGLE_COMPARE(vaddps(ymm1, ymm2, ymm3), 0xc4, 0xe1, 0xec, 0x58, 0xcb);
|
||||||
SINGLE_COMPARE(vaddps(ymm9, ymm12, ymmword[r9 + r14 * 2 + 0x1c]), 0xc4, 0x01, 0x9c, 0x58, 0x4c, 0x71, 0x1c);
|
SINGLE_COMPARE(vaddps(ymm9, ymm12, ymmword[r9 + r14 * 2 + 0x1c]), 0xc4, 0x01, 0x9c, 0x58, 0x4c, 0x71, 0x1c);
|
||||||
|
|
||||||
|
// Coverage for other instructions that follow the same pattern
|
||||||
|
SINGLE_COMPARE(vsubsd(xmm8, xmm10, xmm14), 0xc4, 0x41, 0xab, 0x5c, 0xc6);
|
||||||
|
SINGLE_COMPARE(vmulsd(xmm8, xmm10, xmm14), 0xc4, 0x41, 0xab, 0x59, 0xc6);
|
||||||
|
SINGLE_COMPARE(vdivsd(xmm8, xmm10, xmm14), 0xc4, 0x41, 0xab, 0x5e, 0xc6);
|
||||||
|
|
||||||
|
SINGLE_COMPARE(vxorpd(xmm8, xmm10, xmm14), 0xc4, 0x41, 0xa9, 0x57, 0xc6);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "AVXUnaryMergeInstructionForms")
|
TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "AVXUnaryMergeInstructionForms")
|
||||||
@ -318,6 +332,9 @@ TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "AVXUnaryMergeInstructionForms")
|
|||||||
SINGLE_COMPARE(vsqrtsd(xmm8, xmm10, qword[r9]), 0xc4, 0x41, 0xab, 0x51, 0x01);
|
SINGLE_COMPARE(vsqrtsd(xmm8, xmm10, qword[r9]), 0xc4, 0x41, 0xab, 0x51, 0x01);
|
||||||
SINGLE_COMPARE(vsqrtss(xmm8, xmm10, xmm14), 0xc4, 0x41, 0xaa, 0x51, 0xc6);
|
SINGLE_COMPARE(vsqrtss(xmm8, xmm10, xmm14), 0xc4, 0x41, 0xaa, 0x51, 0xc6);
|
||||||
SINGLE_COMPARE(vsqrtss(xmm8, xmm10, dword[r9]), 0xc4, 0x41, 0xaa, 0x51, 0x01);
|
SINGLE_COMPARE(vsqrtss(xmm8, xmm10, dword[r9]), 0xc4, 0x41, 0xaa, 0x51, 0x01);
|
||||||
|
|
||||||
|
// Coverage for other instructions that follow the same pattern
|
||||||
|
SINGLE_COMPARE(vcomisd(xmm8, xmm10), 0xc4, 0x41, 0xf9, 0x2f, 0xc2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "AVXMoveInstructionForms")
|
TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "AVXMoveInstructionForms")
|
||||||
@ -342,6 +359,11 @@ TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "AVXMoveInstructionForms")
|
|||||||
SINGLE_COMPARE(vmovups(ymm8, ymmword[r9]), 0xc4, 0x41, 0xfc, 0x10, 0x01);
|
SINGLE_COMPARE(vmovups(ymm8, ymmword[r9]), 0xc4, 0x41, 0xfc, 0x10, 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "MiscInstructions")
|
||||||
|
{
|
||||||
|
SINGLE_COMPARE(int3(), 0xcc);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("LogTest")
|
TEST_CASE("LogTest")
|
||||||
{
|
{
|
||||||
AssemblyBuilderX64 build(/* logText= */ true);
|
AssemblyBuilderX64 build(/* logText= */ true);
|
||||||
@ -366,6 +388,7 @@ TEST_CASE("LogTest")
|
|||||||
build.vmovapd(xmmword[rax], xmm11);
|
build.vmovapd(xmmword[rax], xmm11);
|
||||||
build.pop(r12);
|
build.pop(r12);
|
||||||
build.ret();
|
build.ret();
|
||||||
|
build.int3();
|
||||||
|
|
||||||
build.finalize();
|
build.finalize();
|
||||||
|
|
||||||
@ -388,6 +411,7 @@ TEST_CASE("LogTest")
|
|||||||
vmovapd xmmword ptr [rax],xmm11
|
vmovapd xmmword ptr [rax],xmm11
|
||||||
pop r12
|
pop r12
|
||||||
ret
|
ret
|
||||||
|
int3
|
||||||
)";
|
)";
|
||||||
CHECK(same);
|
CHECK(same);
|
||||||
}
|
}
|
||||||
|
@ -3793,6 +3793,8 @@ RETURN R0 1
|
|||||||
|
|
||||||
TEST_CASE("SharedClosure")
|
TEST_CASE("SharedClosure")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag sff("LuauCompileFreeReassign", true);
|
||||||
|
|
||||||
// closures can be shared even if functions refer to upvalues, as long as upvalues are top-level
|
// closures can be shared even if functions refer to upvalues, as long as upvalues are top-level
|
||||||
CHECK_EQ("\n" + compileFunction(R"(
|
CHECK_EQ("\n" + compileFunction(R"(
|
||||||
local val = ...
|
local val = ...
|
||||||
@ -3940,11 +3942,10 @@ LOADN R2 1
|
|||||||
LOADN R0 10
|
LOADN R0 10
|
||||||
LOADN R1 1
|
LOADN R1 1
|
||||||
FORNPREP R0 L5
|
FORNPREP R0 L5
|
||||||
L4: MOVE R3 R2
|
L4: GETIMPORT R3 1
|
||||||
GETIMPORT R4 1
|
NEWCLOSURE R4 P2
|
||||||
NEWCLOSURE R5 P2
|
CAPTURE VAL R2
|
||||||
CAPTURE VAL R3
|
CALL R3 1 0
|
||||||
CALL R4 1 0
|
|
||||||
FORNLOOP R0 L4
|
FORNLOOP R0 L4
|
||||||
L5: RETURN R0 0
|
L5: RETURN R0 0
|
||||||
)");
|
)");
|
||||||
@ -6157,4 +6158,88 @@ RETURN R0 1
|
|||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("LocalReassign")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff("LuauCompileFreeReassign", true);
|
||||||
|
|
||||||
|
// locals can be re-assigned and the register gets reused
|
||||||
|
CHECK_EQ("\n" + compileFunction0(R"(
|
||||||
|
local function test(a, b)
|
||||||
|
local c = a
|
||||||
|
return c + b
|
||||||
|
end
|
||||||
|
)"), R"(
|
||||||
|
ADD R2 R0 R1
|
||||||
|
RETURN R2 1
|
||||||
|
)");
|
||||||
|
|
||||||
|
// this works if the expression is using type casts or grouping
|
||||||
|
CHECK_EQ("\n" + compileFunction0(R"(
|
||||||
|
local function test(a, b)
|
||||||
|
local c = (a :: number)
|
||||||
|
return c + b
|
||||||
|
end
|
||||||
|
)"), R"(
|
||||||
|
ADD R2 R0 R1
|
||||||
|
RETURN R2 1
|
||||||
|
)");
|
||||||
|
|
||||||
|
// the optimization requires that neither local is mutated
|
||||||
|
CHECK_EQ("\n" + compileFunction0(R"(
|
||||||
|
local function test(a, b)
|
||||||
|
local c = a
|
||||||
|
c += 0
|
||||||
|
local d = b
|
||||||
|
b += 0
|
||||||
|
return c + d
|
||||||
|
end
|
||||||
|
)"), R"(
|
||||||
|
MOVE R2 R0
|
||||||
|
ADDK R2 R2 K0
|
||||||
|
MOVE R3 R1
|
||||||
|
ADDK R1 R1 K0
|
||||||
|
ADD R4 R2 R3
|
||||||
|
RETURN R4 1
|
||||||
|
)");
|
||||||
|
|
||||||
|
// sanity check for two values
|
||||||
|
CHECK_EQ("\n" + compileFunction0(R"(
|
||||||
|
local function test(a, b)
|
||||||
|
local c = a
|
||||||
|
local d = b
|
||||||
|
return c + d
|
||||||
|
end
|
||||||
|
)"), R"(
|
||||||
|
ADD R2 R0 R1
|
||||||
|
RETURN R2 1
|
||||||
|
)");
|
||||||
|
|
||||||
|
// note: we currently only support this for single assignments
|
||||||
|
CHECK_EQ("\n" + compileFunction0(R"(
|
||||||
|
local function test(a, b)
|
||||||
|
local c, d = a, b
|
||||||
|
return c + d
|
||||||
|
end
|
||||||
|
)"), R"(
|
||||||
|
MOVE R2 R0
|
||||||
|
MOVE R3 R1
|
||||||
|
ADD R4 R2 R3
|
||||||
|
RETURN R4 1
|
||||||
|
)");
|
||||||
|
|
||||||
|
// of course, captures capture the original register as well (by value since it's immutable)
|
||||||
|
CHECK_EQ("\n" + compileFunction(R"(
|
||||||
|
local function test(a, b)
|
||||||
|
local c = a
|
||||||
|
local d = b
|
||||||
|
return function() return c + d end
|
||||||
|
end
|
||||||
|
)", 1), R"(
|
||||||
|
NEWCLOSURE R2 P0
|
||||||
|
CAPTURE VAL R0
|
||||||
|
CAPTURE VAL R1
|
||||||
|
RETURN R2 1
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_SUITE_END();
|
TEST_SUITE_END();
|
||||||
|
@ -254,9 +254,9 @@ TEST_CASE("Math")
|
|||||||
runConformance("math.lua");
|
runConformance("math.lua");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Table")
|
TEST_CASE("Tables")
|
||||||
{
|
{
|
||||||
runConformance("nextvar.lua", [](lua_State* L) {
|
runConformance("tables.lua", [](lua_State* L) {
|
||||||
lua_pushcfunction(
|
lua_pushcfunction(
|
||||||
L,
|
L,
|
||||||
[](lua_State* L) {
|
[](lua_State* L) {
|
||||||
|
@ -1025,4 +1025,73 @@ TEST_CASE("check_without_builtin_next")
|
|||||||
frontend.check("Module/B");
|
frontend.check("Module/B");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(BuiltinsFixture, "reexport_cyclic_type")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff[] = {
|
||||||
|
{"LuauForceExportSurfacesToBeNormal", true},
|
||||||
|
{"LuauLowerBoundsCalculation", true},
|
||||||
|
{"LuauNormalizeFlagIsConservative", true},
|
||||||
|
};
|
||||||
|
|
||||||
|
fileResolver.source["Module/A"] = R"(
|
||||||
|
type F<T> = (set: G<T>) -> ()
|
||||||
|
|
||||||
|
export type G<T> = {
|
||||||
|
forEach: (a: F<T>) -> (),
|
||||||
|
}
|
||||||
|
|
||||||
|
function X<T>(a: F<T>): ()
|
||||||
|
end
|
||||||
|
|
||||||
|
return X
|
||||||
|
)";
|
||||||
|
|
||||||
|
fileResolver.source["Module/B"] = R"(
|
||||||
|
--!strict
|
||||||
|
local A = require(script.Parent.A)
|
||||||
|
|
||||||
|
export type G<T> = A.G<T>
|
||||||
|
|
||||||
|
return {
|
||||||
|
A = A,
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
CheckResult result = frontend.check("Module/B");
|
||||||
|
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(BuiltinsFixture, "reexport_type_alias")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff[] = {
|
||||||
|
{"LuauForceExportSurfacesToBeNormal", true},
|
||||||
|
{"LuauLowerBoundsCalculation", true},
|
||||||
|
{"LuauNormalizeFlagIsConservative", true},
|
||||||
|
};
|
||||||
|
|
||||||
|
fileResolver.source["Module/A"] = R"(
|
||||||
|
type KeyOfTestEvents = "test-file-start" | "test-file-success" | "test-file-failure" | "test-case-result"
|
||||||
|
type unknown = any
|
||||||
|
|
||||||
|
export type TestFileEvent<T = KeyOfTestEvents> = (
|
||||||
|
eventName: T,
|
||||||
|
args: any --[[ ROBLOX TODO: Unhandled node for type: TSIndexedAccessType ]] --[[ TestEvents[T] ]]
|
||||||
|
) -> unknown
|
||||||
|
|
||||||
|
return {}
|
||||||
|
)";
|
||||||
|
|
||||||
|
fileResolver.source["Module/B"] = R"(
|
||||||
|
--!strict
|
||||||
|
local A = require(script.Parent.A)
|
||||||
|
|
||||||
|
export type TestFileEvent = A.TestFileEvent
|
||||||
|
)";
|
||||||
|
|
||||||
|
CheckResult result = frontend.check("Module/B");
|
||||||
|
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_SUITE_END();
|
TEST_SUITE_END();
|
||||||
|
@ -56,10 +56,19 @@ TEST_CASE("encode_constants")
|
|||||||
AstExprConstantNil nil{Location()};
|
AstExprConstantNil nil{Location()};
|
||||||
AstExprConstantBool b{Location(), true};
|
AstExprConstantBool b{Location(), true};
|
||||||
AstExprConstantNumber n{Location(), 8.2};
|
AstExprConstantNumber n{Location(), 8.2};
|
||||||
|
AstExprConstantNumber bigNum{Location(), 0.1677721600000003};
|
||||||
|
|
||||||
|
AstArray<char> charString;
|
||||||
|
charString.data = const_cast<char*>("a\x1d\0\\\"b");
|
||||||
|
charString.size = 6;
|
||||||
|
|
||||||
|
AstExprConstantString needsEscaping{Location(), charString};
|
||||||
|
|
||||||
CHECK_EQ(R"({"type":"AstExprConstantNil","location":"0,0 - 0,0"})", toJson(&nil));
|
CHECK_EQ(R"({"type":"AstExprConstantNil","location":"0,0 - 0,0"})", toJson(&nil));
|
||||||
CHECK_EQ(R"({"type":"AstExprConstantBool","location":"0,0 - 0,0","value":true})", toJson(&b));
|
CHECK_EQ(R"({"type":"AstExprConstantBool","location":"0,0 - 0,0","value":true})", toJson(&b));
|
||||||
CHECK_EQ(R"({"type":"AstExprConstantNumber","location":"0,0 - 0,0","value":8.2})", toJson(&n));
|
CHECK_EQ(R"({"type":"AstExprConstantNumber","location":"0,0 - 0,0","value":8.1999999999999993})", toJson(&n));
|
||||||
|
CHECK_EQ(R"({"type":"AstExprConstantNumber","location":"0,0 - 0,0","value":0.16777216000000031})", toJson(&bigNum));
|
||||||
|
CHECK_EQ("{\"type\":\"AstExprConstantString\",\"location\":\"0,0 - 0,0\",\"value\":\"a\\u001d\\u0000\\\\\\\"b\"}", toJson(&needsEscaping));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("basic_escaping")
|
TEST_CASE("basic_escaping")
|
||||||
@ -87,7 +96,7 @@ TEST_CASE("encode_AstStatBlock")
|
|||||||
AstStatBlock block{Location(), bodyArray};
|
AstStatBlock block{Location(), bodyArray};
|
||||||
|
|
||||||
CHECK_EQ(
|
CHECK_EQ(
|
||||||
(R"({"type":"AstStatBlock","location":"0,0 - 0,0","body":[{"type":"AstStatLocal","location":"0,0 - 0,0","vars":[{"type":null,"name":"a_local","location":"0,0 - 0,0"}],"values":[]}]})"),
|
(R"({"type":"AstStatBlock","location":"0,0 - 0,0","body":[{"type":"AstStatLocal","location":"0,0 - 0,0","vars":[{"luauType":null,"name":"a_local","type":"AstLocal","location":"0,0 - 0,0"}],"values":[]}]})"),
|
||||||
toJson(&block));
|
toJson(&block));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +115,31 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_tables")
|
|||||||
|
|
||||||
CHECK(
|
CHECK(
|
||||||
json ==
|
json ==
|
||||||
R"({"type":"AstStatBlock","location":"0,0 - 6,4","body":[{"type":"AstStatLocal","location":"1,8 - 5,9","vars":[{"type":{"type":"AstTypeTable","location":"1,17 - 3,9","props":[{"name":"foo","location":"2,12 - 2,15","type":{"type":"AstTypeReference","location":"2,17 - 2,23","name":"number","parameters":[]}}],"indexer":false},"name":"x","location":"1,14 - 1,15"}],"values":[{"type":"AstExprTable","location":"3,12 - 5,9","items":[{"kind":"record","key":{"type":"AstExprConstantString","location":"4,12 - 4,15","value":"foo"},"value":{"type":"AstExprConstantNumber","location":"4,18 - 4,21","value":123}}]}]}]})");
|
R"({"type":"AstStatBlock","location":"0,0 - 6,4","body":[{"type":"AstStatLocal","location":"1,8 - 5,9","vars":[{"luauType":{"type":"AstTypeTable","location":"1,17 - 3,9","props":[{"name":"foo","type":"AstTableProp","location":"2,12 - 2,15","propType":{"type":"AstTypeReference","location":"2,17 - 2,23","name":"number","parameters":[]}}],"indexer":null},"name":"x","type":"AstLocal","location":"1,14 - 1,15"}],"values":[{"type":"AstExprTable","location":"3,12 - 5,9","items":[{"type":"AstExprTableItem","kind":"record","key":{"type":"AstExprConstantString","location":"4,12 - 4,15","value":"foo"},"value":{"type":"AstExprConstantNumber","location":"4,18 - 4,21","value":123}}]}]}]})");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_table_array")
|
||||||
|
{
|
||||||
|
std::string src = R"(type X = {string})";
|
||||||
|
|
||||||
|
AstStatBlock* root = expectParse(src);
|
||||||
|
std::string json = toJson(root);
|
||||||
|
|
||||||
|
CHECK(
|
||||||
|
json ==
|
||||||
|
R"({"type":"AstStatBlock","location":"0,0 - 0,17","body":[{"type":"AstStatTypeAlias","location":"0,0 - 0,17","name":"X","generics":[],"genericPacks":[],"type":{"type":"AstTypeTable","location":"0,9 - 0,17","props":[],"indexer":{"location":"0,10 - 0,16","indexType":{"type":"AstTypeReference","location":"0,10 - 0,16","name":"number","parameters":[]},"resultType":{"type":"AstTypeReference","location":"0,10 - 0,16","name":"string","parameters":[]}}},"exported":false}]})");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_table_indexer")
|
||||||
|
{
|
||||||
|
std::string src = R"(type X = {string})";
|
||||||
|
|
||||||
|
AstStatBlock* root = expectParse(src);
|
||||||
|
std::string json = toJson(root);
|
||||||
|
|
||||||
|
CHECK(
|
||||||
|
json ==
|
||||||
|
R"({"type":"AstStatBlock","location":"0,0 - 0,17","body":[{"type":"AstStatTypeAlias","location":"0,0 - 0,17","name":"X","generics":[],"genericPacks":[],"type":{"type":"AstTypeTable","location":"0,9 - 0,17","props":[],"indexer":{"location":"0,10 - 0,16","indexType":{"type":"AstTypeReference","location":"0,10 - 0,16","name":"number","parameters":[]},"resultType":{"type":"AstTypeReference","location":"0,10 - 0,16","name":"string","parameters":[]}}},"exported":false}]})");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("encode_AstExprGroup")
|
TEST_CASE("encode_AstExprGroup")
|
||||||
@ -132,12 +165,23 @@ TEST_CASE("encode_AstExprGlobal")
|
|||||||
CHECK(json == expected);
|
CHECK(json == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstExprIfThen")
|
||||||
|
{
|
||||||
|
AstStat* statement = expectParseStatement("local a = if x then y else z");
|
||||||
|
|
||||||
|
std::string_view expected =
|
||||||
|
R"({"type":"AstStatLocal","location":"0,0 - 0,28","vars":[{"luauType":null,"name":"a","type":"AstLocal","location":"0,6 - 0,7"}],"values":[{"type":"AstExprIfElse","location":"0,10 - 0,28","condition":{"type":"AstExprGlobal","location":"0,13 - 0,14","global":"x"},"hasThen":true,"trueExpr":{"type":"AstExprGlobal","location":"0,20 - 0,21","global":"y"},"hasElse":true,"falseExpr":{"type":"AstExprGlobal","location":"0,27 - 0,28","global":"z"}}]})";
|
||||||
|
|
||||||
|
CHECK(toJson(statement) == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("encode_AstExprLocal")
|
TEST_CASE("encode_AstExprLocal")
|
||||||
{
|
{
|
||||||
AstLocal local{AstName{"foo"}, Location{}, nullptr, 0, 0, nullptr};
|
AstLocal local{AstName{"foo"}, Location{}, nullptr, 0, 0, nullptr};
|
||||||
AstExprLocal exprLocal{Location{}, &local, false};
|
AstExprLocal exprLocal{Location{}, &local, false};
|
||||||
|
|
||||||
CHECK(toJson(&exprLocal) == R"({"type":"AstExprLocal","location":"0,0 - 0,0","local":{"type":null,"name":"foo","location":"0,0 - 0,0"}})");
|
CHECK(toJson(&exprLocal) == R"({"type":"AstExprLocal","location":"0,0 - 0,0","local":{"luauType":null,"name":"foo","type":"AstLocal","location":"0,0 - 0,0"}})");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("encode_AstExprVarargs")
|
TEST_CASE("encode_AstExprVarargs")
|
||||||
@ -181,7 +225,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstExprFunction")
|
|||||||
AstExpr* expr = expectParseExpr("function (a) return a end");
|
AstExpr* expr = expectParseExpr("function (a) return a end");
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AstExprFunction","location":"0,4 - 0,29","generics":[],"genericPacks":[],"args":[{"type":null,"name":"a","location":"0,14 - 0,15"}],"vararg":false,"varargLocation":"0,0 - 0,0","body":{"type":"AstStatBlock","location":"0,16 - 0,26","body":[{"type":"AstStatReturn","location":"0,17 - 0,25","list":[{"type":"AstExprLocal","location":"0,24 - 0,25","local":{"type":null,"name":"a","location":"0,14 - 0,15"}}]}]},"functionDepth":1,"debugname":"","hasEnd":true})";
|
R"({"type":"AstExprFunction","location":"0,4 - 0,29","generics":[],"genericPacks":[],"args":[{"luauType":null,"name":"a","type":"AstLocal","location":"0,14 - 0,15"}],"vararg":false,"varargLocation":"0,0 - 0,0","body":{"type":"AstStatBlock","location":"0,16 - 0,26","body":[{"type":"AstStatReturn","location":"0,17 - 0,25","list":[{"type":"AstExprLocal","location":"0,24 - 0,25","local":{"luauType":null,"name":"a","type":"AstLocal","location":"0,14 - 0,15"}}]}]},"functionDepth":1,"debugname":"","hasEnd":true})";
|
||||||
|
|
||||||
CHECK(toJson(expr) == expected);
|
CHECK(toJson(expr) == expected);
|
||||||
}
|
}
|
||||||
@ -191,7 +235,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstExprTable")
|
|||||||
AstExpr* expr = expectParseExpr("{true, key=true, [key2]=true}");
|
AstExpr* expr = expectParseExpr("{true, key=true, [key2]=true}");
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AstExprTable","location":"0,4 - 0,33","items":[{"kind":"item","value":{"type":"AstExprConstantBool","location":"0,5 - 0,9","value":true}},{"kind":"record","key":{"type":"AstExprConstantString","location":"0,11 - 0,14","value":"key"},"value":{"type":"AstExprConstantBool","location":"0,15 - 0,19","value":true}},{"kind":"general","key":{"type":"AstExprGlobal","location":"0,22 - 0,26","global":"key2"},"value":{"type":"AstExprConstantBool","location":"0,28 - 0,32","value":true}}]})";
|
R"({"type":"AstExprTable","location":"0,4 - 0,33","items":[{"type":"AstExprTableItem","kind":"item","value":{"type":"AstExprConstantBool","location":"0,5 - 0,9","value":true}},{"type":"AstExprTableItem","kind":"record","key":{"type":"AstExprConstantString","location":"0,11 - 0,14","value":"key"},"value":{"type":"AstExprConstantBool","location":"0,15 - 0,19","value":true}},{"type":"AstExprTableItem","kind":"general","key":{"type":"AstExprGlobal","location":"0,22 - 0,26","global":"key2"},"value":{"type":"AstExprConstantBool","location":"0,28 - 0,32","value":true}}]})";
|
||||||
|
|
||||||
CHECK(toJson(expr) == expected);
|
CHECK(toJson(expr) == expected);
|
||||||
}
|
}
|
||||||
@ -201,7 +245,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstExprUnary")
|
|||||||
AstExpr* expr = expectParseExpr("-b");
|
AstExpr* expr = expectParseExpr("-b");
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AstExprUnary","location":"0,4 - 0,6","op":"minus","expr":{"type":"AstExprGlobal","location":"0,5 - 0,6","global":"b"}})";
|
R"({"type":"AstExprUnary","location":"0,4 - 0,6","op":"Minus","expr":{"type":"AstExprGlobal","location":"0,5 - 0,6","global":"b"}})";
|
||||||
|
|
||||||
CHECK(toJson(expr) == expected);
|
CHECK(toJson(expr) == expected);
|
||||||
}
|
}
|
||||||
@ -259,7 +303,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstStatWhile")
|
|||||||
AstStat* statement = expectParseStatement("while true do end");
|
AstStat* statement = expectParseStatement("while true do end");
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AtStatWhile","location":"0,0 - 0,17","condition":{"type":"AstExprConstantBool","location":"0,6 - 0,10","value":true},"body":{"type":"AstStatBlock","location":"0,13 - 0,14","body":[]},"hasDo":true,"hasEnd":true})";
|
R"({"type":"AstStatWhile","location":"0,0 - 0,17","condition":{"type":"AstExprConstantBool","location":"0,6 - 0,10","value":true},"body":{"type":"AstStatBlock","location":"0,13 - 0,14","body":[]},"hasDo":true,"hasEnd":true})";
|
||||||
|
|
||||||
CHECK(toJson(statement) == expected);
|
CHECK(toJson(statement) == expected);
|
||||||
}
|
}
|
||||||
@ -279,7 +323,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstStatBreak")
|
|||||||
AstStat* statement = expectParseStatement("while true do break end");
|
AstStat* statement = expectParseStatement("while true do break end");
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AtStatWhile","location":"0,0 - 0,23","condition":{"type":"AstExprConstantBool","location":"0,6 - 0,10","value":true},"body":{"type":"AstStatBlock","location":"0,13 - 0,20","body":[{"type":"AstStatBreak","location":"0,14 - 0,19"}]},"hasDo":true,"hasEnd":true})";
|
R"({"type":"AstStatWhile","location":"0,0 - 0,23","condition":{"type":"AstExprConstantBool","location":"0,6 - 0,10","value":true},"body":{"type":"AstStatBlock","location":"0,13 - 0,20","body":[{"type":"AstStatBreak","location":"0,14 - 0,19"}]},"hasDo":true,"hasEnd":true})";
|
||||||
|
|
||||||
CHECK(toJson(statement) == expected);
|
CHECK(toJson(statement) == expected);
|
||||||
}
|
}
|
||||||
@ -289,7 +333,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstStatContinue")
|
|||||||
AstStat* statement = expectParseStatement("while true do continue end");
|
AstStat* statement = expectParseStatement("while true do continue end");
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AtStatWhile","location":"0,0 - 0,26","condition":{"type":"AstExprConstantBool","location":"0,6 - 0,10","value":true},"body":{"type":"AstStatBlock","location":"0,13 - 0,23","body":[{"type":"AstStatContinue","location":"0,14 - 0,22"}]},"hasDo":true,"hasEnd":true})";
|
R"({"type":"AstStatWhile","location":"0,0 - 0,26","condition":{"type":"AstExprConstantBool","location":"0,6 - 0,10","value":true},"body":{"type":"AstStatBlock","location":"0,13 - 0,23","body":[{"type":"AstStatContinue","location":"0,14 - 0,22"}]},"hasDo":true,"hasEnd":true})";
|
||||||
|
|
||||||
CHECK(toJson(statement) == expected);
|
CHECK(toJson(statement) == expected);
|
||||||
}
|
}
|
||||||
@ -299,7 +343,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstStatFor")
|
|||||||
AstStat* statement = expectParseStatement("for a=0,1 do end");
|
AstStat* statement = expectParseStatement("for a=0,1 do end");
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AstStatFor","location":"0,0 - 0,16","var":{"type":null,"name":"a","location":"0,4 - 0,5"},"from":{"type":"AstExprConstantNumber","location":"0,6 - 0,7","value":0},"to":{"type":"AstExprConstantNumber","location":"0,8 - 0,9","value":1},"body":{"type":"AstStatBlock","location":"0,12 - 0,13","body":[]},"hasDo":true,"hasEnd":true})";
|
R"({"type":"AstStatFor","location":"0,0 - 0,16","var":{"luauType":null,"name":"a","type":"AstLocal","location":"0,4 - 0,5"},"from":{"type":"AstExprConstantNumber","location":"0,6 - 0,7","value":0},"to":{"type":"AstExprConstantNumber","location":"0,8 - 0,9","value":1},"body":{"type":"AstStatBlock","location":"0,12 - 0,13","body":[]},"hasDo":true,"hasEnd":true})";
|
||||||
|
|
||||||
CHECK(toJson(statement) == expected);
|
CHECK(toJson(statement) == expected);
|
||||||
}
|
}
|
||||||
@ -309,7 +353,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstStatForIn")
|
|||||||
AstStat* statement = expectParseStatement("for a in b do end");
|
AstStat* statement = expectParseStatement("for a in b do end");
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AstStatForIn","location":"0,0 - 0,17","vars":[{"type":null,"name":"a","location":"0,4 - 0,5"}],"values":[{"type":"AstExprGlobal","location":"0,9 - 0,10","global":"b"}],"body":{"type":"AstStatBlock","location":"0,13 - 0,14","body":[]},"hasIn":true,"hasDo":true,"hasEnd":true})";
|
R"({"type":"AstStatForIn","location":"0,0 - 0,17","vars":[{"luauType":null,"name":"a","type":"AstLocal","location":"0,4 - 0,5"}],"values":[{"type":"AstExprGlobal","location":"0,9 - 0,10","global":"b"}],"body":{"type":"AstStatBlock","location":"0,13 - 0,14","body":[]},"hasIn":true,"hasDo":true,"hasEnd":true})";
|
||||||
|
|
||||||
CHECK(toJson(statement) == expected);
|
CHECK(toJson(statement) == expected);
|
||||||
}
|
}
|
||||||
@ -329,7 +373,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstStatLocalFunction")
|
|||||||
AstStat* statement = expectParseStatement("local function a(b) return end");
|
AstStat* statement = expectParseStatement("local function a(b) return end");
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AstStatLocalFunction","location":"0,0 - 0,30","name":{"type":null,"name":"a","location":"0,15 - 0,16"},"func":{"type":"AstExprFunction","location":"0,0 - 0,30","generics":[],"genericPacks":[],"args":[{"type":null,"name":"b","location":"0,17 - 0,18"}],"vararg":false,"varargLocation":"0,0 - 0,0","body":{"type":"AstStatBlock","location":"0,19 - 0,27","body":[{"type":"AstStatReturn","location":"0,20 - 0,26","list":[]}]},"functionDepth":1,"debugname":"a","hasEnd":true}})";
|
R"({"type":"AstStatLocalFunction","location":"0,0 - 0,30","name":{"luauType":null,"name":"a","type":"AstLocal","location":"0,15 - 0,16"},"func":{"type":"AstExprFunction","location":"0,0 - 0,30","generics":[],"genericPacks":[],"args":[{"luauType":null,"name":"b","type":"AstLocal","location":"0,17 - 0,18"}],"vararg":false,"varargLocation":"0,0 - 0,0","body":{"type":"AstStatBlock","location":"0,19 - 0,27","body":[{"type":"AstStatReturn","location":"0,20 - 0,26","list":[]}]},"functionDepth":1,"debugname":"a","hasEnd":true}})";
|
||||||
|
|
||||||
CHECK(toJson(statement) == expected);
|
CHECK(toJson(statement) == expected);
|
||||||
}
|
}
|
||||||
@ -349,7 +393,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstStatDeclareFunction")
|
|||||||
AstStat* statement = expectParseStatement("declare function foo(x: number): string");
|
AstStat* statement = expectParseStatement("declare function foo(x: number): string");
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AstStatDeclareFunction","location":"0,0 - 0,39","name":"foo","params":{"types":[{"type":"AstTypeReference","location":"0,24 - 0,30","name":"number","parameters":[]}]},"retTypes":{"types":[{"type":"AstTypeReference","location":"0,33 - 0,39","name":"string","parameters":[]}]},"generics":[],"genericPacks":[]})";
|
R"({"type":"AstStatDeclareFunction","location":"0,0 - 0,39","name":"foo","params":{"type":"AstTypeList","types":[{"type":"AstTypeReference","location":"0,24 - 0,30","name":"number","parameters":[]}]},"retTypes":{"type":"AstTypeList","types":[{"type":"AstTypeReference","location":"0,33 - 0,39","name":"string","parameters":[]}]},"generics":[],"genericPacks":[]})";
|
||||||
|
|
||||||
CHECK(toJson(statement) == expected);
|
CHECK(toJson(statement) == expected);
|
||||||
}
|
}
|
||||||
@ -370,11 +414,11 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstStatDeclareClass")
|
|||||||
REQUIRE(2 == root->body.size);
|
REQUIRE(2 == root->body.size);
|
||||||
|
|
||||||
std::string_view expected1 =
|
std::string_view expected1 =
|
||||||
R"({"type":"AstStatDeclareClass","location":"1,22 - 4,11","name":"Foo","props":[{"name":"prop","type":{"type":"AstTypeReference","location":"2,18 - 2,24","name":"number","parameters":[]}},{"name":"method","type":{"type":"AstTypeFunction","location":"3,21 - 4,11","generics":[],"genericPacks":[],"argTypes":{"types":[{"type":"AstTypeReference","location":"3,39 - 3,45","name":"number","parameters":[]}]},"returnTypes":{"types":[{"type":"AstTypeReference","location":"3,48 - 3,54","name":"string","parameters":[]}]}}}]})";
|
R"({"type":"AstStatDeclareClass","location":"1,22 - 4,11","name":"Foo","props":[{"name":"prop","type":"AstDeclaredClassProp","luauType":{"type":"AstTypeReference","location":"2,18 - 2,24","name":"number","parameters":[]}},{"name":"method","type":"AstDeclaredClassProp","luauType":{"type":"AstTypeFunction","location":"3,21 - 4,11","generics":[],"genericPacks":[],"argTypes":{"type":"AstTypeList","types":[{"type":"AstTypeReference","location":"3,39 - 3,45","name":"number","parameters":[]}]},"returnTypes":{"type":"AstTypeList","types":[{"type":"AstTypeReference","location":"3,48 - 3,54","name":"string","parameters":[]}]}}}]})";
|
||||||
CHECK(toJson(root->body.data[0]) == expected1);
|
CHECK(toJson(root->body.data[0]) == expected1);
|
||||||
|
|
||||||
std::string_view expected2 =
|
std::string_view expected2 =
|
||||||
R"({"type":"AstStatDeclareClass","location":"6,22 - 8,11","name":"Bar","superName":"Foo","props":[{"name":"prop2","type":{"type":"AstTypeReference","location":"7,19 - 7,25","name":"string","parameters":[]}}]})";
|
R"({"type":"AstStatDeclareClass","location":"6,22 - 8,11","name":"Bar","superName":"Foo","props":[{"name":"prop2","type":"AstDeclaredClassProp","luauType":{"type":"AstTypeReference","location":"7,19 - 7,25","name":"string","parameters":[]}}]})";
|
||||||
CHECK(toJson(root->body.data[1]) == expected2);
|
CHECK(toJson(root->body.data[1]) == expected2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +427,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_annotation")
|
|||||||
AstStat* statement = expectParseStatement("type T = ((number) -> (string | nil)) & ((string) -> ())");
|
AstStat* statement = expectParseStatement("type T = ((number) -> (string | nil)) & ((string) -> ())");
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AstStatTypeAlias","location":"0,0 - 0,55","name":"T","generics":[],"genericPacks":[],"type":{"type":"AstTypeIntersection","location":"0,9 - 0,55","types":[{"type":"AstTypeFunction","location":"0,10 - 0,35","generics":[],"genericPacks":[],"argTypes":{"types":[{"type":"AstTypeReference","location":"0,11 - 0,17","name":"number","parameters":[]}]},"returnTypes":{"types":[{"type":"AstTypeUnion","location":"0,23 - 0,35","types":[{"type":"AstTypeReference","location":"0,23 - 0,29","name":"string","parameters":[]},{"type":"AstTypeReference","location":"0,32 - 0,35","name":"nil","parameters":[]}]}]}},{"type":"AstTypeFunction","location":"0,41 - 0,55","generics":[],"genericPacks":[],"argTypes":{"types":[{"type":"AstTypeReference","location":"0,42 - 0,48","name":"string","parameters":[]}]},"returnTypes":{"types":[]}}]},"exported":false})";
|
R"({"type":"AstStatTypeAlias","location":"0,0 - 0,55","name":"T","generics":[],"genericPacks":[],"type":{"type":"AstTypeIntersection","location":"0,9 - 0,55","types":[{"type":"AstTypeFunction","location":"0,10 - 0,35","generics":[],"genericPacks":[],"argTypes":{"type":"AstTypeList","types":[{"type":"AstTypeReference","location":"0,11 - 0,17","name":"number","parameters":[]}]},"returnTypes":{"type":"AstTypeList","types":[{"type":"AstTypeUnion","location":"0,23 - 0,35","types":[{"type":"AstTypeReference","location":"0,23 - 0,29","name":"string","parameters":[]},{"type":"AstTypeReference","location":"0,32 - 0,35","name":"nil","parameters":[]}]}]}},{"type":"AstTypeFunction","location":"0,41 - 0,55","generics":[],"genericPacks":[],"argTypes":{"type":"AstTypeList","types":[{"type":"AstTypeReference","location":"0,42 - 0,48","name":"string","parameters":[]}]},"returnTypes":{"type":"AstTypeList","types":[]}}]},"exported":false})";
|
||||||
|
|
||||||
CHECK(toJson(statement) == expected);
|
CHECK(toJson(statement) == expected);
|
||||||
}
|
}
|
||||||
@ -411,7 +455,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstTypePackExplicit")
|
|||||||
CHECK(2 == root->body.size);
|
CHECK(2 == root->body.size);
|
||||||
|
|
||||||
std::string_view expected =
|
std::string_view expected =
|
||||||
R"({"type":"AstStatLocal","location":"2,8 - 2,36","vars":[{"type":{"type":"AstTypeReference","location":"2,17 - 2,36","name":"A","parameters":[{"type":"AstTypePackExplicit","location":"2,19 - 2,20","typeList":{"types":[{"type":"AstTypeReference","location":"2,20 - 2,26","name":"number","parameters":[]},{"type":"AstTypeReference","location":"2,28 - 2,34","name":"string","parameters":[]}]}}]},"name":"a","location":"2,14 - 2,15"}],"values":[]})";
|
R"({"type":"AstStatLocal","location":"2,8 - 2,36","vars":[{"luauType":{"type":"AstTypeReference","location":"2,17 - 2,36","name":"A","parameters":[{"type":"AstTypePackExplicit","location":"2,19 - 2,20","typeList":{"type":"AstTypeList","types":[{"type":"AstTypeReference","location":"2,20 - 2,26","name":"number","parameters":[]},{"type":"AstTypeReference","location":"2,28 - 2,34","name":"string","parameters":[]}]}}]},"name":"a","type":"AstLocal","location":"2,14 - 2,15"}],"values":[]})";
|
||||||
|
|
||||||
CHECK(toJson(root->body.data[1]) == expected);
|
CHECK(toJson(root->body.data[1]) == expected);
|
||||||
}
|
}
|
||||||
|
@ -13,77 +13,6 @@ using namespace Luau;
|
|||||||
|
|
||||||
TEST_SUITE_BEGIN("NonstrictModeTests");
|
TEST_SUITE_BEGIN("NonstrictModeTests");
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "globals")
|
|
||||||
{
|
|
||||||
CheckResult result = check(R"(
|
|
||||||
--!nonstrict
|
|
||||||
foo = true
|
|
||||||
foo = "now i'm a string!"
|
|
||||||
)");
|
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
|
||||||
CHECK_EQ("any", toString(requireType("foo")));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "globals2")
|
|
||||||
{
|
|
||||||
ScopedFastFlag sff[]{
|
|
||||||
{"LuauReturnTypeInferenceInNonstrict", true},
|
|
||||||
{"LuauLowerBoundsCalculation", true},
|
|
||||||
};
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
|
||||||
--!nonstrict
|
|
||||||
foo = function() return 1 end
|
|
||||||
foo = "now i'm a string!"
|
|
||||||
)");
|
|
||||||
|
|
||||||
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
|
||||||
|
|
||||||
TypeMismatch* tm = get<TypeMismatch>(result.errors[0]);
|
|
||||||
REQUIRE(tm);
|
|
||||||
CHECK_EQ("() -> number", toString(tm->wantedType));
|
|
||||||
CHECK_EQ("string", toString(tm->givenType));
|
|
||||||
CHECK_EQ("() -> number", toString(requireType("foo")));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "globals_everywhere")
|
|
||||||
{
|
|
||||||
CheckResult result = check(R"(
|
|
||||||
--!nonstrict
|
|
||||||
foo = 1
|
|
||||||
|
|
||||||
if true then
|
|
||||||
bar = 2
|
|
||||||
end
|
|
||||||
)");
|
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
|
||||||
|
|
||||||
CHECK_EQ("any", toString(requireType("foo")));
|
|
||||||
CHECK_EQ("any", toString(requireType("bar")));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "function_returns_number_or_string")
|
|
||||||
{
|
|
||||||
ScopedFastFlag sff[]{{"LuauReturnTypeInferenceInNonstrict", true}, {"LuauLowerBoundsCalculation", true}};
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
|
||||||
--!nonstrict
|
|
||||||
local function f()
|
|
||||||
if math.random() > 0.5 then
|
|
||||||
return 5
|
|
||||||
else
|
|
||||||
return "hi"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)");
|
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
|
||||||
|
|
||||||
CHECK("() -> number | string" == toString(requireType("f")));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "infer_nullary_function")
|
TEST_CASE_FIXTURE(Fixture, "infer_nullary_function")
|
||||||
{
|
{
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
@ -106,13 +35,8 @@ TEST_CASE_FIXTURE(Fixture, "infer_nullary_function")
|
|||||||
REQUIRE_EQ(0, rets.size());
|
REQUIRE_EQ(0, rets.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "first_return_type_dictates_number_of_return_types")
|
TEST_CASE_FIXTURE(Fixture, "infer_the_maximum_number_of_values_the_function_could_return")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff[]{
|
|
||||||
{"LuauReturnTypeInferenceInNonstrict", true},
|
|
||||||
{"LuauLowerBoundsCalculation", true},
|
|
||||||
};
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
--!nonstrict
|
--!nonstrict
|
||||||
function getMinCardCountForWidth(width)
|
function getMinCardCountForWidth(width)
|
||||||
@ -127,18 +51,22 @@ TEST_CASE_FIXTURE(Fixture, "first_return_type_dictates_number_of_return_types")
|
|||||||
TypeId t = requireType("getMinCardCountForWidth");
|
TypeId t = requireType("getMinCardCountForWidth");
|
||||||
REQUIRE(t);
|
REQUIRE(t);
|
||||||
|
|
||||||
REQUIRE_EQ("(any) -> number", toString(t));
|
REQUIRE_EQ("(any) -> (...any)", toString(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Maybe we want this?
|
||||||
TEST_CASE_FIXTURE(Fixture, "return_annotation_is_still_checked")
|
TEST_CASE_FIXTURE(Fixture, "return_annotation_is_still_checked")
|
||||||
{
|
{
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
--!nonstrict
|
|
||||||
function foo(x): number return 'hello' end
|
function foo(x): number return 'hello' end
|
||||||
)");
|
)");
|
||||||
|
|
||||||
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||||
|
|
||||||
|
REQUIRE_NE(*typeChecker.anyType, *requireType("foo"));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "function_parameters_are_any")
|
TEST_CASE_FIXTURE(Fixture, "function_parameters_are_any")
|
||||||
{
|
{
|
||||||
@ -324,11 +252,6 @@ TEST_CASE_FIXTURE(Fixture, "delay_function_does_not_require_its_argument_to_retu
|
|||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "inconsistent_module_return_types_are_ok")
|
TEST_CASE_FIXTURE(Fixture, "inconsistent_module_return_types_are_ok")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff[]{
|
|
||||||
{"LuauReturnTypeInferenceInNonstrict", true},
|
|
||||||
{"LuauLowerBoundsCalculation", true},
|
|
||||||
};
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
--!nonstrict
|
--!nonstrict
|
||||||
|
|
||||||
@ -345,7 +268,7 @@ TEST_CASE_FIXTURE(Fixture, "inconsistent_module_return_types_are_ok")
|
|||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
|
||||||
REQUIRE_EQ("((any) -> string) | {| foo: any |}", toString(getMainModule()->getModuleScope()->returnType));
|
REQUIRE_EQ("any", toString(getMainModule()->getModuleScope()->returnType));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "returning_insufficient_return_values")
|
TEST_CASE_FIXTURE(Fixture, "returning_insufficient_return_values")
|
||||||
|
@ -621,7 +621,6 @@ TEST_CASE_FIXTURE(Fixture, "normalize_module_return_type")
|
|||||||
{
|
{
|
||||||
ScopedFastFlag sff[] = {
|
ScopedFastFlag sff[] = {
|
||||||
{"LuauLowerBoundsCalculation", true},
|
{"LuauLowerBoundsCalculation", true},
|
||||||
{"LuauReturnTypeInferenceInNonstrict", true},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
check(R"(
|
check(R"(
|
||||||
@ -642,7 +641,7 @@ TEST_CASE_FIXTURE(Fixture, "normalize_module_return_type")
|
|||||||
end
|
end
|
||||||
)");
|
)");
|
||||||
|
|
||||||
CHECK_EQ("(any, any) -> (any, any) -> any", toString(getMainModule()->getModuleScope()->returnType));
|
CHECK_EQ("(any, any) -> (...any)", toString(getMainModule()->getModuleScope()->returnType));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "return_type_is_not_a_constrained_intersection")
|
TEST_CASE_FIXTURE(Fixture, "return_type_is_not_a_constrained_intersection")
|
||||||
|
@ -677,11 +677,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "toposort_doesnt_break_mutual_recursion")
|
|||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "check_function_before_lambda_that_uses_it")
|
TEST_CASE_FIXTURE(Fixture, "check_function_before_lambda_that_uses_it")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff[]{
|
|
||||||
{"LuauReturnTypeInferenceInNonstrict", true},
|
|
||||||
{"LuauLowerBoundsCalculation", true},
|
|
||||||
};
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
--!nonstrict
|
--!nonstrict
|
||||||
|
|
||||||
@ -690,7 +685,7 @@ TEST_CASE_FIXTURE(Fixture, "check_function_before_lambda_that_uses_it")
|
|||||||
end
|
end
|
||||||
|
|
||||||
return function()
|
return function()
|
||||||
return f()
|
return f():andThen()
|
||||||
end
|
end
|
||||||
)");
|
)");
|
||||||
|
|
||||||
@ -817,18 +812,14 @@ TEST_CASE_FIXTURE(Fixture, "calling_function_with_incorrect_argument_type_yields
|
|||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "calling_function_with_anytypepack_doesnt_leak_free_types")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "calling_function_with_anytypepack_doesnt_leak_free_types")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff[]{
|
|
||||||
{"LuauReturnTypeInferenceInNonstrict", true},
|
|
||||||
{"LuauLowerBoundsCalculation", true},
|
|
||||||
};
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
--!nonstrict
|
--!nonstrict
|
||||||
|
|
||||||
function Test(a): ...any
|
function Test(a)
|
||||||
return 1, ""
|
return 1, ""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local tab = {}
|
local tab = {}
|
||||||
table.insert(tab, Test(1));
|
table.insert(tab, Test(1));
|
||||||
)");
|
)");
|
||||||
@ -1625,21 +1616,6 @@ TEST_CASE_FIXTURE(Fixture, "occurs_check_failure_in_function_return_type")
|
|||||||
CHECK(nullptr != get<OccursCheckFailed>(result.errors[0]));
|
CHECK(nullptr != get<OccursCheckFailed>(result.errors[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "weird_fail_to_unify_type_pack")
|
|
||||||
{
|
|
||||||
ScopedFastFlag sff[]{
|
|
||||||
{"LuauReturnTypeInferenceInNonstrict", true},
|
|
||||||
{"LuauLowerBoundsCalculation", true},
|
|
||||||
};
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
|
||||||
local function f() return end
|
|
||||||
local g = function() return f() end
|
|
||||||
)");
|
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "quantify_constrained_types")
|
TEST_CASE_FIXTURE(Fixture, "quantify_constrained_types")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff[]{
|
ScopedFastFlag sff[]{
|
||||||
|
@ -516,7 +516,7 @@ TEST_CASE_FIXTURE(Fixture, "loop_iter_trailing_nil")
|
|||||||
CHECK_EQ(*typeChecker.nilType, *requireType("extra"));
|
CHECK_EQ(*typeChecker.nilType, *requireType("extra"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "loop_iter_no_indexer")
|
TEST_CASE_FIXTURE(Fixture, "loop_iter_no_indexer_strict")
|
||||||
{
|
{
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
local t = {}
|
local t = {}
|
||||||
@ -531,6 +531,17 @@ TEST_CASE_FIXTURE(Fixture, "loop_iter_no_indexer")
|
|||||||
CHECK_EQ("Cannot iterate over a table without indexer", ge->message);
|
CHECK_EQ("Cannot iterate over a table without indexer", ge->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "loop_iter_no_indexer_nonstrict")
|
||||||
|
{
|
||||||
|
CheckResult result = check(Mode::Nonstrict, R"(
|
||||||
|
local t = {}
|
||||||
|
for k, v in t do
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
LUAU_REQUIRE_ERROR_COUNT(0, result);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "loop_iter_iter_metamethod")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "loop_iter_iter_metamethod")
|
||||||
{
|
{
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
|
@ -343,6 +343,20 @@ TEST_CASE_FIXTURE(Fixture, "specialization_binds_with_prototypes_too_early")
|
|||||||
LUAU_REQUIRE_ERRORS(result); // Should not have any errors.
|
LUAU_REQUIRE_ERRORS(result); // Should not have any errors.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "weird_fail_to_unify_type_pack")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff[] = {
|
||||||
|
{"LuauLowerBoundsCalculation", false},
|
||||||
|
};
|
||||||
|
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
local function f() return end
|
||||||
|
local g = function() return f() end
|
||||||
|
)");
|
||||||
|
|
||||||
|
LUAU_REQUIRE_ERRORS(result); // Should not have any errors.
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "weird_fail_to_unify_variadic_pack")
|
TEST_CASE_FIXTURE(Fixture, "weird_fail_to_unify_variadic_pack")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff[] = {
|
ScopedFastFlag sff[] = {
|
||||||
|
@ -2990,6 +2990,15 @@ TEST_CASE_FIXTURE(Fixture, "expected_indexer_value_type_extra_2")
|
|||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "expected_indexer_from_table_union")
|
||||||
|
{
|
||||||
|
ScopedFastFlag luauExpectedTableUnionIndexerType{"LuauExpectedTableUnionIndexerType", true};
|
||||||
|
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(check(R"(local a: {[string]: {number | string}} = {a = {2, 's'}})"));
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(check(R"(local a: {[string]: {number | string}}? = {a = {2, 's'}})"));
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(check(R"(local a: {[string]: {[string]: {string?}}?} = {["a"] = {["b"] = {"a", "b"}}})"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "prop_access_on_key_whose_types_mismatches")
|
TEST_CASE_FIXTURE(Fixture, "prop_access_on_key_whose_types_mismatches")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{"LuauReportErrorsOnIndexerKeyMismatch", true};
|
ScopedFastFlag sff{"LuauReportErrorsOnIndexerKeyMismatch", true};
|
||||||
|
@ -85,20 +85,19 @@ TEST_CASE_FIXTURE(Fixture, "infer_in_nocheck_mode")
|
|||||||
{
|
{
|
||||||
ScopedFastFlag sff[]{
|
ScopedFastFlag sff[]{
|
||||||
{"DebugLuauDeferredConstraintResolution", false},
|
{"DebugLuauDeferredConstraintResolution", false},
|
||||||
{"LuauReturnTypeInferenceInNonstrict", true},
|
|
||||||
{"LuauLowerBoundsCalculation", true},
|
{"LuauLowerBoundsCalculation", true},
|
||||||
};
|
};
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
--!nocheck
|
--!nocheck
|
||||||
function f(x)
|
function f(x)
|
||||||
return 5
|
return x
|
||||||
end
|
end
|
||||||
-- we get type information even if there's type errors
|
-- we get type information even if there's type errors
|
||||||
f(1, 2)
|
f(1, 2)
|
||||||
)");
|
)");
|
||||||
|
|
||||||
CHECK_EQ("(any) -> number", toString(requireType("f")));
|
CHECK_EQ("(any) -> (...any)", toString(requireType("f")));
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
}
|
}
|
||||||
@ -355,6 +354,35 @@ TEST_CASE_FIXTURE(Fixture, "check_expr_recursion_limit")
|
|||||||
CHECK(nullptr != get<CodeTooComplex>(result.errors[0]));
|
CHECK(nullptr != get<CodeTooComplex>(result.errors[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "globals")
|
||||||
|
{
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
--!nonstrict
|
||||||
|
foo = true
|
||||||
|
foo = "now i'm a string!"
|
||||||
|
)");
|
||||||
|
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
CHECK_EQ("any", toString(requireType("foo")));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "globals2")
|
||||||
|
{
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
--!nonstrict
|
||||||
|
foo = function() return 1 end
|
||||||
|
foo = "now i'm a string!"
|
||||||
|
)");
|
||||||
|
|
||||||
|
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||||
|
|
||||||
|
TypeMismatch* tm = get<TypeMismatch>(result.errors[0]);
|
||||||
|
REQUIRE(tm);
|
||||||
|
CHECK_EQ("() -> (...any)", toString(tm->wantedType));
|
||||||
|
CHECK_EQ("string", toString(tm->givenType));
|
||||||
|
CHECK_EQ("() -> (...any)", toString(requireType("foo")));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "globals_are_banned_in_strict_mode")
|
TEST_CASE_FIXTURE(Fixture, "globals_are_banned_in_strict_mode")
|
||||||
{
|
{
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
|
@ -592,4 +592,24 @@ do
|
|||||||
assert(countud() == 3)
|
assert(countud() == 3)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- test __newindex-as-a-table indirection: this had memory safety bugs in Lua 5.1.0
|
||||||
|
do
|
||||||
|
local hit = false
|
||||||
|
|
||||||
|
local grandparent = {}
|
||||||
|
grandparent.__newindex = function(s,k,v)
|
||||||
|
assert(k == "foo" and v == 10)
|
||||||
|
hit = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local parent = {}
|
||||||
|
parent.__newindex = parent
|
||||||
|
setmetatable(parent, grandparent)
|
||||||
|
|
||||||
|
local child = setmetatable({}, parent)
|
||||||
|
child.foo = 10
|
||||||
|
|
||||||
|
assert(hit and child.foo == nil and parent.foo == nil)
|
||||||
|
end
|
||||||
|
|
||||||
return"OK"
|
return"OK"
|
@ -63,7 +63,7 @@ static int testAssertionHandler(const char* expr, const char* file, int line, co
|
|||||||
if (debuggerPresent())
|
if (debuggerPresent())
|
||||||
LUAU_DEBUGBREAK();
|
LUAU_DEBUGBREAK();
|
||||||
|
|
||||||
ADD_FAIL_AT(file, line, "Assertion failed: ", expr);
|
ADD_FAIL_AT(file, line, "Assertion failed: ", std::string(expr));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
521
tools/faillist.txt
Normal file
521
tools/faillist.txt
Normal file
@ -0,0 +1,521 @@
|
|||||||
|
AnnotationTests.as_expr_does_not_propagate_type_info
|
||||||
|
AnnotationTests.as_expr_is_bidirectional
|
||||||
|
AnnotationTests.as_expr_warns_on_unrelated_cast
|
||||||
|
AnnotationTests.builtin_types_are_not_exported
|
||||||
|
AnnotationTests.cannot_use_nonexported_type
|
||||||
|
AnnotationTests.cloned_interface_maintains_pointers_between_definitions
|
||||||
|
AnnotationTests.corecursive_types_error_on_tight_loop
|
||||||
|
AnnotationTests.define_generic_type_alias
|
||||||
|
AnnotationTests.duplicate_type_param_name
|
||||||
|
AnnotationTests.for_loop_counter_annotation_is_checked
|
||||||
|
AnnotationTests.function_return_annotations_are_checked
|
||||||
|
AnnotationTests.generic_aliases_are_cloned_properly
|
||||||
|
AnnotationTests.instantiate_type_fun_should_not_trip_rbxassert
|
||||||
|
AnnotationTests.instantiation_clone_has_to_follow
|
||||||
|
AnnotationTests.interface_types_belong_to_interface_arena
|
||||||
|
AnnotationTests.luau_ice_triggers_an_ice
|
||||||
|
AnnotationTests.luau_ice_triggers_an_ice_exception_with_flag
|
||||||
|
AnnotationTests.luau_ice_triggers_an_ice_exception_with_flag_handler
|
||||||
|
AnnotationTests.luau_ice_triggers_an_ice_handler
|
||||||
|
AnnotationTests.luau_print_is_magic_if_the_flag_is_set
|
||||||
|
AnnotationTests.luau_print_is_not_special_without_the_flag
|
||||||
|
AnnotationTests.occurs_check_on_cyclic_intersection_typevar
|
||||||
|
AnnotationTests.occurs_check_on_cyclic_union_typevar
|
||||||
|
AnnotationTests.self_referential_type_alias
|
||||||
|
AnnotationTests.too_many_type_params
|
||||||
|
AnnotationTests.two_type_params
|
||||||
|
AnnotationTests.type_alias_always_resolve_to_a_real_type
|
||||||
|
AnnotationTests.type_alias_B_should_check_with_another_aliases_until_a_non_aliased_type
|
||||||
|
AnnotationTests.type_alias_should_alias_to_number
|
||||||
|
AnnotationTests.type_aliasing_to_number_should_not_check_given_a_string
|
||||||
|
AnnotationTests.type_annotations_inside_function_bodies
|
||||||
|
AnnotationTests.type_assertion_expr
|
||||||
|
AnnotationTests.typeof_variable_type_annotation_should_return_its_type
|
||||||
|
AnnotationTests.use_generic_type_alias
|
||||||
|
AnnotationTests.use_type_required_from_another_file
|
||||||
|
AstQuery.last_argument_function_call_type
|
||||||
|
AstQuery::getDocumentationSymbolAtPosition.binding
|
||||||
|
AstQuery::getDocumentationSymbolAtPosition.event_callback_arg
|
||||||
|
AstQuery::getDocumentationSymbolAtPosition.overloaded_fn
|
||||||
|
AstQuery::getDocumentationSymbolAtPosition.prop
|
||||||
|
AutocompleteTest.argument_types
|
||||||
|
AutocompleteTest.arguments_to_global_lambda
|
||||||
|
AutocompleteTest.as_types
|
||||||
|
AutocompleteTest.autocomplete_boolean_singleton
|
||||||
|
AutocompleteTest.autocomplete_default_type_pack_parameters
|
||||||
|
AutocompleteTest.autocomplete_default_type_parameters
|
||||||
|
AutocompleteTest.autocomplete_documentation_symbols
|
||||||
|
AutocompleteTest.autocomplete_end_with_fn_exprs
|
||||||
|
AutocompleteTest.autocomplete_end_with_lambda
|
||||||
|
AutocompleteTest.autocomplete_explicit_type_pack
|
||||||
|
AutocompleteTest.autocomplete_first_function_arg_expected_type
|
||||||
|
AutocompleteTest.autocomplete_for_in_middle_keywords
|
||||||
|
AutocompleteTest.autocomplete_for_middle_keywords
|
||||||
|
AutocompleteTest.autocomplete_if_else_regression
|
||||||
|
AutocompleteTest.autocomplete_if_middle_keywords
|
||||||
|
AutocompleteTest.autocomplete_ifelse_expressions
|
||||||
|
AutocompleteTest.autocomplete_on_string_singletons
|
||||||
|
AutocompleteTest.autocomplete_oop_implicit_self
|
||||||
|
AutocompleteTest.autocomplete_repeat_middle_keyword
|
||||||
|
AutocompleteTest.autocomplete_string_singleton_equality
|
||||||
|
AutocompleteTest.autocomplete_string_singleton_escape
|
||||||
|
AutocompleteTest.autocomplete_string_singletons
|
||||||
|
AutocompleteTest.autocomplete_until_expression
|
||||||
|
AutocompleteTest.autocomplete_until_in_repeat
|
||||||
|
AutocompleteTest.autocomplete_while_middle_keywords
|
||||||
|
AutocompleteTest.autocompleteProp_index_function_metamethod_is_variadic
|
||||||
|
AutocompleteTest.bias_toward_inner_scope
|
||||||
|
AutocompleteTest.comments
|
||||||
|
AutocompleteTest.cyclic_table
|
||||||
|
AutocompleteTest.do_not_overwrite_context_sensitive_kws
|
||||||
|
AutocompleteTest.do_not_suggest_internal_module_type
|
||||||
|
AutocompleteTest.do_not_suggest_synthetic_table_name
|
||||||
|
AutocompleteTest.dont_offer_any_suggestions_from_the_end_of_a_comment
|
||||||
|
AutocompleteTest.dont_offer_any_suggestions_from_within_a_broken_comment
|
||||||
|
AutocompleteTest.dont_offer_any_suggestions_from_within_a_broken_comment_at_the_very_end_of_the_file
|
||||||
|
AutocompleteTest.dont_offer_any_suggestions_from_within_a_comment
|
||||||
|
AutocompleteTest.dont_suggest_local_before_its_definition
|
||||||
|
AutocompleteTest.empty_program
|
||||||
|
AutocompleteTest.function_expr_params
|
||||||
|
AutocompleteTest.function_in_assignment_has_parentheses
|
||||||
|
AutocompleteTest.function_in_assignment_has_parentheses_2
|
||||||
|
AutocompleteTest.function_parameters
|
||||||
|
AutocompleteTest.function_result_passed_to_function_has_parentheses
|
||||||
|
AutocompleteTest.function_type_types
|
||||||
|
AutocompleteTest.generic_types
|
||||||
|
AutocompleteTest.get_member_completions
|
||||||
|
AutocompleteTest.get_string_completions
|
||||||
|
AutocompleteTest.get_suggestions_for_new_statement
|
||||||
|
AutocompleteTest.get_suggestions_for_the_very_start_of_the_script
|
||||||
|
AutocompleteTest.global_function_params
|
||||||
|
AutocompleteTest.global_functions_are_not_scoped_lexically
|
||||||
|
AutocompleteTest.if_then_else_elseif_completions
|
||||||
|
AutocompleteTest.if_then_else_full_keywords
|
||||||
|
AutocompleteTest.keyword_members
|
||||||
|
AutocompleteTest.keyword_methods
|
||||||
|
AutocompleteTest.keyword_types
|
||||||
|
AutocompleteTest.leave_numbers_alone
|
||||||
|
AutocompleteTest.library_non_self_calls_are_fine
|
||||||
|
AutocompleteTest.library_self_calls_are_invalid
|
||||||
|
AutocompleteTest.local_function
|
||||||
|
AutocompleteTest.local_function_params
|
||||||
|
AutocompleteTest.local_functions_fall_out_of_scope
|
||||||
|
AutocompleteTest.local_initializer
|
||||||
|
AutocompleteTest.local_initializer_2
|
||||||
|
AutocompleteTest.local_names
|
||||||
|
AutocompleteTest.local_types_builtin
|
||||||
|
AutocompleteTest.method_call_inside_function_body
|
||||||
|
AutocompleteTest.method_call_inside_if_conditional
|
||||||
|
AutocompleteTest.module_type_members
|
||||||
|
AutocompleteTest.modules_with_types
|
||||||
|
AutocompleteTest.nested_member_completions
|
||||||
|
AutocompleteTest.nested_recursive_function
|
||||||
|
AutocompleteTest.no_function_name_suggestions
|
||||||
|
AutocompleteTest.no_incompatible_self_calls
|
||||||
|
AutocompleteTest.no_incompatible_self_calls_2
|
||||||
|
AutocompleteTest.no_incompatible_self_calls_on_class
|
||||||
|
AutocompleteTest.no_incompatible_self_calls_provisional
|
||||||
|
AutocompleteTest.not_the_var_we_are_defining
|
||||||
|
AutocompleteTest.optional_members
|
||||||
|
AutocompleteTest.private_types
|
||||||
|
AutocompleteTest.recommend_statement_starting_keywords
|
||||||
|
AutocompleteTest.recursive_function
|
||||||
|
AutocompleteTest.recursive_function_global
|
||||||
|
AutocompleteTest.recursive_function_local
|
||||||
|
AutocompleteTest.return_types
|
||||||
|
AutocompleteTest.skip_current_local
|
||||||
|
AutocompleteTest.sometimes_the_metatable_is_an_error
|
||||||
|
AutocompleteTest.source_module_preservation_and_invalidation
|
||||||
|
AutocompleteTest.statement_between_two_statements
|
||||||
|
AutocompleteTest.stop_at_first_stat_when_recommending_keywords
|
||||||
|
AutocompleteTest.string_prim_non_self_calls_are_avoided
|
||||||
|
AutocompleteTest.string_prim_self_calls_are_fine
|
||||||
|
AutocompleteTest.suggest_external_module_type
|
||||||
|
AutocompleteTest.suggest_table_keys
|
||||||
|
AutocompleteTest.table_intersection
|
||||||
|
AutocompleteTest.table_union
|
||||||
|
AutocompleteTest.type_correct_argument_type_suggestion
|
||||||
|
AutocompleteTest.type_correct_expected_argument_type_pack_suggestion
|
||||||
|
AutocompleteTest.type_correct_expected_argument_type_suggestion
|
||||||
|
AutocompleteTest.type_correct_expected_argument_type_suggestion_optional
|
||||||
|
AutocompleteTest.type_correct_expected_argument_type_suggestion_self
|
||||||
|
AutocompleteTest.type_correct_expected_return_type_pack_suggestion
|
||||||
|
AutocompleteTest.type_correct_expected_return_type_suggestion
|
||||||
|
AutocompleteTest.type_correct_full_type_suggestion
|
||||||
|
AutocompleteTest.type_correct_function_no_parenthesis
|
||||||
|
AutocompleteTest.type_correct_function_return_types
|
||||||
|
AutocompleteTest.type_correct_function_type_suggestion
|
||||||
|
AutocompleteTest.type_correct_keywords
|
||||||
|
AutocompleteTest.type_correct_local_type_suggestion
|
||||||
|
AutocompleteTest.type_correct_sealed_table
|
||||||
|
AutocompleteTest.type_correct_suggestion_for_overloads
|
||||||
|
AutocompleteTest.type_correct_suggestion_in_argument
|
||||||
|
AutocompleteTest.type_correct_suggestion_in_table
|
||||||
|
AutocompleteTest.type_scoping_easy
|
||||||
|
AutocompleteTest.unsealed_table
|
||||||
|
AutocompleteTest.unsealed_table_2
|
||||||
|
AutocompleteTest.user_defined_globals
|
||||||
|
AutocompleteTest.user_defined_local_functions_in_own_definition
|
||||||
|
BuiltinDefinitionsTest.lib_documentation_symbols
|
||||||
|
BuiltinTests.aliased_string_format
|
||||||
|
BuiltinTests.assert_removes_falsy_types
|
||||||
|
BuiltinTests.assert_removes_falsy_types2
|
||||||
|
BuiltinTests.assert_removes_falsy_types_even_from_type_pack_tail_but_only_for_the_first_type
|
||||||
|
BuiltinTests.assert_returns_false_and_string_iff_it_knows_the_first_argument_cannot_be_truthy
|
||||||
|
BuiltinTests.bad_select_should_not_crash
|
||||||
|
BuiltinTests.builtin_tables_sealed
|
||||||
|
BuiltinTests.coroutine_resume_anything_goes
|
||||||
|
BuiltinTests.coroutine_wrap_anything_goes
|
||||||
|
BuiltinTests.debug_info_is_crazy
|
||||||
|
BuiltinTests.debug_traceback_is_crazy
|
||||||
|
BuiltinTests.dont_add_definitions_to_persistent_types
|
||||||
|
BuiltinTests.find_capture_types
|
||||||
|
BuiltinTests.find_capture_types2
|
||||||
|
BuiltinTests.find_capture_types3
|
||||||
|
BuiltinTests.gcinfo
|
||||||
|
BuiltinTests.getfenv
|
||||||
|
BuiltinTests.global_singleton_types_are_sealed
|
||||||
|
BuiltinTests.gmatch_capture_types
|
||||||
|
BuiltinTests.gmatch_capture_types2
|
||||||
|
BuiltinTests.gmatch_capture_types_balanced_escaped_parens
|
||||||
|
BuiltinTests.gmatch_capture_types_default_capture
|
||||||
|
BuiltinTests.gmatch_capture_types_invalid_pattern_fallback_to_builtin
|
||||||
|
BuiltinTests.gmatch_capture_types_invalid_pattern_fallback_to_builtin2
|
||||||
|
BuiltinTests.gmatch_capture_types_leading_end_bracket_is_part_of_set
|
||||||
|
BuiltinTests.gmatch_capture_types_parens_in_sets_are_ignored
|
||||||
|
BuiltinTests.gmatch_capture_types_set_containing_lbracket
|
||||||
|
BuiltinTests.gmatch_definition
|
||||||
|
BuiltinTests.ipairs_iterator_should_infer_types_and_type_check
|
||||||
|
BuiltinTests.lua_51_exported_globals_all_exist
|
||||||
|
BuiltinTests.match_capture_types
|
||||||
|
BuiltinTests.match_capture_types2
|
||||||
|
BuiltinTests.math_max_checks_for_numbers
|
||||||
|
BuiltinTests.math_max_variatic
|
||||||
|
BuiltinTests.math_things_are_defined
|
||||||
|
BuiltinTests.next_iterator_should_infer_types_and_type_check
|
||||||
|
BuiltinTests.no_persistent_typelevel_change
|
||||||
|
BuiltinTests.os_time_takes_optional_date_table
|
||||||
|
BuiltinTests.pairs_iterator_should_infer_types_and_type_check
|
||||||
|
BuiltinTests.see_thru_select
|
||||||
|
BuiltinTests.see_thru_select_count
|
||||||
|
BuiltinTests.select_on_variadic
|
||||||
|
BuiltinTests.select_slightly_out_of_range
|
||||||
|
BuiltinTests.select_way_out_of_range
|
||||||
|
BuiltinTests.select_with_decimal_argument_is_rounded_down
|
||||||
|
BuiltinTests.select_with_variadic_typepack_tail
|
||||||
|
BuiltinTests.select_with_variadic_typepack_tail_and_string_head
|
||||||
|
BuiltinTests.set_metatable_needs_arguments
|
||||||
|
BuiltinTests.setmetatable_should_not_mutate_persisted_types
|
||||||
|
BuiltinTests.setmetatable_unpacks_arg_types_correctly
|
||||||
|
BuiltinTests.sort
|
||||||
|
BuiltinTests.sort_with_bad_predicate
|
||||||
|
BuiltinTests.sort_with_predicate
|
||||||
|
BuiltinTests.string_format_arg_count_mismatch
|
||||||
|
BuiltinTests.string_format_arg_types_inference
|
||||||
|
BuiltinTests.string_format_as_method
|
||||||
|
BuiltinTests.string_format_correctly_ordered_types
|
||||||
|
BuiltinTests.string_format_report_all_type_errors_at_correct_positions
|
||||||
|
BuiltinTests.string_format_use_correct_argument
|
||||||
|
BuiltinTests.string_format_use_correct_argument2
|
||||||
|
BuiltinTests.string_lib_self_noself
|
||||||
|
BuiltinTests.table_concat_returns_string
|
||||||
|
BuiltinTests.table_dot_remove_optionally_returns_generic
|
||||||
|
BuiltinTests.table_freeze_is_generic
|
||||||
|
BuiltinTests.table_insert_correctly_infers_type_of_array_2_args_overload
|
||||||
|
BuiltinTests.table_insert_correctly_infers_type_of_array_3_args_overload
|
||||||
|
BuiltinTests.table_pack
|
||||||
|
BuiltinTests.table_pack_reduce
|
||||||
|
BuiltinTests.table_pack_variadic
|
||||||
|
BuiltinTests.thread_is_a_type
|
||||||
|
BuiltinTests.tonumber_returns_optional_number_type
|
||||||
|
BuiltinTests.tonumber_returns_optional_number_type2
|
||||||
|
BuiltinTests.xpcall
|
||||||
|
DefinitionTests.class_definition_function_prop
|
||||||
|
DefinitionTests.class_definitions_cannot_extend_non_class
|
||||||
|
DefinitionTests.class_definitions_cannot_overload_non_function
|
||||||
|
DefinitionTests.declaring_generic_functions
|
||||||
|
DefinitionTests.definition_file_class_function_args
|
||||||
|
DefinitionTests.definition_file_classes
|
||||||
|
DefinitionTests.definition_file_loading
|
||||||
|
DefinitionTests.definitions_documentation_symbols
|
||||||
|
DefinitionTests.documentation_symbols_dont_attach_to_persistent_types
|
||||||
|
DefinitionTests.load_definition_file_errors_do_not_pollute_global_scope
|
||||||
|
DefinitionTests.no_cyclic_defined_classes
|
||||||
|
DefinitionTests.single_class_type_identity_in_global_types
|
||||||
|
FrontendTest.accumulate_cached_errors
|
||||||
|
FrontendTest.accumulate_cached_errors_in_consistent_order
|
||||||
|
FrontendTest.any_annotation_breaks_cycle
|
||||||
|
FrontendTest.ast_node_at_position
|
||||||
|
FrontendTest.automatically_check_cyclically_dependent_scripts
|
||||||
|
FrontendTest.automatically_check_dependent_scripts
|
||||||
|
FrontendTest.check_without_builtin_next
|
||||||
|
FrontendTest.clearStats
|
||||||
|
FrontendTest.cycle_detection_between_check_and_nocheck
|
||||||
|
FrontendTest.cycle_detection_disabled_in_nocheck
|
||||||
|
FrontendTest.cycle_error_paths
|
||||||
|
FrontendTest.cycle_errors_can_be_fixed
|
||||||
|
FrontendTest.cycle_incremental_type_surface
|
||||||
|
FrontendTest.cycle_incremental_type_surface_longer
|
||||||
|
FrontendTest.discard_type_graphs
|
||||||
|
FrontendTest.dont_recheck_script_that_hasnt_been_marked_dirty
|
||||||
|
FrontendTest.dont_reparse_clean_file_when_linting
|
||||||
|
FrontendTest.environments
|
||||||
|
FrontendTest.find_a_require
|
||||||
|
FrontendTest.find_a_require_inside_a_function
|
||||||
|
FrontendTest.ignore_require_to_nonexistent_file
|
||||||
|
FrontendTest.imported_table_modification_2
|
||||||
|
FrontendTest.it_should_be_safe_to_stringify_errors_when_full_type_graph_is_discarded
|
||||||
|
FrontendTest.no_use_after_free_with_type_fun_instantiation
|
||||||
|
FrontendTest.nocheck_cycle_used_by_checked
|
||||||
|
FrontendTest.nocheck_modules_are_typed
|
||||||
|
FrontendTest.produce_errors_for_unchanged_file_with_a_syntax_error
|
||||||
|
FrontendTest.produce_errors_for_unchanged_file_with_errors
|
||||||
|
FrontendTest.re_report_type_error_in_required_file
|
||||||
|
FrontendTest.real_source
|
||||||
|
FrontendTest.recheck_if_dependent_script_is_dirty
|
||||||
|
FrontendTest.report_require_to_nonexistent_file
|
||||||
|
FrontendTest.report_syntax_error_in_required_file
|
||||||
|
FrontendTest.reports_errors_from_multiple_sources
|
||||||
|
FrontendTest.stats_are_not_reset_between_checks
|
||||||
|
FrontendTest.test_lint_uses_correct_config
|
||||||
|
FrontendTest.test_pruneParentSegments
|
||||||
|
FrontendTest.trace_requires_in_nonstrict_mode
|
||||||
|
FrontendTest.typecheck_twice_for_ast_types
|
||||||
|
isSubtype.functions_and_any
|
||||||
|
isSubtype.intersection_of_functions_of_different_arities
|
||||||
|
isSubtype.intersection_of_tables
|
||||||
|
isSubtype.table_with_any_prop
|
||||||
|
isSubtype.table_with_table_prop
|
||||||
|
isSubtype.tables
|
||||||
|
Linter.BuiltinGlobalWrite
|
||||||
|
Linter.DeprecatedApi
|
||||||
|
Linter.LocalShadowGlobal
|
||||||
|
Linter.TableOperations
|
||||||
|
Linter.use_all_parent_scopes_for_globals
|
||||||
|
ModuleTests.any_persistance_does_not_leak
|
||||||
|
ModuleTests.builtin_types_point_into_globalTypes_arena
|
||||||
|
ModuleTests.clone_self_property
|
||||||
|
ModuleTests.deepClone_cyclic_table
|
||||||
|
NonstrictModeTests.delay_function_does_not_require_its_argument_to_return_anything
|
||||||
|
NonstrictModeTests.for_in_iterator_variables_are_any
|
||||||
|
NonstrictModeTests.function_parameters_are_any
|
||||||
|
NonstrictModeTests.inconsistent_module_return_types_are_ok
|
||||||
|
NonstrictModeTests.inconsistent_return_types_are_ok
|
||||||
|
NonstrictModeTests.infer_nullary_function
|
||||||
|
NonstrictModeTests.infer_the_maximum_number_of_values_the_function_could_return
|
||||||
|
NonstrictModeTests.inline_table_props_are_also_any
|
||||||
|
NonstrictModeTests.local_tables_are_not_any
|
||||||
|
NonstrictModeTests.locals_are_any_by_default
|
||||||
|
NonstrictModeTests.offer_a_hint_if_you_use_a_dot_instead_of_a_colon
|
||||||
|
NonstrictModeTests.parameters_having_type_any_are_optional
|
||||||
|
NonstrictModeTests.returning_insufficient_return_values
|
||||||
|
NonstrictModeTests.returning_too_many_values
|
||||||
|
NonstrictModeTests.table_dot_insert_and_recursive_calls
|
||||||
|
NonstrictModeTests.table_props_are_any
|
||||||
|
Normalize.any_wins_the_battle_over_unknown_in_unions
|
||||||
|
Normalize.constrained_intersection_of_intersections
|
||||||
|
Normalize.cyclic_intersection
|
||||||
|
Normalize.cyclic_table_is_marked_normal
|
||||||
|
Normalize.cyclic_table_is_not_marked_normal
|
||||||
|
Normalize.cyclic_table_normalizes_sensibly
|
||||||
|
Normalize.cyclic_union
|
||||||
|
Normalize.fuzz_failure_bound_type_is_normal_but_not_its_bounded_to
|
||||||
|
Normalize.fuzz_failure_instersection_combine_must_follow
|
||||||
|
Normalize.higher_order_function
|
||||||
|
Normalize.intersection_combine_on_bound_self
|
||||||
|
Normalize.intersection_inside_a_table_inside_another_intersection
|
||||||
|
Normalize.intersection_inside_a_table_inside_another_intersection_2
|
||||||
|
Normalize.intersection_inside_a_table_inside_another_intersection_3
|
||||||
|
Normalize.intersection_inside_a_table_inside_another_intersection_4
|
||||||
|
Normalize.intersection_of_confluent_overlapping_tables
|
||||||
|
Normalize.intersection_of_disjoint_tables
|
||||||
|
Normalize.intersection_of_functions
|
||||||
|
Normalize.intersection_of_overlapping_tables
|
||||||
|
Normalize.intersection_of_tables_with_indexers
|
||||||
|
Normalize.nested_table_normalization_with_non_table__no_ice
|
||||||
|
Normalize.normalization_does_not_convert_ever
|
||||||
|
Normalize.normalize_module_return_type
|
||||||
|
Normalize.normalize_unions_containing_never
|
||||||
|
Normalize.normalize_unions_containing_unknown
|
||||||
|
Normalize.return_type_is_not_a_constrained_intersection
|
||||||
|
Normalize.skip_force_normal_on_external_types
|
||||||
|
Normalize.union_of_distinct_free_types
|
||||||
|
Normalize.variadic_tail_is_marked_normal
|
||||||
|
Normalize.visiting_a_type_twice_is_not_considered_normal
|
||||||
|
ParseErrorRecovery.empty_function_type_error_recovery
|
||||||
|
ParseErrorRecovery.extra_table_indexer_recovery
|
||||||
|
ParseErrorRecovery.extra_token_in_consume
|
||||||
|
ParseErrorRecovery.extra_token_in_consume_match
|
||||||
|
ParseErrorRecovery.extra_token_in_consume_match_end
|
||||||
|
ParseErrorRecovery.generic_type_list_recovery
|
||||||
|
ParseErrorRecovery.multiple_parse_errors
|
||||||
|
ParseErrorRecovery.recovery_of_parenthesized_expressions
|
||||||
|
ParseErrorRecovery.statement_error_recovery_expected
|
||||||
|
ParseErrorRecovery.statement_error_recovery_unexpected
|
||||||
|
ParserTests.break_return_not_last_error
|
||||||
|
ParserTests.continue_not_last_error
|
||||||
|
ParserTests.error_on_confusable
|
||||||
|
ParserTests.error_on_non_utf8_sequence
|
||||||
|
ParserTests.error_on_unicode
|
||||||
|
ParserTests.export_is_an_identifier_only_when_followed_by_type
|
||||||
|
ParserTests.functions_cannot_have_return_annotations_if_extensions_are_disabled
|
||||||
|
ParserTests.illegal_type_alias_if_extensions_are_disabled
|
||||||
|
ParserTests.incomplete_statement_error
|
||||||
|
ParserTests.local_cannot_have_annotation_with_extensions_disabled
|
||||||
|
ParserTests.parse_compound_assignment_error_call
|
||||||
|
ParserTests.parse_compound_assignment_error_multiple
|
||||||
|
ParserTests.parse_compound_assignment_error_not_lvalue
|
||||||
|
ParserTests.parse_error_function_call
|
||||||
|
ParserTests.parse_error_function_call_newline
|
||||||
|
ParserTests.parse_error_messages
|
||||||
|
ParserTests.parse_error_table_literal
|
||||||
|
ParserTests.parse_error_type_name
|
||||||
|
ParserTests.parse_nesting_based_end_detection
|
||||||
|
ParserTests.parse_nesting_based_end_detection_failsafe_earlier
|
||||||
|
ParserTests.parse_nesting_based_end_detection_local_function
|
||||||
|
ParserTests.parse_nesting_based_end_detection_local_repeat
|
||||||
|
ParserTests.parse_nesting_based_end_detection_nested
|
||||||
|
ParserTests.parse_nesting_based_end_detection_single_line
|
||||||
|
ParserTests.parse_numbers_error
|
||||||
|
ParserTests.parse_numbers_range_error
|
||||||
|
ParserTests.stop_if_line_ends_with_hyphen
|
||||||
|
ParserTests.type_alias_error_messages
|
||||||
|
RuntimeLimits.typescript_port_of_Result_type
|
||||||
|
ToDot.bound_table
|
||||||
|
ToDot.class
|
||||||
|
ToDot.function
|
||||||
|
ToDot.metatable
|
||||||
|
ToDot.primitive
|
||||||
|
ToDot.table
|
||||||
|
ToString.exhaustive_toString_of_cyclic_table
|
||||||
|
ToString.function_type_with_argument_names
|
||||||
|
ToString.function_type_with_argument_names_and_self
|
||||||
|
ToString.function_type_with_argument_names_generic
|
||||||
|
ToString.named_metatable_toStringNamedFunction
|
||||||
|
ToString.no_parentheses_around_cyclic_function_type_in_union
|
||||||
|
ToString.toStringDetailed2
|
||||||
|
ToString.toStringErrorPack
|
||||||
|
ToString.toStringNamedFunction_generic_pack
|
||||||
|
ToString.toStringNamedFunction_hide_type_params
|
||||||
|
ToString.toStringNamedFunction_id
|
||||||
|
ToString.toStringNamedFunction_map
|
||||||
|
ToString.toStringNamedFunction_overrides_param_names
|
||||||
|
ToString.toStringNamedFunction_variadics
|
||||||
|
TranspilerTests.attach_types
|
||||||
|
TranspilerTests.type_lists_should_be_emitted_correctly
|
||||||
|
TranspilerTests.types_should_not_be_considered_cyclic_if_they_are_not_recursive
|
||||||
|
TypeAliases.basic_alias
|
||||||
|
TypeAliases.cannot_steal_hoisted_type_alias
|
||||||
|
TypeAliases.cli_38393_recursive_intersection_oom
|
||||||
|
TypeAliases.corecursive_function_types
|
||||||
|
TypeAliases.corecursive_types_generic
|
||||||
|
TypeAliases.cyclic_function_type_in_type_alias
|
||||||
|
TypeAliases.cyclic_types_of_named_table_fields_do_not_expand_when_stringified
|
||||||
|
TypeAliases.do_not_quantify_unresolved_aliases
|
||||||
|
TypeAliases.dont_stop_typechecking_after_reporting_duplicate_type_definition
|
||||||
|
TypeAliases.export_type_and_type_alias_are_duplicates
|
||||||
|
TypeAliases.forward_declared_alias_is_not_clobbered_by_prior_unification_with_any
|
||||||
|
TypeAliases.forward_declared_alias_is_not_clobbered_by_prior_unification_with_any_2
|
||||||
|
TypeAliases.free_variables_from_typeof_in_aliases
|
||||||
|
TypeAliases.general_require_multi_assign
|
||||||
|
TypeAliases.generic_param_remap
|
||||||
|
TypeAliases.generic_typevars_are_not_considered_to_escape_their_scope_if_they_are_reused_in_multiple_aliases
|
||||||
|
TypeAliases.module_export_free_type_leak
|
||||||
|
TypeAliases.module_export_wrapped_free_type_leak
|
||||||
|
TypeAliases.mutually_recursive_aliases
|
||||||
|
TypeAliases.mutually_recursive_generic_aliases
|
||||||
|
TypeAliases.mutually_recursive_types_errors
|
||||||
|
TypeAliases.mutually_recursive_types_restriction_not_ok_1
|
||||||
|
TypeAliases.mutually_recursive_types_restriction_not_ok_2
|
||||||
|
TypeAliases.mutually_recursive_types_restriction_ok
|
||||||
|
TypeAliases.mutually_recursive_types_swapsies_not_ok
|
||||||
|
TypeAliases.mutually_recursive_types_swapsies_ok
|
||||||
|
TypeAliases.names_are_ascribed
|
||||||
|
TypeAliases.non_recursive_aliases_that_reuse_a_generic_name
|
||||||
|
TypeAliases.recursive_types_restriction_not_ok
|
||||||
|
TypeAliases.recursive_types_restriction_ok
|
||||||
|
TypeAliases.reported_location_is_correct_when_type_alias_are_duplicates
|
||||||
|
TypeAliases.stringify_optional_parameterized_alias
|
||||||
|
TypeAliases.stringify_type_alias_of_recursive_template_table_type
|
||||||
|
TypeAliases.stringify_type_alias_of_recursive_template_table_type2
|
||||||
|
TypeAliases.type_alias_fwd_declaration_is_precise
|
||||||
|
TypeAliases.type_alias_import_mutation
|
||||||
|
TypeAliases.type_alias_local_mutation
|
||||||
|
TypeAliases.type_alias_local_rename
|
||||||
|
TypeAliases.type_alias_local_synthetic_mutation
|
||||||
|
TypeAliases.type_alias_of_an_imported_recursive_generic_type
|
||||||
|
TypeAliases.type_alias_of_an_imported_recursive_type
|
||||||
|
TypeAliases.use_table_name_and_generic_params_in_errors
|
||||||
|
TypeInferAnyError.any_type_propagates
|
||||||
|
TypeInferAnyError.assign_prop_to_table_by_calling_any_yields_any
|
||||||
|
TypeInferAnyError.call_to_any_yields_any
|
||||||
|
TypeInferAnyError.calling_error_type_yields_error
|
||||||
|
TypeInferAnyError.can_get_length_of_any
|
||||||
|
TypeInferAnyError.can_subscript_any
|
||||||
|
TypeInferAnyError.CheckMethodsOfAny
|
||||||
|
TypeInferAnyError.for_in_loop_iterator_is_any
|
||||||
|
TypeInferAnyError.for_in_loop_iterator_is_any2
|
||||||
|
TypeInferAnyError.for_in_loop_iterator_is_error
|
||||||
|
TypeInferAnyError.for_in_loop_iterator_is_error2
|
||||||
|
TypeInferAnyError.for_in_loop_iterator_returns_any
|
||||||
|
TypeInferAnyError.for_in_loop_iterator_returns_any2
|
||||||
|
TypeInferAnyError.indexing_error_type_does_not_produce_an_error
|
||||||
|
TypeInferAnyError.length_of_error_type_does_not_produce_an_error
|
||||||
|
TypeInferAnyError.metatable_of_any_can_be_a_table
|
||||||
|
TypeInferAnyError.prop_access_on_any_with_other_options
|
||||||
|
TypeInferAnyError.quantify_any_does_not_bind_to_itself
|
||||||
|
TypeInferAnyError.replace_every_free_type_when_unifying_a_complex_function_with_any
|
||||||
|
TypeInferAnyError.type_error_addition
|
||||||
|
TypeInferClasses.assign_to_prop_of_class
|
||||||
|
TypeInferClasses.call_base_method
|
||||||
|
TypeInferClasses.call_instance_method
|
||||||
|
TypeInferClasses.call_method_of_a_child_class
|
||||||
|
TypeInferClasses.call_method_of_a_class
|
||||||
|
TypeInferClasses.can_assign_to_prop_of_base_class
|
||||||
|
TypeInferClasses.can_assign_to_prop_of_base_class_using_string
|
||||||
|
TypeInferClasses.can_read_prop_of_base_class
|
||||||
|
TypeInferClasses.can_read_prop_of_base_class_using_string
|
||||||
|
TypeInferClasses.cannot_call_method_of_child_on_base_instance
|
||||||
|
TypeInferClasses.cannot_call_unknown_method_of_a_class
|
||||||
|
TypeInferClasses.cannot_unify_class_instance_with_primitive
|
||||||
|
TypeInferClasses.class_type_mismatch_with_name_conflict
|
||||||
|
TypeInferClasses.class_unification_type_mismatch_is_correct_order
|
||||||
|
TypeInferClasses.classes_can_have_overloaded_operators
|
||||||
|
TypeInferClasses.classes_without_overloaded_operators_cannot_be_added
|
||||||
|
TypeInferClasses.detailed_class_unification_error
|
||||||
|
TypeInferClasses.function_arguments_are_covariant
|
||||||
|
TypeInferClasses.higher_order_function_arguments_are_contravariant
|
||||||
|
TypeInferClasses.higher_order_function_return_type_is_not_contravariant
|
||||||
|
TypeInferClasses.higher_order_function_return_values_are_covariant
|
||||||
|
TypeInferClasses.optional_class_field_access_error
|
||||||
|
TypeInferClasses.table_class_unification_reports_sane_errors_for_missing_properties
|
||||||
|
TypeInferClasses.table_indexers_are_invariant
|
||||||
|
TypeInferClasses.table_properties_are_invariant
|
||||||
|
TypeInferClasses.warn_when_prop_almost_matches
|
||||||
|
TypeInferClasses.we_can_infer_that_a_parameter_must_be_a_particular_class
|
||||||
|
TypeInferClasses.we_can_report_when_someone_is_trying_to_use_a_table_rather_than_a_class
|
||||||
|
TypeInferFunctions.another_indirect_function_case_where_it_is_ok_to_provide_too_many_arguments
|
||||||
|
TypeInferFunctions.another_recursive_local_function
|
||||||
|
TypeInferFunctions.cannot_hoist_interior_defns_into_signature
|
||||||
|
TypeInferFunctions.check_function_before_lambda_that_uses_it
|
||||||
|
TypeInferFunctions.complicated_return_types_require_an_explicit_annotation
|
||||||
|
TypeInferFunctions.cyclic_function_type_in_args
|
||||||
|
TypeInferFunctions.dont_give_other_overloads_message_if_only_one_argument_matching_overload_exists
|
||||||
|
TypeInferFunctions.duplicate_functions_with_different_signatures_not_allowed_in_nonstrict
|
||||||
|
TypeInferFunctions.first_argument_can_be_optional
|
||||||
|
TypeInferFunctions.func_expr_doesnt_leak_free
|
||||||
|
TypeInferFunctions.higher_order_function_2
|
||||||
|
TypeInferFunctions.higher_order_function_4
|
||||||
|
TypeInferFunctions.infer_return_type_from_selected_overload
|
||||||
|
TypeInferFunctions.infer_that_function_does_not_return_a_table
|
||||||
|
TypeInferFunctions.it_is_ok_not_to_supply_enough_retvals
|
||||||
|
TypeInferFunctions.it_is_ok_to_oversaturate_a_higher_order_function_argument
|
||||||
|
TypeInferFunctions.list_all_overloads_if_no_overload_takes_given_argument_count
|
||||||
|
TypeInferFunctions.list_only_alternative_overloads_that_match_argument_count
|
||||||
|
TypeInferFunctions.mutual_recursion
|
||||||
|
TypeInferFunctions.recursive_function
|
||||||
|
TypeInferFunctions.recursive_local_function
|
||||||
|
TypeInferFunctions.too_many_arguments
|
||||||
|
TypeInferFunctions.toposort_doesnt_break_mutual_recursion
|
||||||
|
TypeInferFunctions.vararg_function_is_quantified
|
||||||
|
TypeInferFunctions.vararg_functions_should_allow_calls_of_any_types_and_size
|
@ -38,6 +38,38 @@
|
|||||||
<DisplayString Condition="typeId == 29" Optional="true">{{ typeId=29, value={*($T30*)storage} }}</DisplayString>
|
<DisplayString Condition="typeId == 29" Optional="true">{{ typeId=29, value={*($T30*)storage} }}</DisplayString>
|
||||||
<DisplayString Condition="typeId == 30" Optional="true">{{ typeId=30, value={*($T31*)storage} }}</DisplayString>
|
<DisplayString Condition="typeId == 30" Optional="true">{{ typeId=30, value={*($T31*)storage} }}</DisplayString>
|
||||||
<DisplayString Condition="typeId == 31" Optional="true">{{ typeId=31, value={*($T32*)storage} }}</DisplayString>
|
<DisplayString Condition="typeId == 31" Optional="true">{{ typeId=31, value={*($T32*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 32" Optional="true">{{ typeId=32, value={*($T33*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 33" Optional="true">{{ typeId=33, value={*($T34*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 34" Optional="true">{{ typeId=34, value={*($T35*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 35" Optional="true">{{ typeId=35, value={*($T36*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 36" Optional="true">{{ typeId=36, value={*($T37*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 37" Optional="true">{{ typeId=37, value={*($T38*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 38" Optional="true">{{ typeId=38, value={*($T39*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 39" Optional="true">{{ typeId=39, value={*($T40*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 40" Optional="true">{{ typeId=40, value={*($T41*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 41" Optional="true">{{ typeId=41, value={*($T42*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 42" Optional="true">{{ typeId=42, value={*($T43*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 43" Optional="true">{{ typeId=43, value={*($T44*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 44" Optional="true">{{ typeId=44, value={*($T45*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 45" Optional="true">{{ typeId=45, value={*($T46*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 46" Optional="true">{{ typeId=46, value={*($T47*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 47" Optional="true">{{ typeId=47, value={*($T48*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 48" Optional="true">{{ typeId=48, value={*($T49*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 49" Optional="true">{{ typeId=49, value={*($T50*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 50" Optional="true">{{ typeId=50, value={*($T51*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 51" Optional="true">{{ typeId=51, value={*($T52*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 52" Optional="true">{{ typeId=52, value={*($T53*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 53" Optional="true">{{ typeId=53, value={*($T54*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 54" Optional="true">{{ typeId=54, value={*($T55*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 55" Optional="true">{{ typeId=55, value={*($T56*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 56" Optional="true">{{ typeId=56, value={*($T57*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 57" Optional="true">{{ typeId=57, value={*($T58*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 58" Optional="true">{{ typeId=58, value={*($T59*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 59" Optional="true">{{ typeId=59, value={*($T60*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 60" Optional="true">{{ typeId=60, value={*($T61*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 61" Optional="true">{{ typeId=61, value={*($T62*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 62" Optional="true">{{ typeId=62, value={*($T63*)storage} }}</DisplayString>
|
||||||
|
<DisplayString Condition="typeId == 63" Optional="true">{{ typeId=63, value={*($T64*)storage} }}</DisplayString>
|
||||||
<Expand>
|
<Expand>
|
||||||
<Item Name="typeId">typeId</Item>
|
<Item Name="typeId">typeId</Item>
|
||||||
<Item Name="[value]" Condition="typeId == 0" Optional="true">*($T1*)storage</Item>
|
<Item Name="[value]" Condition="typeId == 0" Optional="true">*($T1*)storage</Item>
|
||||||
@ -72,6 +104,38 @@
|
|||||||
<Item Name="[value]" Condition="typeId == 29" Optional="true">*($T30*)storage</Item>
|
<Item Name="[value]" Condition="typeId == 29" Optional="true">*($T30*)storage</Item>
|
||||||
<Item Name="[value]" Condition="typeId == 30" Optional="true">*($T31*)storage</Item>
|
<Item Name="[value]" Condition="typeId == 30" Optional="true">*($T31*)storage</Item>
|
||||||
<Item Name="[value]" Condition="typeId == 31" Optional="true">*($T32*)storage</Item>
|
<Item Name="[value]" Condition="typeId == 31" Optional="true">*($T32*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 32" Optional="true">*($T33*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 33" Optional="true">*($T34*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 34" Optional="true">*($T35*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 35" Optional="true">*($T36*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 36" Optional="true">*($T37*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 37" Optional="true">*($T38*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 38" Optional="true">*($T39*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 39" Optional="true">*($T40*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 40" Optional="true">*($T41*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 41" Optional="true">*($T42*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 42" Optional="true">*($T43*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 43" Optional="true">*($T44*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 44" Optional="true">*($T45*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 45" Optional="true">*($T46*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 46" Optional="true">*($T47*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 47" Optional="true">*($T48*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 48" Optional="true">*($T49*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 49" Optional="true">*($T50*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 50" Optional="true">*($T51*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 51" Optional="true">*($T52*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 52" Optional="true">*($T53*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 53" Optional="true">*($T54*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 54" Optional="true">*($T55*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 55" Optional="true">*($T56*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 56" Optional="true">*($T57*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 57" Optional="true">*($T58*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 58" Optional="true">*($T59*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 59" Optional="true">*($T60*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 60" Optional="true">*($T61*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 61" Optional="true">*($T62*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 62" Optional="true">*($T63*)storage</Item>
|
||||||
|
<Item Name="[value]" Condition="typeId == 63" Optional="true">*($T64*)storage</Item>
|
||||||
</Expand>
|
</Expand>
|
||||||
</Type>
|
</Type>
|
||||||
|
|
||||||
|
124
tools/test_dcr.py
Normal file
124
tools/test_dcr.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os.path
|
||||||
|
import subprocess as sp
|
||||||
|
import sys
|
||||||
|
import xml.sax as x
|
||||||
|
|
||||||
|
SCRIPT_PATH = os.path.split(sys.argv[0])[0]
|
||||||
|
FAIL_LIST_PATH = os.path.join(SCRIPT_PATH, "faillist.txt")
|
||||||
|
|
||||||
|
|
||||||
|
def loadFailList():
|
||||||
|
with open(FAIL_LIST_PATH) as f:
|
||||||
|
return set(map(str.strip, f.readlines()))
|
||||||
|
|
||||||
|
|
||||||
|
class Handler(x.ContentHandler):
|
||||||
|
def __init__(self, failList):
|
||||||
|
self.currentTest = []
|
||||||
|
self.failList = failList # Set of dotted test names that are expected to fail
|
||||||
|
|
||||||
|
self.results = {} # {DottedName: TrueIfTheTestPassed}
|
||||||
|
|
||||||
|
def startElement(self, name, attrs):
|
||||||
|
if name == "TestSuite":
|
||||||
|
self.currentTest.append(attrs["name"])
|
||||||
|
elif name == "TestCase":
|
||||||
|
self.currentTest.append(attrs["name"])
|
||||||
|
|
||||||
|
elif name == "OverallResultsAsserts":
|
||||||
|
if self.currentTest:
|
||||||
|
try:
|
||||||
|
failed = 0 != int(attrs["failures"])
|
||||||
|
except ValueError:
|
||||||
|
failed = False
|
||||||
|
|
||||||
|
dottedName = ".".join(self.currentTest)
|
||||||
|
shouldFail = dottedName in self.failList
|
||||||
|
|
||||||
|
if failed and not shouldFail:
|
||||||
|
print("UNEXPECTED: {} should have passed".format(dottedName))
|
||||||
|
elif not failed and shouldFail:
|
||||||
|
print("UNEXPECTED: {} should have failed".format(dottedName))
|
||||||
|
|
||||||
|
self.results[dottedName] = not failed
|
||||||
|
|
||||||
|
def endElement(self, name):
|
||||||
|
if name == "TestCase":
|
||||||
|
self.currentTest.pop()
|
||||||
|
|
||||||
|
elif name == "TestSuite":
|
||||||
|
self.currentTest.pop()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Run Luau.UnitTest with deferred constraint resolution enabled"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"path", action="store", help="Path to the Luau.UnitTest executable"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--dump",
|
||||||
|
dest="dump",
|
||||||
|
action="store_true",
|
||||||
|
help="Instead of doing any processing, dump the raw output of the test run. Useful for debugging this tool.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--write",
|
||||||
|
dest="write",
|
||||||
|
action="store_true",
|
||||||
|
help="Write a new faillist.txt after running tests.",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
failList = loadFailList()
|
||||||
|
|
||||||
|
p = sp.Popen(
|
||||||
|
[
|
||||||
|
args.path,
|
||||||
|
"--reporters=xml",
|
||||||
|
"--fflags=true,DebugLuauDeferredConstraintResolution=true",
|
||||||
|
],
|
||||||
|
stdout=sp.PIPE,
|
||||||
|
)
|
||||||
|
|
||||||
|
handler = Handler(failList)
|
||||||
|
|
||||||
|
if args.dump:
|
||||||
|
for line in p.stdout:
|
||||||
|
sys.stdout.buffer.write(line)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
x.parse(p.stdout, handler)
|
||||||
|
|
||||||
|
p.wait()
|
||||||
|
|
||||||
|
if args.write:
|
||||||
|
newFailList = sorted(
|
||||||
|
(
|
||||||
|
dottedName
|
||||||
|
for dottedName, passed in handler.results.items()
|
||||||
|
if not passed
|
||||||
|
),
|
||||||
|
key=str.lower,
|
||||||
|
)
|
||||||
|
with open(FAIL_LIST_PATH, "w", newline="\n") as f:
|
||||||
|
for name in newFailList:
|
||||||
|
print(name, file=f)
|
||||||
|
print("Updated faillist.txt")
|
||||||
|
|
||||||
|
sys.exit(
|
||||||
|
0
|
||||||
|
if all(
|
||||||
|
not passed == (dottedName in failList)
|
||||||
|
for dottedName, passed in handler.results.items()
|
||||||
|
)
|
||||||
|
else 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user