Skip to content

Commit

Permalink
Merge branch 'upstream' into merge
Browse files Browse the repository at this point in the history
  • Loading branch information
zeux committed Feb 11, 2022
2 parents 46ba695 + e9bf182 commit a08f52a
Show file tree
Hide file tree
Showing 45 changed files with 989 additions and 268 deletions.
2 changes: 2 additions & 0 deletions Analysis/include/Luau/Autocomplete.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ struct OwningAutocompleteResult
};

AutocompleteResult autocomplete(Frontend& frontend, const ModuleName& moduleName, Position position, StringCompletionCallback callback);

// Deprecated, do not use in new work.
OwningAutocompleteResult autocompleteSource(Frontend& frontend, std::string_view source, Position position, StringCompletionCallback callback);

} // namespace Luau
1 change: 1 addition & 0 deletions Analysis/include/Luau/Linter.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ struct LintWarning
Code_DeprecatedApi = 22,
Code_TableOperations = 23,
Code_DuplicateCondition = 24,
Code_MisleadingAndOr = 25,

Code__Count
};
Expand Down
2 changes: 1 addition & 1 deletion Analysis/include/Luau/Substitution.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ struct Tarjan

// This should never be null; ensure you initialize it before calling
// substitution methods.
const TxnLog* log;
const TxnLog* log = nullptr;

std::vector<TypeId> edgesTy;
std::vector<TypePackId> edgesTp;
Expand Down
4 changes: 2 additions & 2 deletions Analysis/include/Luau/TxnLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,8 @@ struct TxnLog
//
// We can't use a DenseHashMap here because we need a non-const iterator
// over the map when we concatenate.
std::unordered_map<TypeId, std::unique_ptr<PendingType>> typeVarChanges;
std::unordered_map<TypePackId, std::unique_ptr<PendingTypePack>> typePackChanges;
std::unordered_map<TypeId, std::unique_ptr<PendingType>, DenseHashPointer> typeVarChanges;
std::unordered_map<TypePackId, std::unique_ptr<PendingTypePack>, DenseHashPointer> typePackChanges;

TxnLog* parent = nullptr;

Expand Down
11 changes: 11 additions & 0 deletions Analysis/include/Luau/TypeInfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ struct GenericTypeDefinitions
std::vector<GenericTypePackDefinition> genericPacks;
};

struct HashBoolNamePair
{
size_t operator()(const std::pair<bool, Name>& pair) const;
};

// All TypeVars are retained via Environment::typeVars. All TypeIds
// within a program are borrowed pointers into this set.
struct TypeChecker
Expand Down Expand Up @@ -411,6 +416,12 @@ struct TypeChecker
private:
int checkRecursionCount = 0;
int recursionCount = 0;

/**
* We use this to avoid doing second-pass analysis of type aliases that are duplicates. We record a pair
* (exported, name) to properly deal with the case where the two duplicates do not have the same export status.
*/
DenseHashSet<std::pair<bool, Name>, HashBoolNamePair> duplicateTypeAliases;
};

// Unit test hook
Expand Down
3 changes: 0 additions & 3 deletions Analysis/include/Luau/TypePack.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@ struct TypePackVar
bool persistent = false;

// Pointer to the type arena that allocated this type.
// Do not depend on the value of this under any circumstances. This is for
// debugging purposes only. This is only set in debug builds; it is nullptr
// in all other environments.
TypeArena* owningArena = nullptr;
};

Expand Down
3 changes: 0 additions & 3 deletions Analysis/include/Luau/TypeVar.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,9 +449,6 @@ struct TypeVar final
std::optional<std::string> documentationSymbol;

// Pointer to the type arena that allocated this type.
// Do not depend on the value of this under any circumstances. This is for
// debugging purposes only. This is only set in debug builds; it is nullptr
// in all other environments.
TypeArena* owningArena = nullptr;

bool operator==(const TypeVar& rhs) const;
Expand Down
12 changes: 2 additions & 10 deletions Analysis/src/EmbeddedBuiltinDefinitions.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#include "Luau/BuiltinDefinitions.h"

