Skip to content

Commit

Permalink
Sync to upstream/release/588 (#992)
Browse files Browse the repository at this point in the history
Type checker/autocomplete:
* `Luau::autocomplete` no longer performs typechecking internally, make
sure to run `Frontend::check` before performing autocomplete requests
* Autocomplete string suggestions without "" are now only suggested
inside the ""
* Autocomplete suggestions now include `function (anonymous autofilled)`
key with a full suggestion for the function expression (with arguments
included) stored in `AutocompleteEntry::insertText`
* `AutocompleteEntry::indexedWithSelf` is provided for function call
suggestions made with `:`
* Cyclic modules now see each other type exports as `any` to prevent
memory use-after-free (similar to module return type)

Runtime:
* Updated inline/loop unroll cost model to better handle assignments
(Fixes #978)
* `math.noise` speed was improved by ~30%
* `table.concat` speed was improved by ~5-7%
* `tonumber` and `tostring` now have fastcall paths that execute ~1.5x
and ~2.5x faster respectively (fixes #777)
* Fixed crash in `luaL_typename` when index refers to a non-existing
value
* Fixed potential out of memory scenario when using `string.sub` or
`string.char` in a loop
* Fixed behavior of some fastcall builtins when called without arguments
under -O2 to match original functions
* Support for native code execution in VM is now enabled by default
(note: native code still has to be generated explicitly)
* `Codegen::compile` now accepts `CodeGen_OnlyNativeModules` flag. When
set, only modules that have a `--!native` hot-comment at the top will be
compiled to native code

In our new typechecker:
* Generic type packs are no longer considered to be variadic during
unification
* Timeout and cancellation now works in new solver
* Fixed false positive errors around 'table' and 'function' type
refinements
* Table literals now use covariant unification rules. This is sound
since literal has no type specified and has no aliases
* Fixed issues with blocked types escaping the constraint solver
* Fixed more places where error messages that should've been suppressed
were still reported
* Fixed errors when iterating over a top table type

In our native code generation (jit):
* 'DebugLuauAbortingChecks' flag is now supported on A64
* LOP_NEWCLOSURE has been translated to IR
  • Loading branch information
vegorov-rbx authored Jul 28, 2023
1 parent 087be52 commit 76f67e0
Show file tree
Hide file tree
Showing 96 changed files with 3,082 additions and 1,016 deletions.
7 changes: 7 additions & 0 deletions Analysis/include/Luau/Autocomplete.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ enum class AutocompleteEntryKind
String,
Type,
Module,
GeneratedFunction,
};

enum class ParenthesesRecommendation
Expand Down Expand Up @@ -70,6 +71,10 @@ struct AutocompleteEntry
std::optional<std::string> documentationSymbol = std::nullopt;
Tags tags;
ParenthesesRecommendation parens = ParenthesesRecommendation::None;
std::optional<std::string> insertText;

// Only meaningful if kind is Property.
bool indexedWithSelf = false;
};

using AutocompleteEntryMap = std::unordered_map<std::string, AutocompleteEntry>;
Expand All @@ -94,4 +99,6 @@ using StringCompletionCallback =

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

constexpr char kGeneratedAnonymousFunctionEntryName[] = "function (anonymous autofilled)";

} // namespace Luau
2 changes: 1 addition & 1 deletion Analysis/include/Luau/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct Config
{
Config();

Mode mode;
Mode mode = Mode::Nonstrict;

ParseOptions parseOptions;

Expand Down
3 changes: 2 additions & 1 deletion Analysis/include/Luau/ConstraintGraphBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,13 @@ struct ConstraintGraphBuilder
ScopePtr globalScope;

std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope;
std::vector<RequireCycle> requireCycles;

DcrLogger* logger;

ConstraintGraphBuilder(ModulePtr module, TypeArena* arena, NotNull<ModuleResolver> moduleResolver, NotNull<BuiltinTypes> builtinTypes,
NotNull<InternalErrorReporter> ice, const ScopePtr& globalScope, std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope,
DcrLogger* logger, NotNull<DataFlowGraph> dfg);
DcrLogger* logger, NotNull<DataFlowGraph> dfg, std::vector<RequireCycle> requireCycles);

