Skip to content

Commit

Permalink
Sync to upstream/release/506 (#270)
Browse files Browse the repository at this point in the history
- Fix some cases where type checking would overflow the native stack
- Improve autocomplete behavior when assigning a partially written function call (not currently exposed through command line tools)
- Improve autocomplete type inference feedback for some expressions where previously the type would not be known
- Improve quantification performance during type checking for large types
- Improve type checking for table literals when the expected type of the table is known because of a type annotation
- Fix type checking errors in cases where required module has errors in the resulting type
- Fix debug line information for multi-line chained call sequences (Add function name information for "attempt to call a nil value" #255)
- lua_newuserdata now takes 2 arguments to match Lua/LuaJIT APIs better; lua_newuserdatatagged should be used if the third argument was non-0.
- lua_ref can no longer be used with LUA_REGISTRYINDEX to prevent mistakes when migrating Lua FFI (Inconsistency with lua_ref #247)
- Fix assertions and possible crashes when executing script code indirectly via metatable dispatch from lua_equal/lua_lessthan/lua_getfield/etc. (Hitting a crash in an assert after lua_equal is called. #259)
- Fix flamegraph scripts to run under Python 2
  • Loading branch information
zeux authored Dec 3, 2021
1 parent f5ec6df commit 32fb6d1
Show file tree
Hide file tree
Showing 62 changed files with 2,422 additions and 2,335 deletions.
23 changes: 0 additions & 23 deletions Analysis/include/Luau/FileResolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,6 @@ struct FileResolver
{
return std::nullopt;
}

// DEPRECATED APIS
// These are going to be removed with LuauNewRequireTrace2
virtual bool moduleExists(const ModuleName& name) const = 0;
virtual std::optional<ModuleName> fromAstFragment(AstExpr* expr) const = 0;
virtual ModuleName concat(const ModuleName& lhs, std::string_view rhs) const = 0;
virtual std::optional<ModuleName> getParentModuleName(const ModuleName& name) const = 0;
};

struct NullFileResolver : FileResolver
Expand All @@ -66,22 +59,6 @@ struct NullFileResolver : FileResolver
{
return std::nullopt;
}
bool moduleExists(const ModuleName& name) const override
{
return false;
}
std::optional<ModuleName> fromAstFragment(AstExpr* expr) const override
{
return std::nullopt;
}
ModuleName concat(const ModuleName& lhs, std::string_view rhs) const override
{
return lhs;
}
std::optional<ModuleName> getParentModuleName(const ModuleName& name) const override
{
return std::nullopt;
}
};

} // namespace Luau
12 changes: 9 additions & 3 deletions Analysis/include/Luau/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,15 @@ void unfreeze(TypeArena& arena);
using SeenTypes = std::unordered_map<TypeId, TypeId>;
using SeenTypePacks = std::unordered_map<TypePackId, TypePackId>;

TypePackId clone(TypePackId tp, TypeArena& dest, SeenTypes& seenTypes, SeenTypePacks& seenTypePacks, bool* encounteredFreeType = nullptr);
TypeId clone(TypeId tp, TypeArena& dest, SeenTypes& seenTypes, SeenTypePacks& seenTypePacks, bool* encounteredFreeType = nullptr);
TypeFun clone(const TypeFun& typeFun, TypeArena& dest, SeenTypes& seenTypes, SeenTypePacks& seenTypePacks, bool* encounteredFreeType = nullptr);
struct CloneState
{
int recursionCount = 0;
bool encounteredFreeType = false;
};

TypePackId clone(TypePackId tp, TypeArena& dest, SeenTypes& seenTypes, SeenTypePacks& seenTypePacks, CloneState& cloneState);
TypeId clone(TypeId tp, TypeArena& dest, SeenTypes& seenTypes, SeenTypePacks& seenTypePacks, CloneState& cloneState);
TypeFun clone(const TypeFun& typeFun, TypeArena& dest, SeenTypes& seenTypes, SeenTypePacks& seenTypePacks, CloneState& cloneState);

struct Module
{
Expand Down
31 changes: 31 additions & 0 deletions Analysis/include/Luau/ToDot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once

#include "Luau/Common.h"

#include <string>

namespace Luau
{
struct TypeVar;
using TypeId = const TypeVar*;

struct TypePackVar;
using TypePackId = const TypePackVar*;

struct ToDotOptions
{
bool showPointers = true; // Show pointer value in the node label
bool duplicatePrimitives = true; // Display primitive types and 'any' as separate nodes
};

std::string toDot(TypeId ty, const ToDotOptions& opts);
std::string toDot(TypePackId tp, const ToDotOptions& opts);

std::string toDot(TypeId ty);
std::string toDot(TypePackId tp);

void dumpDot(TypeId ty);
void dumpDot(TypePackId tp);

} // namespace Luau
9 changes: 0 additions & 9 deletions Analysis/include/Luau/TxnLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,6 @@ struct TxnLog
{
}

explicit TxnLog(const std::vector<std::pair<TypeId, TypeId>>& ownedSeen)
: originalSeenSize(ownedSeen.size())
, ownedSeen(ownedSeen)
, sharedSeen(nullptr)
{
// This is deprecated!
LUAU_ASSERT(!FFlag::LuauShareTxnSeen);
}

TxnLog(const TxnLog&) = delete;
TxnLog& operator=(const TxnLog&) = delete;

Expand Down
1 change: 0 additions & 1 deletion Analysis/include/Luau/TypeInfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ struct TypeChecker

private:
Unifier mkUnifier(const Location& location);
Unifier mkUnifier(const std::vector<std::pair<TypeId, TypeId>>& seen, const Location& location);

// These functions are only safe to call when we are in the process of typechecking a module.

Expand Down
15 changes: 0 additions & 15 deletions Analysis/include/Luau/TypeVar.h
Original file line number Diff line number Diff line change
Expand Up @@ -517,21 +517,6 @@ extern SingletonTypes singletonTypes;
void persist(TypeId ty);
void persist(TypePackId tp);

struct ToDotOptions
{
bool showPointers = true; // Show pointer value in the node label
bool duplicatePrimitives = true; // Display primitive types and 'any' as separate nodes
};

std::string toDot(TypeId ty, const ToDotOptions& opts);
std::string toDot(TypePackId tp, const ToDotOptions& opts);

std::string toDot(TypeId ty);
std::string toDot(TypePackId tp);

void dumpDot(TypeId ty);
void dumpDot(TypePackId tp);

const TypeLevel* getLevel(TypeId ty);
TypeLevel* getMutableLevel(TypeId ty);

Expand Down
25 changes: 3 additions & 22 deletions Analysis/include/Luau/Unifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ enum Variance
Invariant
};

struct UnifierCounters
{
int recursionCount = 0;
int iterationCount = 0;
};

struct Unifier
{
TypeArena* const types;
Expand All @@ -37,20 +31,11 @@ struct Unifier
Variance variance = Covariant;
CountMismatch::Context ctx = CountMismatch::Arg;

UnifierCounters* counters;
UnifierCounters countersData;

std::shared_ptr<UnifierCounters> counters_DEPRECATED;

UnifierSharedState& sharedState;

Unifier(TypeArena* types, Mode mode, ScopePtr globalScope, const Location& location, Variance variance, UnifierSharedState& sharedState);
Unifier(TypeArena* types, Mode mode, ScopePtr globalScope, const std::vector<std::pair<TypeId, TypeId>>& ownedSeen, const Location& location,
Variance variance, UnifierSharedState& sharedState, const std::shared_ptr<UnifierCounters>& counters_DEPRECATED = nullptr,
UnifierCounters* counters = nullptr);
Unifier(TypeArena* types, Mode mode, ScopePtr globalScope, std::vector<std::pair<TypeId, TypeId>>* sharedSeen, const Location& location,
Variance variance, UnifierSharedState& sharedState, const std::shared_ptr<UnifierCounters>& counters_DEPRECATED = nullptr,
UnifierCounters* counters = nullptr);
Variance variance, UnifierSharedState& sharedState);

// Test whether the two type vars unify. Never commits the result.
ErrorVec canUnify(TypeId superTy, TypeId subTy);
Expand Down Expand Up @@ -92,9 +77,9 @@ struct Unifier
public:
// Report an "infinite type error" if the type "needle" already occurs within "haystack"
void occursCheck(TypeId needle, TypeId haystack);
void occursCheck(std::unordered_set<TypeId>& seen_DEPRECATED, DenseHashSet<TypeId>& seen, TypeId needle, TypeId haystack);
void occursCheck(DenseHashSet<TypeId>& seen, TypeId needle, TypeId haystack);
void occursCheck(TypePackId needle, TypePackId haystack);
void occursCheck(std::unordered_set<TypePackId>& seen_DEPRECATED, DenseHashSet<TypePackId>& seen, TypePackId needle, TypePackId haystack);
void occursCheck(DenseHashSet<TypePackId>& seen, TypePackId needle, TypePackId haystack);

Unifier makeChildUnifier();

Expand All @@ -106,10 +91,6 @@ struct Unifier

[[noreturn]] void ice(const std::string& message, const Location& location);
[[noreturn]] void ice(const std::string& message);

// Remove with FFlagLuauCacheUnifyTableResults
DenseHashSet<TypeId> tempSeenTy_DEPRECATED{nullptr};
DenseHashSet<TypePackId> tempSeenTp_DEPRECATED{nullptr};
};

} // namespace Luau
8 changes: 8 additions & 0 deletions Analysis/include/Luau/UnifierSharedState.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ struct TypeIdPairHash
}
};

