Skip to content

Commit

Permalink
Sync to upstream/release/571 (#895)
Browse files Browse the repository at this point in the history
* `table.sort` was improved further. It now guarentees N*log(N) time
complexity in the worst case.
* Fix #880

We are also working on fixing final bugs and crashes in the new type
solver.

On the CodeGen front we have a few things going on:
* We have a smarter register allocator for the x86 JIT
* We lower more instructions on arm64
* The vector constructor builtin is now translated to IR

---------

Co-authored-by: Arseny Kapoulkine <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>
  • Loading branch information
3 people authored Apr 7, 2023
1 parent d148d7d commit ba67fb2
Show file tree
Hide file tree
Showing 77 changed files with 2,537 additions and 1,128 deletions.
4 changes: 1 addition & 3 deletions Analysis/include/Luau/BuiltinDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ struct TypeArena;

void registerBuiltinTypes(GlobalTypes& globals);

void registerBuiltinGlobals(TypeChecker& typeChecker, GlobalTypes& globals);
void registerBuiltinGlobals(Frontend& frontend);

void registerBuiltinGlobals(Frontend& frontend, GlobalTypes& globals, bool typeCheckForAutocomplete = false);
TypeId makeUnion(TypeArena& arena, std::vector<TypeId>&& types);
TypeId makeIntersection(TypeArena& arena, std::vector<TypeId>&& types);

Expand Down
19 changes: 7 additions & 12 deletions Analysis/include/Luau/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include "Luau/Scope.h"
#include "Luau/TypeInfer.h"
#include "Luau/Variant.h"

#include <string>
#include <vector>
#include <optional>
Expand Down Expand Up @@ -36,9 +35,6 @@ struct LoadDefinitionFileResult
ModulePtr module;
};

LoadDefinitionFileResult loadDefinitionFile(TypeChecker& typeChecker, GlobalTypes& globals, ScopePtr targetScope, std::string_view definition,
const std::string& packageName, bool captureComments);

std::optional<Mode> parseMode(const std::vector<HotComment>& hotcomments);