/**
* Fabricates a new free type belonging to a given scope.
Expand Down
8 changes: 7 additions & 1 deletion Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "Luau/Normalize.h"
#include "Luau/ToString.h"
#include "Luau/Type.h"
#include "Luau/TypeCheckLimits.h"
#include "Luau/Variant.h"

#include <vector>
Expand Down Expand Up @@ -81,9 +82,11 @@ struct ConstraintSolver
std::vector<RequireCycle> requireCycles;

DcrLogger* logger;
TypeCheckLimits limits;

explicit ConstraintSolver(NotNull<Normalizer> normalizer, NotNull<Scope> rootScope, std::vector<NotNull<Constraint>> constraints,
ModuleName moduleName, NotNull<ModuleResolver> moduleResolver, std::vector<RequireCycle> requireCycles, DcrLogger* logger);
ModuleName moduleName, NotNull<ModuleResolver> moduleResolver, std::vector<RequireCycle> requireCycles, DcrLogger* logger,
TypeCheckLimits limits);

// Randomize the order in which to dispatch constraints
void randomize(unsigned seed);
Expand Down Expand Up @@ -280,6 +283,9 @@ struct ConstraintSolver

TypePackId anyifyModuleReturnTypePackGenerics(TypePackId tp);

void throwTimeLimitError();
void throwUserCancelError();

ToStringOptions opts;
};

Expand Down
20 changes: 16 additions & 4 deletions Analysis/include/Luau/Differ.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once

#include "Luau/DenseHash.h"
#include "Luau/Type.h"
#include <optional>
#include <string>
#include <unordered_map>

namespace Luau
{
Expand All @@ -17,6 +19,7 @@ struct DiffPathNode
FunctionReturn,
Union,
Intersection,
Negation,
};
Kind kind;
// non-null when TableProperty
Expand Down Expand Up @@ -54,18 +57,24 @@ struct DiffPathNodeLeaf
std::optional<Name> tableProperty;
std::optional<int> minLength;
bool isVariadic;
DiffPathNodeLeaf(std::optional<TypeId> ty, std::optional<Name> tableProperty, std::optional<int> minLength, bool isVariadic)
// TODO: Rename to anonymousIndex, for both union and Intersection
std::optional<size_t> unionIndex;
DiffPathNodeLeaf(
std::optional<TypeId> ty, std::optional<Name> tableProperty, std::optional<int> minLength, bool isVariadic, std::optional<size_t> unionIndex)
: ty(ty)
, tableProperty(tableProperty)
, minLength(minLength)
, isVariadic(isVariadic)
, unionIndex(unionIndex)
{
}

static DiffPathNodeLeaf detailsNormal(TypeId ty);

static DiffPathNodeLeaf detailsTableProperty(TypeId ty, Name tableProperty);

static DiffPathNodeLeaf detailsUnionIndex(TypeId ty, size_t index);

static DiffPathNodeLeaf detailsLength(int minLength, bool isVariadic);

static DiffPathNodeLeaf nullopts();
Expand All @@ -82,11 +91,12 @@ struct DiffError
enum Kind
{
Normal,
MissingProperty,
MissingTableProperty,
MissingUnionMember,
MissingIntersectionMember,
IncompatibleGeneric,
LengthMismatchInFnArgs,
LengthMismatchInFnRets,
LengthMismatchInUnion,
LengthMismatchInIntersection,
};
Kind kind;

Expand Down Expand Up @@ -141,6 +151,8 @@ struct DifferEnvironment
{
TypeId rootLeft;
TypeId rootRight;

DenseHashMap<TypeId, TypeId> genericMatchedPairs;
};
DifferResult diff(TypeId ty1, TypeId ty2);

Expand Down
14 changes: 4 additions & 10 deletions Analysis/include/Luau/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "Luau/ModuleResolver.h"
#include "Luau/RequireTracer.h"
#include "Luau/Scope.h"
#include "Luau/TypeCheckLimits.h"
#include "Luau/TypeInfer.h"
#include "Luau/Variant.h"

Expand Down Expand Up @@ -189,14 +190,6 @@ struct Frontend
std::optional<CheckResult> getCheckResult(const ModuleName& name, bool accumulateNested, bool forAutocomplete = false);

private:
struct TypeCheckLimits
{
std::optional<double> finishTime;
std::optional<int> instantiationChildLimit;
std::optional<int> unifierIterationLimit;
std::shared_ptr<FrontendCancellationToken> cancellationToken;
};

ModulePtr check(const SourceModule& sourceModule, Mode mode, std::vector<RequireCycle> requireCycles, std::optional<ScopePtr> environmentScope,
bool forAutocomplete, bool recordJsonLog, TypeCheckLimits typeCheckLimits);

Expand Down Expand Up @@ -248,11 +241,12 @@ struct Frontend

ModulePtr check(const SourceModule& sourceModule, const std::vector<RequireCycle>& requireCycles, NotNull<BuiltinTypes> builtinTypes,
NotNull<InternalErrorReporter> iceHandler, NotNull<ModuleResolver> moduleResolver, NotNull<FileResolver> fileResolver,
const ScopePtr& globalScope, std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope, FrontendOptions options);
const ScopePtr& globalScope, std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope, FrontendOptions options,
TypeCheckLimits limits);

ModulePtr check(const SourceModule& sourceModule, const std::vector<RequireCycle>& requireCycles, NotNull<BuiltinTypes> builtinTypes,
NotNull<InternalErrorReporter> iceHandler, NotNull<ModuleResolver> moduleResolver, NotNull<FileResolver> fileResolver,
const ScopePtr& globalScope, std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope, FrontendOptions options,
bool recordJsonLog);
TypeCheckLimits limits, bool recordJsonLog);

} // namespace Luau
3 changes: 3 additions & 0 deletions Analysis/include/Luau/Normalize.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ struct NormalizedType
/// Returns true if this type should result in error suppressing behavior.
bool shouldSuppressErrors() const;

/// Returns true if this type contains the primitve top table type, `table`.
bool hasTopTable() const;

// Helpers that improve readability of the above (they just say if the component is present)
bool hasTops() const;
bool hasBooleans() const;
Expand Down
14 changes: 1 addition & 13 deletions Analysis/include/Luau/Symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

#include <string>

LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution)

namespace Luau
{

Expand Down Expand Up @@ -42,17 +40,7 @@ struct Symbol
return local != nullptr || global.value != nullptr;
}

bool operator==(const Symbol& rhs) const
{
if (local)
return local == rhs.local;
else if (global.value)
return rhs.global.value && global == rhs.global.value; // Subtlety: AstName::operator==(const char*) uses strcmp, not pointer identity.
else if (FFlag::DebugLuauDeferredConstraintResolution)
return !rhs.local && !rhs.global.value; // Reflexivity: we already know `this` Symbol is empty, so check that rhs is.
else
return false;
}
bool operator==(const Symbol& rhs) const;

bool operator!=(const Symbol& rhs) const
{
Expand Down
4 changes: 4 additions & 0 deletions Analysis/include/Luau/TypeArena.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@

namespace Luau
{
struct Module;

struct TypeArena
{
TypedAllocator<Type> types;
TypedAllocator<TypePackVar> typePacks;

// Owning module, if any
Module* owningModule = nullptr;

void clear();

template<typename T>
Expand Down
41 changes: 41 additions & 0 deletions Analysis/include/Luau/TypeCheckLimits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once

#include "Luau/Cancellation.h"
#include "Luau/Error.h"

#include <memory>
#include <optional>
#include <string>

namespace Luau
{

class TimeLimitError : public InternalCompilerError
{
public:
explicit TimeLimitError(const std::string& moduleName)
: InternalCompilerError("Typeinfer failed to complete in allotted time", moduleName)
{
}
};

class UserCancelError : public InternalCompilerError
{
public:
explicit UserCancelError(const std::string& moduleName)
: InternalCompilerError("Analysis has been cancelled by user", moduleName)
{
}
};

struct TypeCheckLimits
{
std::optional<double> finishTime;
std::optional<int> instantiationChildLimit;
std::optional<int> unifierIterationLimit;

std::shared_ptr<FrontendCancellationToken> cancellationToken;
};

} // namespace Luau
19 changes: 1 addition & 18 deletions Analysis/include/Luau/TypeInfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "Luau/Symbol.h"
#include "Luau/TxnLog.h"
#include "Luau/Type.h"
#include "Luau/TypeCheckLimits.h"
#include "Luau/TypePack.h"
#include "Luau/TypeUtils.h"
#include "Luau/Unifier.h"
Expand Down Expand Up @@ -56,24 +57,6 @@ struct HashBoolNamePair
size_t operator()(const std::pair<bool, Name>& pair) const;
};

class TimeLimitError : public InternalCompilerError
{
public:
explicit TimeLimitError(const std::string& moduleName)
: InternalCompilerError("Typeinfer failed to complete in allotted time", moduleName)
{
}
};

class UserCancelError : public InternalCompilerError
{
public:
explicit UserCancelError(const std::string& moduleName)
: InternalCompilerError("Analysis has been cancelled by user", moduleName)
{
}
};

struct GlobalTypes
{
GlobalTypes(NotNull<BuiltinTypes> builtinTypes);
Expand Down
46 changes: 46 additions & 0 deletions Analysis/include/Luau/TypeUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace Luau

struct TxnLog;
struct TypeArena;
class Normalizer;

enum class ValueContext
{
Expand Down Expand Up @@ -55,6 +56,51 @@ std::vector<TypeId> reduceUnion(const std::vector<TypeId>& types);
*/
TypeId stripNil(NotNull<BuiltinTypes> builtinTypes, TypeArena& arena, TypeId ty);

