Skip to content

Commit

Permalink
Sync to upstream/release/541 (#644)
Browse files Browse the repository at this point in the history
- Fix autocomplete not suggesting globals defined after the cursor (fixes #622)
- Improve type checker stability
- Reduce parser C stack consumption which fixes some stack overflow crashes on deeply nested sources
- Improve performance of bit32.extract/replace when width is implied (~3% faster chess)
- Improve performance of bit32.extract when field/width are constants (~10% faster base64)
- Heap dump now annotates thread stacks with local variable/function names
  • Loading branch information
zeux authored Aug 18, 2022
1 parent 0e118b5 commit be2769a
Show file tree
Hide file tree
Showing 56 changed files with 1,787 additions and 937 deletions.
38 changes: 38 additions & 0 deletions Analysis/include/Luau/Anyification.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details

#pragma once

#include "Luau/NotNull.h"
#include "Luau/Substitution.h"
#include "Luau/TypeVar.h"

#include <memory>

namespace Luau
{

struct TypeArena;
struct Scope;
struct InternalErrorReporter;
using ScopePtr = std::shared_ptr<Scope>;

// A substitution which replaces free types by any
struct Anyification : Substitution
{
Anyification(TypeArena* arena, const ScopePtr& scope, InternalErrorReporter* iceHandler, TypeId anyType, TypePackId anyTypePack);
NotNull<Scope> scope;
InternalErrorReporter* iceHandler;

TypeId anyType;
TypePackId anyTypePack;
bool normalizationTooComplex = false;
bool isDirty(TypeId ty) override;
bool isDirty(TypePackId tp) override;
TypeId clean(TypeId ty) override;
TypePackId clean(TypePackId tp) override;

bool ignoreChildren(TypeId ty) override;
bool ignoreChildren(TypePackId ty) override;
};

}
4 changes: 2 additions & 2 deletions Analysis/include/Luau/Constraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ struct GeneralizationConstraint
{
TypeId generalizedType;
TypeId sourceType;
Scope* scope;
};

// subType ~ inst superType
Expand Down Expand Up @@ -85,13 +84,14 @@ using ConstraintPtr = std::unique_ptr<struct Constraint>;

struct Constraint
{
explicit Constraint(ConstraintV&& c);
Constraint(ConstraintV&& c, NotNull<Scope> scope);

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

ConstraintV c;
std::vector<NotNull<Constraint>> dependencies;
NotNull<Scope> scope;
};

inline Constraint& asMutable(const Constraint& c)
Expand Down
7 changes: 5 additions & 2 deletions Analysis/include/Luau/ConstraintGraphBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ struct ConstraintGraphBuilder

/**
* Fabricates a scope that is a child of another scope.
* @param location the lexical extent of the scope in the source code.
* @param node the lexical node that the scope belongs to.
* @param parent the parent scope of the new scope. Must not be null.
*/
ScopePtr childScope(Location location, const ScopePtr& parent);
ScopePtr childScope(AstNode* node, const ScopePtr& parent);

/**
* Adds a new constraint with no dependencies to a given scope.
Expand Down Expand Up @@ -105,10 +105,12 @@ struct ConstraintGraphBuilder
void visit(const ScopePtr& scope, AstStatLocal* local);
void visit(const ScopePtr& scope, AstStatFor* for_);
void visit(const ScopePtr& scope, AstStatWhile* while_);
void visit(const ScopePtr& scope, AstStatRepeat* repeat);
void visit(const ScopePtr& scope, AstStatLocalFunction* function);
void visit(const ScopePtr& scope, AstStatFunction* function);
void visit(const ScopePtr& scope, AstStatReturn* ret);
void visit(const ScopePtr& scope, AstStatAssign* assign);
void visit(const ScopePtr& scope, AstStatCompoundAssign* assign);
void visit(const ScopePtr& scope, AstStatIf* ifStatement);
void visit(const ScopePtr& scope, AstStatTypeAlias* alias);
void visit(const ScopePtr& scope, AstStatDeclareGlobal* declareGlobal);
Expand All @@ -133,6 +135,7 @@ struct ConstraintGraphBuilder
TypeId check(const ScopePtr& scope, AstExprIndexExpr* indexExpr);
TypeId check(const ScopePtr& scope, AstExprUnary* unary);
TypeId check(const ScopePtr& scope, AstExprBinary* binary);
TypeId check(const ScopePtr& scope, AstExprIfElse* ifElse);
TypeId check(const ScopePtr& scope, AstExprTypeAssertion* typeAssert);

struct FunctionSignature
Expand Down
11 changes: 8 additions & 3 deletions Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ struct ConstraintSolver
// Memoized instantiations of type aliases.
DenseHashMap<InstantiationSignature, TypeId, HashInstantiationSignature> instantiatedAliases{{}};

// Recorded errors that take place within the solver.
ErrorVec errors;

ConstraintSolverLogger logger;

explicit ConstraintSolver(TypeArena* arena, NotNull<Scope> rootScope);
Expand Down Expand Up @@ -115,21 +118,23 @@ struct ConstraintSolver
* @param subType the sub-type to unify.
* @param superType the super-type to unify.
*/
void unify(TypeId subType, TypeId superType);
void unify(TypeId subType, TypeId superType, NotNull<Scope> scope);

/**
* Creates a new Unifier and performs a single unification operation. Commits
* the result.
* @param subPack the sub-type pack to unify.
* @param superPack the super-type pack to unify.
*/
void unify(TypePackId subPack, TypePackId superPack);
void unify(TypePackId subPack, TypePackId superPack, NotNull<Scope> scope);

/** Pushes a new solver constraint to the solver.
* @param cv the body of the constraint.
**/
void pushConstraint(ConstraintV cv);
void pushConstraint(ConstraintV cv, NotNull<Scope> scope);

void reportError(TypeErrorData&& data, const Location& location);
void reportError(TypeError e);
private:
/**
* Marks a constraint as being blocked on a type or type pack. The constraint
Expand Down
2 changes: 2 additions & 0 deletions Analysis/include/Luau/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ struct Module
DenseHashMap<const AstExpr*, TypeId> astOverloadResolvedTypes{nullptr};
DenseHashMap<const AstType*, TypeId> astResolvedTypes{nullptr};
DenseHashMap<const AstTypePack*, TypePackId> astResolvedTypePacks{nullptr};
// Map AST nodes to the scope they create. Cannot be NotNull<Scope> because we need a sentinel value for the map.
DenseHashMap<const AstNode*, Scope*> astScopes{nullptr};

std::unordered_map<Name, TypeId> declaredGlobals;
ErrorVec errors;
Expand Down
20 changes: 14 additions & 6 deletions Analysis/include/Luau/Normalize.h
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details

#include "Luau/Substitution.h"
#include "Luau/TypeVar.h"
#include "Luau/Module.h"
#include "Luau/NotNull.h"
#include "Luau/TypeVar.h"

#include <memory>

namespace Luau
{

struct InternalErrorReporter;
struct Module;
struct Scope;

using ModulePtr = std::shared_ptr<Module>;

bool isSubtype(TypeId subTy, TypeId superTy, InternalErrorReporter& ice);
bool isSubtype(TypePackId subTy, TypePackId superTy, InternalErrorReporter& ice);
bool isSubtype(TypeId subTy, TypeId superTy, NotNull<Scope> scope, InternalErrorReporter& ice);
bool isSubtype(TypePackId subTy, TypePackId superTy, NotNull<Scope> scope, InternalErrorReporter& ice);

std::pair<TypeId, bool> normalize(TypeId ty, TypeArena& arena, InternalErrorReporter& ice);
std::pair<TypeId, bool> normalize(TypeId ty, NotNull<Scope> scope, TypeArena& arena, InternalErrorReporter& ice);
std::pair<TypeId, bool> normalize(TypeId ty, NotNull<Module> module, InternalErrorReporter& ice);
std::pair<TypeId, bool> normalize(TypeId ty, const ModulePtr& module, InternalErrorReporter& ice);
std::pair<TypePackId, bool> normalize(TypePackId ty, TypeArena& arena, InternalErrorReporter& ice);
std::pair<TypePackId, bool> normalize(TypePackId ty, NotNull<Scope> scope, TypeArena& arena, InternalErrorReporter& ice);
std::pair<TypePackId, bool> normalize(TypePackId ty, NotNull<Module> module, InternalErrorReporter& ice);
std::pair<TypePackId, bool> normalize(TypePackId ty, const ModulePtr& module, InternalErrorReporter& ice);

} // namespace Luau
63 changes: 15 additions & 48 deletions Analysis/include/Luau/TypeInfer.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once

#include "Luau/Anyification.h"
#include "Luau/Predicate.h"
#include "Luau/Error.h"
#include "Luau/Module.h"
Expand Down Expand Up @@ -36,40 +37,6 @@ const AstStat* getFallthrough(const AstStat* node);
struct UnifierOptions;
struct Unifier;

// A substitution which replaces free types by any
struct Anyification : Substitution
{
Anyification(TypeArena* arena, InternalErrorReporter* iceHandler, TypeId anyType, TypePackId anyTypePack)
: Substitution(TxnLog::empty(), arena)
, iceHandler(iceHandler)
, anyType(anyType)
, anyTypePack(anyTypePack)
{
}

InternalErrorReporter* iceHandler;

TypeId anyType;
TypePackId anyTypePack;
bool normalizationTooComplex = false;
bool isDirty(TypeId ty) override;
bool isDirty(TypePackId tp) override;
TypeId clean(TypeId ty) override;
TypePackId clean(TypePackId tp) override;

bool ignoreChildren(TypeId ty) override
{
if (FFlag::LuauClassTypeVarsInSubstitution && get<ClassTypeVar>(ty))
return true;

return ty->persistent;
}
bool ignoreChildren(TypePackId ty) override
{
return ty->persistent;
}
};

struct GenericTypeDefinitions
{
std::vector<GenericTypeDefinition> genericTypes;
Expand Down Expand Up @@ -196,32 +163,32 @@ struct TypeChecker
/** Attempt to unify the types.
* Treat any failures as type errors in the final typecheck report.
*/
bool unify(TypeId subTy, TypeId superTy, const Location& location);
bool unify(TypeId subTy, TypeId superTy, const Location& location, const UnifierOptions& options);
bool unify(TypePackId subTy, TypePackId superTy, const Location& location, CountMismatch::Context ctx = CountMismatch::Context::Arg);
bool unify(TypeId subTy, TypeId superTy, const ScopePtr& scope, const Location& location);
bool unify(TypeId subTy, TypeId superTy, const ScopePtr& scope, const Location& location, const UnifierOptions& options);
bool unify(TypePackId subTy, TypePackId superTy, const ScopePtr& scope, const Location& location, CountMismatch::Context ctx = CountMismatch::Context::Arg);

/** Attempt to unify the types.
* If this fails, and the subTy type can be instantiated, do so and try unification again.
*/
bool unifyWithInstantiationIfNeeded(const ScopePtr& scope, TypeId subTy, TypeId superTy, const Location& location);
void unifyWithInstantiationIfNeeded(const ScopePtr& scope, TypeId subTy, TypeId superTy, Unifier& state);
bool unifyWithInstantiationIfNeeded(TypeId subTy, TypeId superTy, const ScopePtr& scope, const Location& location);
void unifyWithInstantiationIfNeeded(TypeId subTy, TypeId superTy, const ScopePtr& scope, Unifier& state);

/** Attempt to unify.
* If there are errors, undo everything and return the errors.
* If there are no errors, commit and return an empty error vector.
*/
template<typename Id>
ErrorVec tryUnify_(Id subTy, Id superTy, const Location& location);
ErrorVec tryUnify(TypeId subTy, TypeId superTy, const Location& location);
ErrorVec tryUnify(TypePackId subTy, TypePackId superTy, const Location& location);
ErrorVec tryUnify_(Id subTy, Id superTy, const ScopePtr& scope, const Location& location);
ErrorVec tryUnify(TypeId subTy, TypeId superTy, const ScopePtr& scope, const Location& location);
ErrorVec tryUnify(TypePackId subTy, TypePackId superTy, const ScopePtr& scope, const Location& location);

// Test whether the two type vars unify. Never commits the result.
template<typename Id>
ErrorVec canUnify_(Id subTy, Id superTy, const Location& location);
ErrorVec canUnify(TypeId subTy, TypeId superTy, const Location& location);
ErrorVec canUnify(TypePackId subTy, TypePackId superTy, const Location& location);
ErrorVec canUnify_(Id subTy, Id superTy, const ScopePtr& scope, const Location& location);
ErrorVec canUnify(TypeId subTy, TypeId superTy, const ScopePtr& scope, const Location& location);
ErrorVec canUnify(TypePackId subTy, TypePackId superTy, const ScopePtr& scope, const Location& location);

void unifyLowerBound(TypePackId subTy, TypePackId superTy, TypeLevel demotedLevel, const Location& location);
void unifyLowerBound(TypePackId subTy, TypePackId superTy, TypeLevel demotedLevel, const ScopePtr& scope, const Location& location);

std::optional<TypeId> findMetatableEntry(TypeId type, std::string entry, const Location& location, bool addErrors);
std::optional<TypeId> findTablePropertyRespectingMeta(TypeId lhsType, Name name, const Location& location, bool addErrors);
Expand Down Expand Up @@ -290,7 +257,7 @@ struct TypeChecker
void reportErrorCodeTooComplex(const Location& location);

private:
Unifier mkUnifier(const Location& location);
Unifier mkUnifier(const ScopePtr& scope, const Location& location);

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

Expand All @@ -312,7 +279,7 @@ struct TypeChecker
std::pair<std::optional<TypeId>, bool> pickTypesFromSense(TypeId type, bool sense);

private:
TypeId unionOfTypes(TypeId a, TypeId b, const Location& location, bool unifyFreeTypes = true);
TypeId unionOfTypes(TypeId a, TypeId b, const ScopePtr& scope, const Location& location, bool unifyFreeTypes = true);

// ex
// TypeId id = addType(FreeTypeVar());
Expand Down
7 changes: 5 additions & 2 deletions Analysis/include/Luau/TypeUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ namespace Luau

using ScopePtr = std::shared_ptr<struct Scope>;

std::optional<TypeId> findMetatableEntry(ErrorVec& errors, TypeId type, std::string entry, Location location);
std::optional<TypeId> findTablePropertyRespectingMeta(ErrorVec& errors, TypeId ty, Name name, Location location);
std::optional<TypeId> findMetatableEntry(ErrorVec& errors, TypeId type, const std::string& entry, Location location);
std::optional<TypeId> findTablePropertyRespectingMeta(ErrorVec& errors, TypeId ty, const std::string& name, Location location);
std::optional<TypeId> getIndexTypeFromType(
const ScopePtr& scope, ErrorVec& errors, TypeArena* arena, TypeId type, const std::string& prop, const Location& location, bool addErrors,
InternalErrorReporter& handle);

} // namespace Luau
4 changes: 2 additions & 2 deletions Analysis/include/Luau/TypedAllocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Luau
{

void* pagedAllocate(size_t size);
void pagedDeallocate(void* ptr);
void pagedDeallocate(void* ptr, size_t size);
void pagedFreeze(void* ptr, size_t size);
void pagedUnfreeze(void* ptr, size_t size);

Expand Down Expand Up @@ -113,7 +113,7 @@ class TypedAllocator
for (size_t i = 0; i < blockSize; ++i)
block[i].~T();

pagedDeallocate(block);
pagedDeallocate(block, kBlockSizeBytes);
}

stuff.clear();
Expand Down
6 changes: 4 additions & 2 deletions Analysis/include/Luau/Unifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

#include "Luau/Error.h"
#include "Luau/Location.h"
#include "Luau/Scope.h"
#include "Luau/TxnLog.h"
#include "Luau/TypeInfer.h"
#include "Luau/TypeArena.h"
#include "Luau/TypeInfer.h"
#include "Luau/UnifierSharedState.h"

#include <unordered_set>
Expand Down Expand Up @@ -48,6 +49,7 @@ struct Unifier
TypeArena* const types;
Mode mode;

NotNull<Scope> scope; // const Scope maybe
TxnLog log;
ErrorVec errors;
Location location;
Expand All @@ -57,7 +59,7 @@ struct Unifier

UnifierSharedState& sharedState;

Unifier(TypeArena* types, Mode mode, const Location& location, Variance variance, UnifierSharedState& sharedState, TxnLog* parentLog = nullptr);
Unifier(TypeArena* types, Mode mode, NotNull<Scope> scope, const Location& location, Variance variance, UnifierSharedState& sharedState, TxnLog* parentLog = nullptr);

// Test whether the two type vars unify. Never commits the result.
ErrorVec canUnify(TypeId subTy, TypeId superTy);
Expand Down
Loading

0 comments on commit be2769a

Please sign in to comment.