Skip to content

Commit

Permalink
Sync to upstream/release/520 (#427)
Browse files Browse the repository at this point in the history
  • Loading branch information
zeux committed Mar 24, 2022
1 parent 5e7e462 commit 2c339d5
Show file tree
Hide file tree
Showing 37 changed files with 797 additions and 555 deletions.
1 change: 1 addition & 0 deletions Analysis/include/Luau/Error.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ struct CountMismatch
size_t expected;
size_t actual;
Context context = Arg;
bool isVariadic = false;

bool operator==(const CountMismatch& rhs) const;
};
Expand Down
3 changes: 2 additions & 1 deletion Analysis/include/Luau/ToString.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct ToStringOptions
size_t maxTypeLength = size_t(FInt::LuauTypeMaximumStringifierLength);
std::optional<ToStringNameMap> nameMap;
std::shared_ptr<Scope> scope; // If present, module names will be added and types that are not available in scope will be marked as 'invalid'
std::vector<std::string> namedFunctionOverrideArgNames; // If present, named function argument names will be overridden
};

struct ToStringResult
Expand Down Expand Up @@ -65,7 +66,7 @@ inline std::string toString(TypePackId ty)
std::string toString(const TypeVar& tv, const ToStringOptions& opts = {});
std::string toString(const TypePackVar& tp, const ToStringOptions& opts = {});

std::string toStringNamedFunction(const std::string& prefix, const FunctionTypeVar& ftv, ToStringOptions opts = {});
std::string toStringNamedFunction(const std::string& funcName, const FunctionTypeVar& ftv, const ToStringOptions& opts = {});

// It could be useful to see the text representation of a type during a debugging session instead of exploring the content of the class
// These functions will dump the type to stdout and can be evaluated in Watch/Immediate windows or as gdb/lldb expression
Expand Down
6 changes: 3 additions & 3 deletions Analysis/include/Luau/TypePack.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ bool areEqual(SeenSet& seen, const TypePackVar& lhs, const TypePackVar& rhs);
TypePackId follow(TypePackId tp);
TypePackId follow(TypePackId tp, std::function<TypePackId(TypePackId)> mapper);

size_t size(TypePackId tp);
bool finite(TypePackId tp);
size_t size(const TypePack& tp);
size_t size(TypePackId tp, TxnLog* log = nullptr);
bool finite(TypePackId tp, TxnLog* log = nullptr);
size_t size(const TypePack& tp, TxnLog* log = nullptr);
std::optional<TypeId> first(TypePackId tp);

TypePackVar* asMutable(TypePackId tp);
Expand Down
3 changes: 3 additions & 0 deletions Analysis/include/Luau/TypeVar.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,9 @@ const TableTypeVar* getTableType(TypeId type);
// Returns nullptr if the type has no name.
const std::string* getName(TypeId type);

// Returns name of the module where type was defined if type has that information
std::optional<ModuleName> getDefinitionModuleName(TypeId type);

// Checks whether a union contains all types of another union.
bool isSubset(const UnionTypeVar& super, const UnionTypeVar& sub);

Expand Down
4 changes: 3 additions & 1 deletion Analysis/include/Luau/Unifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ struct Unifier

TypeId deeplyOptional(TypeId ty, std::unordered_map<TypeId, TypeId> seen = {});

void cacheResult(TypeId subTy, TypeId superTy);
bool canCacheResult(TypeId subTy, TypeId superTy);
void cacheResult(TypeId subTy, TypeId superTy, size_t prevErrorCount);
void cacheResult_DEPRECATED(TypeId subTy, TypeId superTy);

public:
void tryUnify(TypePackId subTy, TypePackId superTy, bool isFunctionCall = false);
Expand Down
2 changes: 2 additions & 0 deletions Analysis/include/Luau/UnifierSharedState.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#pragma once

#include "Luau/DenseHash.h"
#include "Luau/Error.h"
#include "Luau/TypeVar.h"
#include "Luau/TypePack.h"

Expand Down Expand Up @@ -42,6 +43,7 @@ struct UnifierSharedState
DenseHashSet<void*> seenAny{nullptr};
DenseHashMap<TypeId, bool> skipCacheForType{nullptr};
DenseHashSet<std::pair<TypeId, TypeId>, TypeIdPairHash> cachedUnify{{nullptr, nullptr}};
DenseHashMap<std::pair<TypeId, TypeId>, TypeErrorData, TypeIdPairHash> cachedUnifyError{{nullptr, nullptr}};

DenseHashSet<TypeId> tempSeenTy{nullptr};
DenseHashSet<TypePackId> tempSeenTp{nullptr};
Expand Down
30 changes: 28 additions & 2 deletions Analysis/src/Error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <stdexcept>

LUAU_FASTFLAGVARIABLE(BetterDiagnosticCodesInStudio, false);
LUAU_FASTFLAGVARIABLE(LuauTypeMismatchModuleName, false);