enum class ErrorSuppression
{
Suppress,
DoNotSuppress,
NormalizationFailed
};

/**
* Normalizes the given type using the normalizer to determine if the type
* should suppress any errors that would be reported involving it.
* @param normalizer the normalizer to use
* @param ty the type to check for error suppression
* @returns an enum indicating whether or not to suppress the error or to signal a normalization failure
*/
ErrorSuppression shouldSuppressErrors(NotNull<Normalizer> normalizer, TypeId ty);

/**
* Flattens and normalizes the given typepack using the normalizer to determine if the type
* should suppress any errors that would be reported involving it.
* @param normalizer the normalizer to use
* @param tp the typepack to check for error suppression
* @returns an enum indicating whether or not to suppress the error or to signal a normalization failure
*/
ErrorSuppression shouldSuppressErrors(NotNull<Normalizer> normalizer, TypePackId tp);

/**
* Normalizes the two given type using the normalizer to determine if either type
* should suppress any errors that would be reported involving it.
* @param normalizer the normalizer to use
* @param ty1 the first type to check for error suppression
* @param ty2 the second type to check for error suppression
* @returns an enum indicating whether or not to suppress the error or to signal a normalization failure
*/
ErrorSuppression shouldSuppressErrors(NotNull<Normalizer> normalizer, TypeId ty1, TypeId ty2);

/**
* Flattens and normalizes the two given typepacks using the normalizer to determine if either type
* should suppress any errors that would be reported involving it.
* @param normalizer the normalizer to use
* @param tp1 the first typepack to check for error suppression
* @param tp2 the second typepack to check for error suppression
* @returns an enum indicating whether or not to suppress the error or to signal a normalization failure
*/
ErrorSuppression shouldSuppressErrors(NotNull<Normalizer> normalizer, TypePackId tp1, TypePackId tp2);

template<typename T, typename Ty>
const T* get(std::optional<Ty> ty)
{
Expand Down
Loading

0 comments on commit 76f67e0

Please sign in to comment.