Skip to content

Commit

Permalink
Sync to upstream/release/522 (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
zeux committed Apr 7, 2022
1 parent ffff25a commit de1381e
Show file tree
Hide file tree
Showing 36 changed files with 1,376 additions and 754 deletions.
25 changes: 25 additions & 0 deletions Analysis/include/Luau/Clone.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once

#include "Luau/TypeVar.h"

#include <unordered_map>

namespace Luau
{

// Only exposed so they can be unit tested.
using SeenTypes = std::unordered_map<TypeId, TypeId>;
using SeenTypePacks = std::unordered_map<TypePackId, TypePackId>;

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);

} // namespace Luau
23 changes: 19 additions & 4 deletions Analysis/include/Luau/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <vector>
#include <optional>

LUAU_FASTFLAG(LuauSeparateTypechecks)

namespace Luau
{

Expand Down Expand Up @@ -55,10 +57,19 @@ std::optional<ModuleName> pathExprToModuleName(const ModuleName& currentModuleNa

struct SourceNode
{
bool isDirty(bool forAutocomplete) const
{
if (FFlag::LuauSeparateTypechecks)
return forAutocomplete ? dirtyAutocomplete : dirty;
else
return dirty;
}

ModuleName name;
std::unordered_set<ModuleName> requires;
std::vector<std::pair<ModuleName, Location>> requireLocations;
bool dirty = true;
bool dirtyAutocomplete = true;
};

struct FrontendOptions
Expand All @@ -71,12 +82,16 @@ struct FrontendOptions

// When true, we run typechecking twice, once in the regular mode, and once in strict mode
// in order to get more precise type information (e.g. for autocomplete).
bool typecheckTwice = false;
bool typecheckTwice_DEPRECATED = false;

// Run typechecking only in mode required for autocomplete (strict mode in order to get more precise type information)
bool forAutocomplete = false;
};

struct CheckResult
{
std::vector<TypeError> errors;
std::vector<ModuleName> timeoutHits;
};

struct FrontendModuleResolver : ModuleResolver
Expand Down Expand Up @@ -123,7 +138,7 @@ struct Frontend
CheckResult check(const SourceModule& module); // OLD. TODO KILL
LintResult lint(const SourceModule& module, std::optional<LintOptions> enabledLintWarnings = {});

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

/** Borrow a pointer into the SourceModule cache.
Expand All @@ -147,10 +162,10 @@ struct Frontend
void applyBuiltinDefinitionToEnvironment(const std::string& environmentName, const std::string& definitionName);

private:
std::pair<SourceNode*, SourceModule*> getSourceNode(CheckResult& checkResult, const ModuleName& name);
std::pair<SourceNode*, SourceModule*> getSourceNode(CheckResult& checkResult, const ModuleName& name, bool forAutocomplete);
SourceModule parse(const ModuleName& name, std::string_view src, const ParseOptions& parseOptions);

bool parseGraph(std::vector<ModuleName>& buildQueue, CheckResult& checkResult, const ModuleName& root);
bool parseGraph(std::vector<ModuleName>& buildQueue, CheckResult& checkResult, const ModuleName& root, bool forAutocomplete);

static LintResult classifyLints(const std::vector<LintWarning>& warnings, const Config& config);

Expand Down
29 changes: 13 additions & 16 deletions Analysis/include/Luau/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ struct SourceModule
std::optional<std::string> environmentName;
bool cyclic = false;

std::unique_ptr<Allocator> allocator;
std::unique_ptr<AstNameTable> names;
std::shared_ptr<Allocator> allocator;
std::shared_ptr<AstNameTable> names;
std::vector<ParseError> parseErrors;

AstStatBlock* root = nullptr;
Expand All @@ -48,6 +48,12 @@ struct SourceModule

bool isWithinComment(const SourceModule& sourceModule, Position pos);

struct RequireCycle
{
Location location;
std::vector<ModuleName> path; // one of the paths for a require() to go all the way back to the originating module
};

struct TypeArena
{
TypedAllocator<TypeVar> typeVars;
Expand Down Expand Up @@ -77,27 +83,17 @@ struct TypeArena
void freeze(TypeArena& arena);
void unfreeze(TypeArena& arena);

// Only exposed so they can be unit tested.
using SeenTypes = std::unordered_map<TypeId, TypeId>;
using SeenTypePacks = std::unordered_map<TypePackId, TypePackId>;

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
{
~Module();

TypeArena interfaceTypes;
TypeArena internalTypes;

// Scopes and AST types refer to parse data, so we need to keep that alive
std::shared_ptr<Allocator> allocator;
std::shared_ptr<AstNameTable> names;

std::vector<std::pair<Location, ScopePtr>> scopes; // never empty

DenseHashMap<const AstExpr*, TypeId> astTypes{nullptr};
Expand All @@ -109,6 +105,7 @@ struct Module
ErrorVec errors;
Mode mode;
SourceCode::Type type;
bool timeout = false;

ScopePtr getModuleScope() const;

Expand Down
10 changes: 10 additions & 0 deletions Analysis/include/Luau/TypeInfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ struct HashBoolNamePair
size_t operator()(const std::pair<bool, Name>& pair) const;
};

class TimeLimitError : public std::exception
{
public:
virtual const char* what() const throw();
};

// All TypeVars are retained via Environment::typeVars. All TypeIds
// within a program are borrowed pointers into this set.
struct TypeChecker
Expand Down Expand Up @@ -413,6 +419,10 @@ struct TypeChecker

UnifierSharedState unifierState;

std::vector<RequireCycle> requireCycles;

std::optional<double> finishTime;

public:
const TypeId nilType;
const TypeId numberType;
Expand Down
2 changes: 2 additions & 0 deletions Analysis/include/Luau/TypeVar.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,8 @@ struct SingletonTypes
const TypeId stringType;
const TypeId booleanType;
const TypeId threadType;
const TypeId trueType;
const TypeId falseType;
const TypeId anyType;
const TypeId optionalNumberType;

Expand Down
36 changes: 4 additions & 32 deletions Analysis/include/Luau/Variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,14 @@
#pragma once

#include "Luau/Common.h"

#ifndef LUAU_USE_STD_VARIANT
#define LUAU_USE_STD_VARIANT 0
#endif

#if LUAU_USE_STD_VARIANT
#include <variant>
#else
#include <new>
#include <type_traits>
#include <initializer_list>
#include <stddef.h>
#endif

namespace Luau
{

#if LUAU_USE_STD_VARIANT
template<typename... Ts>
using Variant = std::variant<Ts...>;

template<class Visitor, class Variant>
auto visit(Visitor&& vis, Variant&& var)
{
// This change resolves the ABI issues with std::variant on libc++; std::visit normally throws bad_variant_access
// but it requires an update to libc++.dylib which ships with macOS 10.14. To work around this, we assert on valueless
// variants since we will never generate them and call into a libc++ function that doesn't throw.
LUAU_ASSERT(!var.valueless_by_exception());

#ifdef __APPLE__
// See https://stackoverflow.com/a/53868971/503215
return std::__variant_detail::__visitation::__variant::__visit_value(vis, var);
#else
return std::visit(vis, var);
#endif
}

using std::get_if;
#else
template<typename... Ts>
class Variant
{
Expand Down Expand Up @@ -248,6 +217,8 @@ static void fnVisitV(Visitor& vis, std::conditional_t<std::is_const_v<T>, const
template<class Visitor, typename... Ts>
auto visit(Visitor&& vis, const Variant<Ts...>& var)
{
static_assert(std::conjunction_v<std::is_invocable<Visitor, Ts>...>, "visitor must accept every alternative as an argument");

using Result = std::invoke_result_t<Visitor, typename Variant<Ts...>::first_alternative>;
static_assert(std::conjunction_v<std::is_same<Result, std::invoke_result_t<Visitor, Ts>>...>,
"visitor result type must be consistent between alternatives");
Expand All @@ -273,6 +244,8 @@ auto visit(Visitor&& vis, const Variant<Ts...>& var)
template<class Visitor, typename... Ts>
auto visit(Visitor&& vis, Variant<Ts...>& var)
{
static_assert(std::conjunction_v<std::is_invocable<Visitor, Ts&>...>, "visitor must accept every alternative as an argument");

using Result = std::invoke_result_t<Visitor, typename Variant<Ts...>::first_alternative&>;
static_assert(std::conjunction_v<std::is_same<Result, std::invoke_result_t<Visitor, Ts&>>...>,
"visitor result type must be consistent between alternatives");
Expand All @@ -294,7 +267,6 @@ auto visit(Visitor&& vis, Variant<Ts...>& var)
return res;
}
}
#endif

template<class>
inline constexpr bool always_false_v = false;
Expand Down
Loading

0 comments on commit de1381e

Please sign in to comment.