std::vector<std::string_view> parsePathExpr(const AstExpr& pathExpr);
Expand All @@ -55,7 +51,9 @@ std::optional<ModuleName> pathExprToModuleName(const ModuleName& currentModuleNa
* error when we try during typechecking.
*/
std::optional<ModuleName> pathExprToModuleName(const ModuleName& currentModuleName, const AstExpr& expr);

// TODO: Deprecate this code path when we move away from the old solver
LoadDefinitionFileResult loadDefinitionFileNoDCR(TypeChecker& typeChecker, GlobalTypes& globals, ScopePtr targetScope, std::string_view definition,
const std::string& packageName, bool captureComments);
struct SourceNode
{
bool hasDirtySourceModule() const
Expand Down Expand Up @@ -140,10 +138,6 @@ struct Frontend

CheckResult check(const ModuleName& name, std::optional<FrontendOptions> optionOverride = {}); // new shininess

// Use 'check' with 'runLintChecks' set to true in FrontendOptions (enabledLintWarnings be set there as well)
LintResult lint_DEPRECATED(const ModuleName& name, std::optional<LintOptions> enabledLintWarnings = {});
LintResult lint_DEPRECATED(const SourceModule& module, std::optional<LintOptions> enabledLintWarnings = {});

bool isDirty(const ModuleName& name, bool forAutocomplete = false) const;
void markDirty(const ModuleName& name, std::vector<ModuleName>* markedDirty = nullptr);

Expand All @@ -164,10 +158,11 @@ struct Frontend
ScopePtr addEnvironment(const std::string& environmentName);
ScopePtr getEnvironmentScope(const std::string& environmentName) const;

void registerBuiltinDefinition(const std::string& name, std::function<void(TypeChecker&, GlobalTypes&, ScopePtr)>);
void registerBuiltinDefinition(const std::string& name, std::function<void(Frontend&, GlobalTypes&, ScopePtr)>);
void applyBuiltinDefinitionToEnvironment(const std::string& environmentName, const std::string& definitionName);

LoadDefinitionFileResult loadDefinitionFile(std::string_view source, const std::string& packageName, bool captureComments);
LoadDefinitionFileResult loadDefinitionFile(GlobalTypes& globals, ScopePtr targetScope, std::string_view source, const std::string& packageName,
bool captureComments, bool typeCheckForAutocomplete = false);

private:
ModulePtr check(const SourceModule& sourceModule, Mode mode, std::vector<RequireCycle> requireCycles, bool forAutocomplete = false, bool recordJsonLog = false);
Expand All @@ -182,7 +177,7 @@ struct Frontend
ScopePtr getModuleEnvironment(const SourceModule& module, const Config& config, bool forAutocomplete) const;

std::unordered_map<std::string, ScopePtr> environments;
std::unordered_map<std::string, std::function<void(TypeChecker&, GlobalTypes&, ScopePtr)>> builtinDefinitions;
std::unordered_map<std::string, std::function<void(Frontend&, GlobalTypes&, ScopePtr)>> builtinDefinitions;

BuiltinTypes builtinTypes_;

Expand Down
51 changes: 42 additions & 9 deletions Analysis/include/Luau/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,44 @@ using TypeId = const Type*;
using Name = std::string;

// A free type var is one whose exact shape has yet to be fully determined.
using FreeType = Unifiable::Free;
struct FreeType
{
explicit FreeType(TypeLevel level);
explicit FreeType(Scope* scope);
FreeType(Scope* scope, TypeLevel level);

// When a free type var is unified with any other, it is then "bound"
// to that type var, indicating that the two types are actually the same type.
using BoundType = Unifiable::Bound<TypeId>;
int index;
TypeLevel level;
Scope* scope = nullptr;

// True if this free type variable is part of a mutually
// recursive type alias whose definitions haven't been
// resolved yet.
bool forwardedTypeAlias = false;
};

struct GenericType
{
// By default, generics are global, with a synthetic name
GenericType();

using GenericType = Unifiable::Generic;
explicit GenericType(TypeLevel level);
explicit GenericType(const Name& name);
explicit GenericType(Scope* scope);

GenericType(TypeLevel level, const Name& name);
GenericType(Scope* scope, const Name& name);

int index;
TypeLevel level;
Scope* scope = nullptr;
Name name;
bool explicitName = false;
};

// When an equality constraint is found, it is then "bound" to that type,
// indicating that the two types are actually the same type.
using BoundType = Unifiable::Bound<TypeId>;

using Tags = std::vector<std::string>;

Expand Down Expand Up @@ -395,9 +426,11 @@ struct TableType
// Represents a metatable attached to a table type. Somewhat analogous to a bound type.
struct MetatableType
{
// Always points to a TableType.
// Should always be a TableType.
TypeId table;
// Always points to either a TableType or a MetatableType.
// Should almost always either be a TableType or another MetatableType,
// though it is possible for other types (like AnyType and ErrorType) to
// find their way here sometimes.
TypeId metatable;

std::optional<std::string> syntheticName;
Expand Down Expand Up @@ -536,8 +569,8 @@ struct NegationType

using ErrorType = Unifiable::Error;

using TypeVariant = Unifiable::Variant<TypeId, PrimitiveType, BlockedType, PendingExpansionType, SingletonType, FunctionType, TableType,
MetatableType, ClassType, AnyType, UnionType, IntersectionType, LazyType, UnknownType, NeverType, NegationType>;
using TypeVariant = Unifiable::Variant<TypeId, FreeType, GenericType, PrimitiveType, BlockedType, PendingExpansionType, SingletonType, FunctionType,
TableType, MetatableType, ClassType, AnyType, UnionType, IntersectionType, LazyType, UnknownType, NeverType, NegationType>;

struct Type final
{
Expand Down
38 changes: 33 additions & 5 deletions Analysis/include/Luau/TypePack.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,48 @@ namespace Luau
{

struct TypeArena;
struct TxnLog;

struct TypePack;
struct VariadicTypePack;
struct BlockedTypePack;

struct TypePackVar;
using TypePackId = const TypePackVar*;

struct TxnLog;
struct FreeTypePack
{
explicit FreeTypePack(TypeLevel level);
explicit FreeTypePack(Scope* scope);
FreeTypePack(Scope* scope, TypeLevel level);

int index;
TypeLevel level;
Scope* scope = nullptr;
};

struct GenericTypePack
{
// By default, generics are global, with a synthetic name
GenericTypePack();
explicit GenericTypePack(TypeLevel level);
explicit GenericTypePack(const Name& name);
explicit GenericTypePack(Scope* scope);
GenericTypePack(TypeLevel level, const Name& name);
GenericTypePack(Scope* scope, const Name& name);

int index;
TypeLevel level;
Scope* scope = nullptr;
Name name;
bool explicitName = false;
};

using TypePackId = const TypePackVar*;
using FreeTypePack = Unifiable::Free;
using BoundTypePack = Unifiable::Bound<TypePackId>;
using GenericTypePack = Unifiable::Generic;
using TypePackVariant = Unifiable::Variant<TypePackId, TypePack, VariadicTypePack, BlockedTypePack>;

using ErrorTypePack = Unifiable::Error;

using TypePackVariant = Unifiable::Variant<TypePackId, FreeTypePack, GenericTypePack, TypePack, VariadicTypePack, BlockedTypePack>;

/* A TypePack is a rope-like string of TypeIds. We use this structure to encode
* notions like packs of unknown length and packs of any length, as well as more
Expand Down
40 changes: 1 addition & 39 deletions Analysis/include/Luau/Unifiable.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,24 +83,6 @@ using Name = std::string;

int freshIndex();

struct Free
{
explicit Free(TypeLevel level);
explicit Free(Scope* scope);
explicit Free(Scope* scope, TypeLevel level);

int index;
TypeLevel level;
Scope* scope = nullptr;
// True if this free type variable is part of a mutually
// recursive type alias whose definitions haven't been
// resolved yet.
bool forwardedTypeAlias = false;

private:
static int DEPRECATED_nextIndex;
};

template<typename Id>
struct Bound
{
Expand All @@ -112,26 +94,6 @@ struct Bound
Id boundTo;
};

struct Generic
{
// By default, generics are global, with a synthetic name
Generic();
explicit Generic(TypeLevel level);
explicit Generic(const Name& name);
explicit Generic(Scope* scope);
Generic(TypeLevel level, const Name& name);
Generic(Scope* scope, const Name& name);

int index;
TypeLevel level;
Scope* scope = nullptr;
Name name;
bool explicitName = false;

private:
static int DEPRECATED_nextIndex;
};

struct Error
{
// This constructor has to be public, since it's used in Type and TypePack,
Expand All @@ -145,6 +107,6 @@ struct Error
};

template<typename Id, typename... Value>
using Variant = Luau::Variant<Free, Bound<Id>, Generic, Error, Value...>;
using Variant = Luau::Variant<Bound<Id>, Error, Value...>;

} // namespace Luau::Unifiable
4 changes: 2 additions & 2 deletions Analysis/include/Luau/VisitType.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,10 +341,10 @@ struct GenericTypeVisitor
traverse(btv->boundTo);
}

else if (auto ftv = get<Unifiable::Free>(tp))
else if (auto ftv = get<FreeTypePack>(tp))
visit(tp, *ftv);

else if (auto gtv = get<Unifiable::Generic>(tp))
else if (auto gtv = get<GenericTypePack>(tp))
visit(tp, *gtv);

else if (auto etv = get<Unifiable::Error>(tp))
Expand Down
11 changes: 3 additions & 8 deletions Analysis/src/Autocomplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
#include <unordered_set>
#include <utility>

LUAU_FASTFLAGVARIABLE(LuauAutocompleteSkipNormalization, 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 @@ -143,12 +141,9 @@ static bool checkTypeMatch(TypeId subTy, TypeId superTy, NotNull<Scope> scope, T
Normalizer normalizer{typeArena, builtinTypes, NotNull{&unifierState}};
Unifier unifier(NotNull<Normalizer>{&normalizer}, Mode::Strict, scope, Location(), Variance::Covariant);

if (FFlag::LuauAutocompleteSkipNormalization)
{
// Cost of normalization can be too high for autocomplete response time requirements
unifier.normalize = false;
unifier.checkInhabited = false;
}
// Cost of normalization can be too high for autocomplete response time requirements
unifier.normalize = false;
unifier.checkInhabited = false;

return unifier.canUnify(subTy, superTy).empty();
}
Expand Down
Loading

0 comments on commit ba67fb2

Please sign in to comment.