struct UnifierCounters
{
int recursionCount = 0;
int iterationCount = 0;
};

struct UnifierSharedState
{
UnifierSharedState(InternalErrorReporter* iceHandler)
Expand All @@ -39,6 +45,8 @@ struct UnifierSharedState

DenseHashSet<TypeId> tempSeenTy{nullptr};
DenseHashSet<TypePackId> tempSeenTp{nullptr};

UnifierCounters counters;
};

} // namespace Luau
4 changes: 1 addition & 3 deletions Analysis/include/Luau/VisitTypeVar.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
#include "Luau/TypeVar.h"
#include "Luau/TypePack.h"

LUAU_FASTFLAG(LuauCacheUnifyTableResults)

namespace Luau
{

Expand Down Expand Up @@ -101,7 +99,7 @@ void visit(TypeId ty, F& f, Set& seen)
// Some visitors want to see bound tables, that's why we visit the original type
if (apply(ty, *ttv, seen, f))
{
if (FFlag::LuauCacheUnifyTableResults && ttv->boundTo)
if (ttv->boundTo)
{
visit(*ttv->boundTo, f, seen);
}
Expand Down
64 changes: 44 additions & 20 deletions Analysis/src/Autocomplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
#include <unordered_set>
#include <utility>

LUAU_FASTFLAGVARIABLE(ElseElseIfCompletionImprovements, false);
LUAU_FASTFLAG(LuauIfElseExpressionAnalysisSupport)
LUAU_FASTFLAGVARIABLE(LuauAutocompleteAvoidMutation, false);
LUAU_FASTFLAGVARIABLE(LuauAutocompletePreferToCallFunctions, false);

static const std::unordered_set<std::string> kStatementStartingKeywords = {
"while", "if", "local", "repeat", "function", "do", "for", "return", "break", "continue", "type", "export"};
Expand Down Expand Up @@ -203,8 +203,9 @@ static TypeCorrectKind checkTypeCorrectKind(const Module& module, TypeArena* typ
{
SeenTypes seenTypes;
SeenTypePacks seenTypePacks;
expectedType = clone(expectedType, *typeArena, seenTypes, seenTypePacks, nullptr);
actualType = clone(actualType, *typeArena, seenTypes, seenTypePacks, nullptr);
CloneState cloneState;
expectedType = clone(expectedType, *typeArena, seenTypes, seenTypePacks, cloneState);
actualType = clone(actualType, *typeArena, seenTypes, seenTypePacks, cloneState);

auto errors = unifier.canUnify(expectedType, actualType);
return errors.empty();
Expand All @@ -229,28 +230,51 @@ static TypeCorrectKind checkTypeCorrectKind(const Module& module, TypeArena* typ

TypeId expectedType = follow(*it);

if (canUnify(expectedType, ty))
return TypeCorrectKind::Correct;
if (FFlag::LuauAutocompletePreferToCallFunctions)
{
// We also want to suggest functions that return compatible result
if (const FunctionTypeVar* ftv = get<FunctionTypeVar>(ty))
{
auto [retHead, retTail] = flatten(ftv->retType);

// We also want to suggest functions that return compatible result
const FunctionTypeVar* ftv = get<FunctionTypeVar>(ty);
if (!retHead.empty() && canUnify(expectedType, retHead.front()))
return TypeCorrectKind::CorrectFunctionResult;

if (!ftv)
return TypeCorrectKind::None;
// We might only have a variadic tail pack, check if the element is compatible
if (retTail)
{
if (const VariadicTypePack* vtp = get<VariadicTypePack>(follow(*retTail)); vtp && canUnify(expectedType, vtp->ty))
return TypeCorrectKind::CorrectFunctionResult;
}
}

return canUnify(expectedType, ty) ? TypeCorrectKind::Correct : TypeCorrectKind::None;
}
else
{
if (canUnify(expectedType, ty))
return TypeCorrectKind::Correct;

auto [retHead, retTail] = flatten(ftv->retType);
// We also want to suggest functions that return compatible result
const FunctionTypeVar* ftv = get<FunctionTypeVar>(ty);

if (!retHead.empty())
return canUnify(expectedType, retHead.front()) ? TypeCorrectKind::CorrectFunctionResult : TypeCorrectKind::None;
if (!ftv)
return TypeCorrectKind::None;

// We might only have a variadic tail pack, check if the element is compatible
if (retTail)
{
if (const VariadicTypePack* vtp = get<VariadicTypePack>(follow(*retTail)))
return canUnify(expectedType, vtp->ty) ? TypeCorrectKind::CorrectFunctionResult : TypeCorrectKind::None;
}
auto [retHead, retTail] = flatten(ftv->retType);

if (!retHead.empty())
return canUnify(expectedType, retHead.front()) ? TypeCorrectKind::CorrectFunctionResult : TypeCorrectKind::None;

return TypeCorrectKind::None;
// We might only have a variadic tail pack, check if the element is compatible
if (retTail)
{
if (const VariadicTypePack* vtp = get<VariadicTypePack>(follow(*retTail)))
return canUnify(expectedType, vtp->ty) ? TypeCorrectKind::CorrectFunctionResult : TypeCorrectKind::None;
}

return TypeCorrectKind::None;
}
}

enum class PropIndexType
Expand Down Expand Up @@ -1413,7 +1437,7 @@ static AutocompleteResult autocomplete(const SourceModule& sourceModule, const M
else if (AstStatWhile* statWhile = extractStat<AstStatWhile>(finder.ancestry); statWhile && !statWhile->hasDo)
return {{{"do", AutocompleteEntry{AutocompleteEntryKind::Keyword}}}, finder.ancestry};

else if (AstStatIf* statIf = node->as<AstStatIf>(); FFlag::ElseElseIfCompletionImprovements && statIf && !statIf->hasElse)
else if (AstStatIf* statIf = node->as<AstStatIf>(); statIf && !statIf->hasElse)
{
return {{{"else", AutocompleteEntry{AutocompleteEntryKind::Keyword}}, {"elseif", AutocompleteEntry{AutocompleteEntryKind::Keyword}}},
finder.ancestry};
Expand Down
6 changes: 1 addition & 5 deletions Analysis/src/BuiltinDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@

#include <algorithm>

LUAU_FASTFLAG(LuauNewRequireTrace2)

/** FIXME: Many of these type definitions are not quite completely accurate.
*
* Some of them require richer generics than we have. For instance, we do not yet have a way to talk
Expand Down Expand Up @@ -473,9 +471,7 @@ static std::optional<ExprResult<TypePackId>> magicFunctionRequire(
if (!checkRequirePath(typechecker, expr.args.data[0]))
return std::nullopt;

const AstExpr* require = FFlag::LuauNewRequireTrace2 ? &expr : expr.args.data[0];

if (auto moduleInfo = typechecker.resolver->resolveModuleInfo(typechecker.currentModuleName, *require))
if (auto moduleInfo = typechecker.resolver->resolveModuleInfo(typechecker.currentModuleName, expr))
return ExprResult<TypePackId>{arena.addTypePack({typechecker.checkRequire(scope, *moduleInfo, expr.location)})};

return std::nullopt;
Expand Down
Loading

0 comments on commit 32fb6d1

Please sign in to comment.