static std::string wrongNumberOfArgsString(size_t expectedCount, size_t actualCount, const char* argPrefix = nullptr, bool isVariadic = false)
{
Expand Down Expand Up @@ -53,7 +54,32 @@ struct ErrorConverter
{
std::string operator()(const Luau::TypeMismatch& tm) const
{
std::string result = "Type '" + Luau::toString(tm.givenType) + "' could not be converted into '" + Luau::toString(tm.wantedType) + "'";
std::string givenTypeName = Luau::toString(tm.givenType);
std::string wantedTypeName = Luau::toString(tm.wantedType);

std::string result;

if (FFlag::LuauTypeMismatchModuleName)
{
if (givenTypeName == wantedTypeName)
{
if (auto givenDefinitionModule = getDefinitionModuleName(tm.givenType))
{
if (auto wantedDefinitionModule = getDefinitionModuleName(tm.wantedType))
{
result = "Type '" + givenTypeName + "' from '" + *givenDefinitionModule + "' could not be converted into '" + wantedTypeName +
"' from '" + *wantedDefinitionModule + "'";
}
}
}

if (result.empty())
result = "Type '" + givenTypeName + "' could not be converted into '" + wantedTypeName + "'";
}
else
{
result = "Type '" + givenTypeName + "' could not be converted into '" + wantedTypeName + "'";
}

if (tm.error)
{
Expand Down Expand Up @@ -147,7 +173,7 @@ struct ErrorConverter
return "Function only returns " + std::to_string(e.expected) + " value" + expectedS + ". " + std::to_string(e.actual) +
" are required here";
case CountMismatch::Arg:
return "Argument count mismatch. Function " + wrongNumberOfArgsString(e.expected, e.actual);
return "Argument count mismatch. Function " + wrongNumberOfArgsString(e.expected, e.actual, /*argPrefix*/ nullptr, e.isVariadic);
}

LUAU_ASSERT(!"Unknown context");
Expand Down
43 changes: 32 additions & 11 deletions Analysis/src/Linter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

LUAU_FASTINTVARIABLE(LuauSuggestionDistance, 4)
LUAU_FASTFLAGVARIABLE(LuauLintGlobalNeverReadBeforeWritten, false)
LUAU_FASTFLAGVARIABLE(LuauLintNoRobloxBits, false)

namespace Luau
{
Expand Down Expand Up @@ -1135,16 +1136,20 @@ class LintUnknownType : AstVisitor

enum TypeKind
{
Kind_Invalid,
Kind_Unknown,
Kind_Primitive, // primitive type supported by VM - boolean/userdata/etc. No differentiation between types of userdata.
Kind_Vector, // For 'vector' but only used when type is used
Kind_Userdata, // custom userdata type - Vector3/etc.
Kind_Vector, // 'vector' but only used when type is used
Kind_Userdata, // custom userdata type

// TODO: remove these with LuauLintNoRobloxBits
Kind_Class, // custom userdata type that reflects Roblox Instance-derived hierarchy - Part/etc.
Kind_Enum, // custom userdata type referring to an enum item of enum classes, e.g. Enum.NormalId.Back/Enum.Axis.X/etc.
};

bool containsPropName(TypeId ty, const std::string& propName)
{
LUAU_ASSERT(!FFlag::LuauLintNoRobloxBits);

if (auto ctv = get<ClassTypeVar>(ty))
return lookupClassProp(ctv, propName) != nullptr;

Expand All @@ -1163,21 +1168,31 @@ class LintUnknownType : AstVisitor
if (name == "vector")
return Kind_Vector;

if (std::optional<TypeFun> maybeTy = context->scope->lookupType(name))
// Kind_Userdata is probably not 100% precise but is close enough
return containsPropName(maybeTy->type, "ClassName") ? Kind_Class : Kind_Userdata;
else if (std::optional<TypeFun> maybeTy = context->scope->lookupImportedType("Enum", name))
return Kind_Enum;
if (FFlag::LuauLintNoRobloxBits)
{
if (std::optional<TypeFun> maybeTy = context->scope->lookupType(name))
return Kind_Userdata;

return Kind_Invalid;
return Kind_Unknown;
}
else
{
if (std::optional<TypeFun> maybeTy = context->scope->lookupType(name))
// Kind_Userdata is probably not 100% precise but is close enough
return containsPropName(maybeTy->type, "ClassName") ? Kind_Class : Kind_Userdata;
else if (std::optional<TypeFun> maybeTy = context->scope->lookupImportedType("Enum", name))
return Kind_Enum;

return Kind_Unknown;
}
}

void validateType(AstExprConstantString* expr, std::initializer_list<TypeKind> expected, const char* expectedString)
{
std::string name(expr->value.data, expr->value.size);
TypeKind kind = getTypeKind(name);

if (kind == Kind_Invalid)
if (kind == Kind_Unknown)
{
emitWarning(*context, LintWarning::Code_UnknownType, expr->location, "Unknown type '%s'", name.c_str());
return;
Expand All @@ -1189,7 +1204,7 @@ class LintUnknownType : AstVisitor
return;

// as a special case, Instance and EnumItem are both a userdata type (as returned by typeof) and a class type
if (ek == Kind_Userdata && (name == "Instance" || name == "EnumItem"))
if (!FFlag::LuauLintNoRobloxBits && ek == Kind_Userdata && (name == "Instance" || name == "EnumItem"))
return;
}

Expand All @@ -1198,12 +1213,18 @@ class LintUnknownType : AstVisitor

bool acceptsClassName(AstName method)
{
LUAU_ASSERT(!FFlag::LuauLintNoRobloxBits);

return method.value[0] == 'F' && (method == "FindFirstChildOfClass" || method == "FindFirstChildWhichIsA" ||
method == "FindFirstAncestorOfClass" || method == "FindFirstAncestorWhichIsA");
}

bool visit(AstExprCall* node) override
{
// TODO: Simply remove the override
if (FFlag::LuauLintNoRobloxBits)
return true;

if (AstExprIndexName* index = node->func->as<AstExprIndexName>())
{
AstExprConstantString* arg0 = node->args.size > 0 ? node->args.data[0]->as<AstExprConstantString>() : NULL;
Expand Down
31 changes: 8 additions & 23 deletions Analysis/src/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@
#include <algorithm>

LUAU_FASTFLAGVARIABLE(DebugLuauFreezeArena, false)
LUAU_FASTFLAGVARIABLE(DebugLuauTrackOwningArena, false) // Remove with FFlagLuauImmutableTypes
LUAU_FASTINTVARIABLE(LuauTypeCloneRecursionLimit, 300)
LUAU_FASTFLAGVARIABLE(LuauCloneDeclaredGlobals, false)
LUAU_FASTFLAG(LuauImmutableTypes)

namespace Luau
{
Expand Down Expand Up @@ -65,8 +63,7 @@ TypeId TypeArena::addTV(TypeVar&& tv)
{
TypeId allocated = typeVars.allocate(std::move(tv));

if (FFlag::DebugLuauTrackOwningArena || FFlag::LuauImmutableTypes)
asMutable(allocated)->owningArena = this;
asMutable(allocated)->owningArena = this;

return allocated;
}
Expand All @@ -75,8 +72,7 @@ TypeId TypeArena::freshType(TypeLevel level)
{
TypeId allocated = typeVars.allocate(FreeTypeVar{level});

if (FFlag::DebugLuauTrackOwningArena || FFlag::LuauImmutableTypes)
asMutable(allocated)->owningArena = this;
asMutable(allocated)->owningArena = this;

return allocated;
}
Expand All @@ -85,8 +81,7 @@ TypePackId TypeArena::addTypePack(std::initializer_list<TypeId> types)
{
TypePackId allocated = typePacks.allocate(TypePack{std::move(types)});

if (FFlag::DebugLuauTrackOwningArena || FFlag::LuauImmutableTypes)
asMutable(allocated)->owningArena = this;
asMutable(allocated)->owningArena = this;

return allocated;
}
Expand All @@ -95,8 +90,7 @@ TypePackId TypeArena::addTypePack(std::vector<TypeId> types)
{
TypePackId allocated = typePacks.allocate(TypePack{std::move(types)});

if (FFlag::DebugLuauTrackOwningArena || FFlag::LuauImmutableTypes)
asMutable(allocated)->owningArena = this;
asMutable(allocated)->owningArena = this;

return allocated;
}
Expand All @@ -105,8 +99,7 @@ TypePackId TypeArena::addTypePack(TypePack tp)
{
TypePackId allocated = typePacks.allocate(std::move(tp));

if (FFlag::DebugLuauTrackOwningArena || FFlag::LuauImmutableTypes)
asMutable(allocated)->owningArena = this;
asMutable(allocated)->owningArena = this;

return allocated;
}
Expand All @@ -115,8 +108,7 @@ TypePackId TypeArena::addTypePack(TypePackVar tp)
{
TypePackId allocated = typePacks.allocate(std::move(tp));

if (FFlag::DebugLuauTrackOwningArena || FFlag::LuauImmutableTypes)
asMutable(allocated)->owningArena = this;
asMutable(allocated)->owningArena = this;

return allocated;
}
Expand Down Expand Up @@ -439,16 +431,9 @@ TypeId clone(TypeId typeId, TypeArena& dest, SeenTypes& seenTypes, SeenTypePacks
TypeCloner cloner{dest, typeId, seenTypes, seenTypePacks, cloneState};
Luau::visit(cloner, typeId->ty); // Mutates the storage that 'res' points into.

if (FFlag::LuauImmutableTypes)
{
// Persistent types are not being cloned and we get the original type back which might be read-only
if (!res->persistent)
asMutable(res)->documentationSymbol = typeId->documentationSymbol;
}
else
{
// Persistent types are not being cloned and we get the original type back which might be read-only
if (!res->persistent)
asMutable(res)->documentationSymbol = typeId->documentationSymbol;
}
}

return res;
Expand Down
Loading

0 comments on commit 2c339d5

Please sign in to comment.