Skip to content

Commit

Permalink
Sync to upstream/release/547 (#690)
Browse files Browse the repository at this point in the history
- Type aliases can no longer override primitive types; attempts to do
that will result in a type error
- Fix misleading type error messages for mismatches in expression list
length during assignment
- Fix incorrect type name display in certain cases
- setmetatable/getmetatable are now ~2x faster
- tools/perfstat.py can be used to display statistics about profiles
captured via --profile switch
  • Loading branch information
zeux authored Sep 29, 2022
1 parent 1acd66c commit 944e837
Show file tree
Hide file tree
Showing 77 changed files with 1,635 additions and 677 deletions.
4 changes: 3 additions & 1 deletion Analysis/include/Luau/BuiltinDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
namespace Luau
{

void registerBuiltinTypes(TypeChecker& typeChecker);
void registerBuiltinTypes(Frontend& frontend);

void registerBuiltinGlobals(TypeChecker& typeChecker);
void registerBuiltinGlobals(Frontend& frontend);

TypeId makeUnion(TypeArena& arena, std::vector<TypeId>&& types);
TypeId makeIntersection(TypeArena& arena, std::vector<TypeId>&& types);

Expand Down
7 changes: 2 additions & 5 deletions Analysis/include/Luau/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,9 @@ constexpr const char* kConfigName = ".luaurc";

struct Config
{
Config()
{
enabledLint.setDefaults();
}
Config();

Mode mode = Mode::NoCheck;
Mode mode;

ParseOptions parseOptions;

Expand Down
3 changes: 2 additions & 1 deletion Analysis/include/Luau/Constraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ struct FunctionCallConstraint
{
std::vector<NotNull<const struct Constraint>> innerConstraints;
TypeId fn;
TypePackId argsPack;
TypePackId result;
class AstExprCall* astFragment;
class AstExprCall* callSite;
};

// result ~ prim ExpectedType SomeSingletonType MultitonType
Expand Down
1 change: 1 addition & 0 deletions Analysis/include/Luau/ConstraintGraphBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ struct ConstraintGraphBuilder
void visit(const ScopePtr& scope, AstStatDeclareGlobal* declareGlobal);
void visit(const ScopePtr& scope, AstStatDeclareClass* declareClass);
void visit(const ScopePtr& scope, AstStatDeclareFunction* declareFunction);
void visit(const ScopePtr& scope, AstStatError* error);

TypePackId checkPack(const ScopePtr& scope, AstArray<AstExpr*> exprs, const std::vector<TypeId>& expectedTypes = {});
TypePackId checkPack(const ScopePtr& scope, AstExpr* expr, const std::vector<TypeId>& expectedTypes = {});
Expand Down
1 change: 1 addition & 0 deletions Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ struct ConstraintSolver
bool tryDispatch(const HasPropConstraint& c, NotNull<const Constraint> constraint);

// for a, ... in some_table do
// also handles __iter metamethod
bool tryDispatchIterableTable(TypeId iteratorTy, const IterableConstraint& c, NotNull<const Constraint> constraint, bool force);

// for a, ... in next_function, t, ... do
Expand Down
5 changes: 3 additions & 2 deletions Analysis/include/Luau/Error.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ struct OnlyTablesCanHaveMethods
struct DuplicateTypeDefinition
{
Name name;
Location previousLocation;
std::optional<Location> previousLocation;

bool operator==(const DuplicateTypeDefinition& rhs) const;
};
Expand All @@ -91,7 +91,8 @@ struct CountMismatch
enum Context
{
Arg,
Result,
FunctionResult,
ExprListResult,
Return,
};
size_t expected;
Expand Down
10 changes: 6 additions & 4 deletions Analysis/include/Luau/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ struct Frontend
ScopePtr getGlobalScope();

private:
ModulePtr check(const SourceModule& sourceModule, Mode mode, const ScopePtr& environmentScope, std::vector<RequireCycle> requireCycles);
ModulePtr check(const SourceModule& sourceModule, Mode mode, const ScopePtr& environmentScope, std::vector<RequireCycle> requireCycles,
bool forAutocomplete = false);

std::pair<SourceNode*, SourceModule*> getSourceNode(CheckResult& checkResult, const ModuleName& name);
SourceModule parse(const ModuleName& name, std::string_view src, const ParseOptions& parseOptions);
Expand All @@ -171,10 +172,9 @@ struct Frontend
std::unordered_map<std::string, ScopePtr> environments;
std::unordered_map<std::string, std::function<void(TypeChecker&, ScopePtr)>> builtinDefinitions;

ScopePtr globalScope;
SingletonTypes singletonTypes_;

public:
SingletonTypes singletonTypes_;
const NotNull<SingletonTypes> singletonTypes;

FileResolver* fileResolver;
Expand All @@ -186,13 +186,15 @@ struct Frontend
FrontendOptions options;
InternalErrorReporter iceHandler;
TypeArena globalTypes;
TypeArena arenaForAutocomplete;

std::unordered_map<ModuleName, SourceNode> sourceNodes;
std::unordered_map<ModuleName, SourceModule> sourceModules;
std::unordered_map<ModuleName, RequireTraceResult> requireTrace;

Stats stats = {};

private:
ScopePtr globalScope;
};

} // namespace Luau
10 changes: 7 additions & 3 deletions Analysis/include/Luau/Instantiation.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@ struct TxnLog;
// A substitution which replaces generic types in a given set by free types.
struct ReplaceGenerics : Substitution
{
ReplaceGenerics(
const TxnLog* log, TypeArena* arena, TypeLevel level, const std::vector<TypeId>& generics, const std::vector<TypePackId>& genericPacks)
ReplaceGenerics(const TxnLog* log, TypeArena* arena, TypeLevel level, Scope* scope, const std::vector<TypeId>& generics,
const std::vector<TypePackId>& genericPacks)
: Substitution(log, arena)
, level(level)
, scope(scope)
, generics(generics)
, genericPacks(genericPacks)
{
}

TypeLevel level;
Scope* scope;
std::vector<TypeId> generics;
std::vector<TypePackId> genericPacks;
bool ignoreChildren(TypeId ty) override;
Expand All @@ -36,13 +38,15 @@ struct ReplaceGenerics : Substitution
// A substitution which replaces generic functions by monomorphic functions
struct Instantiation : Substitution
{
Instantiation(const TxnLog* log, TypeArena* arena, TypeLevel level)
Instantiation(const TxnLog* log, TypeArena* arena, TypeLevel level, Scope* scope)
: Substitution(log, arena)
, level(level)
, scope(scope)
{
}

TypeLevel level;
Scope* scope;
bool ignoreChildren(TypeId ty) override;
bool isDirty(TypeId ty) override;
bool isDirty(TypePackId tp) override;
Expand Down
15 changes: 13 additions & 2 deletions Analysis/include/Luau/Scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ struct Scope
std::unordered_map<Name, TypeFun> exportedTypeBindings;
std::unordered_map<Name, TypeFun> privateTypeBindings;
std::unordered_map<Name, Location> typeAliasLocations;

std::unordered_map<Name, std::unordered_map<Name, TypeFun>> importedTypeBindings;

DenseHashSet<Name> builtinTypeNames{""};
void addBuiltinTypeBinding(const Name& name, const TypeFun& tyFun);

std::optional<TypeId> lookup(Symbol sym);

std::optional<TypeFun> lookupType(const Name& name);
Expand All @@ -61,7 +63,7 @@ struct Scope
std::optional<TypePackId> lookupPack(const Name& name);

// WARNING: This function linearly scans for a string key of equal value! It is thus O(n**2)
std::optional<Binding> linearSearchForBinding(const std::string& name, bool traverseScopeChain = true);
std::optional<Binding> linearSearchForBinding(const std::string& name, bool traverseScopeChain = true) const;

RefinementMap refinements;

Expand All @@ -73,4 +75,13 @@ struct Scope
std::unordered_map<Name, TypePackId> typeAliasTypePackParameters;
};

// Returns true iff the left scope encloses the right scope. A Scope* equal to
// nullptr is considered to be the outermost-possible scope.
bool subsumesStrict(Scope* left, Scope* right);

// Returns true if the left scope encloses the right scope, or if they are the
// same scope. As in subsumesStrict(), nullptr is considered to be the
// outermost-possible scope.
bool subsumes(Scope* left, Scope* right);

} // namespace Luau
10 changes: 10 additions & 0 deletions Analysis/include/Luau/TxnLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,16 @@ struct TxnLog
// The pointer returned lives until `commit` or `clear` is called.
PendingTypePack* changeLevel(TypePackId tp, TypeLevel newLevel);

// Queues the replacement of a type's scope with the provided scope.
//
// The pointer returned lives until `commit` or `clear` is called.
PendingType* changeScope(TypeId ty, NotNull<Scope> scope);

// Queues the replacement of a type pack's scope with the provided scope.
//
// The pointer returned lives until `commit` or `clear` is called.
PendingTypePack* changeScope(TypePackId tp, NotNull<Scope> scope);

// Queues a replacement of a table type with another table type with a new
// indexer.
//
Expand Down
1 change: 1 addition & 0 deletions Analysis/include/Luau/TypeArena.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct TypeArena

TypeId freshType(TypeLevel level);
TypeId freshType(Scope* scope);
TypeId freshType(Scope* scope, TypeLevel level);

TypePackId freshTypePack(Scope* scope);

Expand Down
10 changes: 8 additions & 2 deletions Analysis/include/Luau/TypeInfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,12 @@ struct TypeChecker
void check(const ScopePtr& scope, const AstStatForIn& forin);
void check(const ScopePtr& scope, TypeId ty, const ScopePtr& funScope, const AstStatFunction& function);
void check(const ScopePtr& scope, TypeId ty, const ScopePtr& funScope, const AstStatLocalFunction& function);
void check(const ScopePtr& scope, const AstStatTypeAlias& typealias, int subLevel = 0, bool forwardDeclare = false);
void check(const ScopePtr& scope, const AstStatTypeAlias& typealias);
void check(const ScopePtr& scope, const AstStatDeclareClass& declaredClass);
void check(const ScopePtr& scope, const AstStatDeclareFunction& declaredFunction);

void prototype(const ScopePtr& scope, const AstStatTypeAlias& typealias, int subLevel = 0);

void checkBlock(const ScopePtr& scope, const AstStatBlock& statement);
void checkBlockWithoutRecursionCheck(const ScopePtr& scope, const AstStatBlock& statement);
void checkBlockTypeAliases(const ScopePtr& scope, std::vector<AstStat*>& sorted);
Expand Down Expand Up @@ -392,8 +394,12 @@ struct TypeChecker
std::vector<std::pair<TypeId, ScopePtr>> deferredQuantification;
};