LUAU_FASTFLAGVARIABLE(LuauFixTonumberReturnType, false)

namespace Luau
{

Expand Down Expand Up @@ -115,6 +113,7 @@ declare function gcinfo(): number
declare function error<T>(message: T, level: number?)
declare function tostring<T>(value: T): string
declare function tonumber<T>(value: T, radix: number?): number?
declare function rawequal<T1, T2>(a: T1, b: T2): boolean
declare function rawget<K, V>(tab: {[K]: V}, k: K): V
Expand Down Expand Up @@ -200,14 +199,7 @@ declare function gcinfo(): number

std::string getBuiltinDefinitionSource()
{
std::string result = kBuiltinDefinitionLuaSrc;

if (FFlag::LuauFixTonumberReturnType)
result += "declare function tonumber<T>(value: T, radix: number?): number?\n";
else
result += "declare function tonumber<T>(value: T, radix: number?): number\n";

return result;
return kBuiltinDefinitionLuaSrc;
}

} // namespace Luau
103 changes: 95 additions & 8 deletions Analysis/src/Linter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ static const char* kWarningNames[] = {
"DeprecatedApi",
"TableOperations",
"DuplicateCondition",
"MisleadingAndOr",
};
// clang-format on

Expand Down Expand Up @@ -2040,18 +2041,28 @@ class LintDeprecatedApi : AstVisitor
const Property* prop = lookupClassProp(cty, node->index.value);

if (prop && prop->deprecated)
{
if (!prop->deprecatedSuggestion.empty())
emitWarning(*context, LintWarning::Code_DeprecatedApi, node->location, "Member '%s.%s' is deprecated, use '%s' instead",
cty->name.c_str(), node->index.value, prop->deprecatedSuggestion.c_str());
else
emitWarning(*context, LintWarning::Code_DeprecatedApi, node->location, "Member '%s.%s' is deprecated", cty->name.c_str(),
node->index.value);
}
report(node->location, *prop, cty->name.c_str(), node->index.value);
}
else if (const TableTypeVar* tty = get<TableTypeVar>(follow(*ty)))
{
auto prop = tty->props.find(node->index.value);

if (prop != tty->props.end() && prop->second.deprecated)
report(node->location, prop->second, tty->name ? tty->name->c_str() : nullptr, node->index.value);
}

return true;
}

void report(const Location& location, const Property& prop, const char* container, const char* field)
{
std::string suggestion = prop.deprecatedSuggestion.empty() ? "" : format(", use '%s' instead", prop.deprecatedSuggestion.c_str());

if (container)
emitWarning(*context, LintWarning::Code_DeprecatedApi, location, "Member '%s.%s' is deprecated%s", container, field, suggestion.c_str());
else
emitWarning(*context, LintWarning::Code_DeprecatedApi, location, "Member '%s' is deprecated%s", field, suggestion.c_str());
}
};

class LintTableOperations : AstVisitor
Expand Down Expand Up @@ -2257,6 +2268,39 @@ class LintDuplicateCondition : AstVisitor
return false;
}

bool visit(AstExprIfElse* expr) override
{
if (!expr->falseExpr->is<AstExprIfElse>())
return true;

// if..elseif chain detected, we need to unroll it
std::vector<AstExpr*> conditions;
conditions.reserve(2);

AstExprIfElse* head = expr;
while (head)
{
head->condition->visit(this);
head->trueExpr->visit(this);

conditions.push_back(head->condition);

if (head->falseExpr->is<AstExprIfElse>())
{
head = head->falseExpr->as<AstExprIfElse>();
continue;
}

head->falseExpr->visit(this);
break;
}

detectDuplicates(conditions);

// block recursive visits so that we only analyze each chain once
return false;
}

bool visit(AstExprBinary* expr) override
{
if (expr->op != AstExprBinary::And && expr->op != AstExprBinary::Or)
Expand Down Expand Up @@ -2418,6 +2462,46 @@ class LintDuplicateLocal : AstVisitor
}
};

class LintMisleadingAndOr : AstVisitor
{
public:
LUAU_NOINLINE static void process(LintContext& context)
{
LintMisleadingAndOr pass;
pass.context = &context;

context.root->visit(&pass);
}

private:
LintContext* context;

bool visit(AstExprBinary* node) override
{
if (node->op != AstExprBinary::Or)
return true;

AstExprBinary* and_ = node->left->as<AstExprBinary>();
if (!and_ || and_->op != AstExprBinary::And)
return true;

const char* alt = nullptr;

if (and_->right->is<AstExprConstantNil>())
alt = "nil";
else if (AstExprConstantBool* c = and_->right->as<AstExprConstantBool>(); c && c->value == false)
alt = "false";

if (alt)
emitWarning(*context, LintWarning::Code_MisleadingAndOr, node->location,
"The and-or expression always evaluates to the second alternative because the first alternative is %s; consider using if-then-else "
"expression instead",
alt);

return true;
}
};

static void fillBuiltinGlobals(LintContext& context, const AstNameTable& names, const ScopePtr& env)
{
ScopePtr current = env;
Expand Down Expand Up @@ -2522,6 +2606,9 @@ std::vector<LintWarning> lint(AstStat* root, const AstNameTable& names, const Sc
if (context.warningEnabled(LintWarning::Code_DuplicateLocal))
LintDuplicateLocal::process(context);

if (context.warningEnabled(LintWarning::Code_MisleadingAndOr))
LintMisleadingAndOr::process(context);

std::sort(context.result.begin(), context.result.end(), WarningComparator());

return context.result;
Expand Down
28 changes: 18 additions & 10 deletions Analysis/src/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
#include <algorithm>

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

LUAU_FASTFLAG(LuauImmutableTypes)
LUAU_FASTFLAGVARIABLE(LuauPrepopulateUnionOptionsBeforeAllocation, false)

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

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

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

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

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

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

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

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

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

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

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

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

return allocated;
Expand Down Expand Up @@ -454,8 +454,16 @@ 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.

// TODO: Make this work when the arena of 'res' might be frozen
asMutable(res)->documentationSymbol = typeId->documentationSymbol;
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
{
asMutable(res)->documentationSymbol = typeId->documentationSymbol;
}
}

return res;
Expand Down
4 changes: 4 additions & 0 deletions Analysis/src/Scope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "Luau/Scope.h"

LUAU_FASTFLAG(LuauTwoPassAliasDefinitionFix);

namespace Luau
{

Expand All @@ -17,6 +19,8 @@ Scope::Scope(const ScopePtr& parent, int subLevel)
, returnType(parent->returnType)
, level(parent->level.incr())
{
if (FFlag::LuauTwoPassAliasDefinitionFix)
level = level.incr();
level.subLevel = subLevel;
}

Expand Down
8 changes: 8 additions & 0 deletions Analysis/src/TxnLog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,10 @@ PendingTypePack* TxnLog::queue(TypePackId tp)

PendingType* TxnLog::pending(TypeId ty) const
{
// This function will technically work if `this` is nullptr, but this
// indicates a bug, so we explicitly assert.
LUAU_ASSERT(static_cast<const void*>(this) != nullptr);

for (const TxnLog* current = this; current; current = current->parent)
{
if (auto it = current->typeVarChanges.find(ty); it != current->typeVarChanges.end())
Expand All @@ -261,6 +265,10 @@ PendingType* TxnLog::pending(TypeId ty) const

PendingTypePack* TxnLog::pending(TypePackId tp) const
{
// This function will technically work if `this` is nullptr, but this
// indicates a bug, so we explicitly assert.
LUAU_ASSERT(static_cast<const void*>(this) != nullptr);

for (const TxnLog* current = this; current; current = current->parent)
{
if (auto it = current->typePackChanges.find(tp); it != current->typePackChanges.end())
Expand Down
Loading

0 comments on commit a08f52a

Please sign in to comment.