using PrintLineProc = void(*)(const std::string&);

extern PrintLineProc luauPrintLine;

// Unit test hook
void setPrintLine(void (*pl)(const std::string& s));
void setPrintLine(PrintLineProc pl);
void resetPrintLine();

} // namespace Luau
4 changes: 4 additions & 0 deletions Analysis/include/Luau/TypeUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ std::optional<TypeId> getIndexTypeFromType(const ScopePtr& scope, ErrorVec& erro
// Returns the minimum and maximum number of types the argument list can accept.
std::pair<size_t, std::optional<size_t>> getParameterExtents(const TxnLog* log, TypePackId tp, bool includeHiddenVariadics = false);

// "Render" a type pack out to an array of a given length. Expands variadics and
// various other things to get there.
std::vector<TypeId> flatten(TypeArena& arena, NotNull<SingletonTypes> singletonTypes, TypePackId pack, size_t length);

} // namespace Luau
18 changes: 16 additions & 2 deletions Analysis/include/Luau/TypeVar.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Luau

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

/**
* There are three kinds of type variables:
Expand Down Expand Up @@ -264,7 +265,15 @@ struct WithPredicate
using MagicFunction = std::function<std::optional<WithPredicate<TypePackId>>(
struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>)>;

using DcrMagicFunction = std::function<bool(NotNull<struct ConstraintSolver>, TypePackId, const class AstExprCall*)>;
struct MagicFunctionCallContext
{
NotNull<struct ConstraintSolver> solver;
const class AstExprCall* callSite;
TypePackId arguments;
TypePackId result;
};

using DcrMagicFunction = std::function<bool(MagicFunctionCallContext)>;

struct FunctionTypeVar
{
Expand All @@ -277,10 +286,14 @@ struct FunctionTypeVar

// Local monomorphic function
FunctionTypeVar(TypeLevel level, TypePackId argTypes, TypePackId retTypes, std::optional<FunctionDefinition> defn = {}, bool hasSelf = false);
FunctionTypeVar(
TypeLevel level, Scope* scope, TypePackId argTypes, TypePackId retTypes, std::optional<FunctionDefinition> defn = {}, bool hasSelf = false);

// Local polymorphic function
FunctionTypeVar(TypeLevel level, std::vector<TypeId> generics, std::vector<TypePackId> genericPacks, TypePackId argTypes, TypePackId retTypes,
std::optional<FunctionDefinition> defn = {}, bool hasSelf = false);
FunctionTypeVar(TypeLevel level, Scope* scope, std::vector<TypeId> generics, std::vector<TypePackId> genericPacks, TypePackId argTypes,
TypePackId retTypes, std::optional<FunctionDefinition> defn = {}, bool hasSelf = false);

TypeLevel level;
Scope* scope = nullptr;
Expand Down Expand Up @@ -345,8 +358,9 @@ struct TableTypeVar
using Props = std::map<Name, Property>;

TableTypeVar() = default;
explicit TableTypeVar(TableState state, TypeLevel level);
explicit TableTypeVar(TableState state, TypeLevel level, Scope* scope = nullptr);
TableTypeVar(const Props& props, const std::optional<TableIndexer>& indexer, TypeLevel level, TableState state);
TableTypeVar(const Props& props, const std::optional<TableIndexer>& indexer, TypeLevel level, Scope* scope, TableState state);

Props props;
std::optional<TableIndexer> indexer;
Expand Down
1 change: 1 addition & 0 deletions Analysis/include/Luau/Unifiable.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ struct Free
{
explicit Free(TypeLevel level);
explicit Free(Scope* scope);
explicit Free(Scope* scope, TypeLevel level);

int index;
TypeLevel level;
Expand Down
3 changes: 2 additions & 1 deletion Analysis/include/Luau/Unifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ struct Unifier
Location location;
Variance variance = Covariant;
bool anyIsTop = false; // If true, we consider any to be a top type. If false, it is a familiar but weird mix of top and bottom all at once.
bool useScopes = false; // If true, we use the scope hierarchy rather than TypeLevels
CountMismatch::Context ctx = CountMismatch::Arg;

UnifierSharedState& sharedState;
Expand Down Expand Up @@ -140,6 +141,6 @@ struct Unifier
std::optional<int> firstPackErrorPos;
};

void promoteTypeLevels(TxnLog& log, const TypeArena* arena, TypeLevel minLevel, TypePackId tp);
void promoteTypeLevels(TxnLog& log, const TypeArena* arena, TypeLevel minLevel, Scope* outerScope, bool useScope, TypePackId tp);

} // namespace Luau
Loading

0 comments on commit 944e837

Please sign in to comment.