Skip to content

Commit

Permalink
Sync to upstream/release/543 (#657)
Browse files Browse the repository at this point in the history
- Improve ComparisonPrecedence lint suggestions for three-way comparisons (X < Y < Z)
- Improve type checking stability
- Improve location information for errors when parsing invalid type annotations
- Compiler now generates bytecode version 3 in all configurations
- Improve performance of comparisons against numeric constants on AArch64
  • Loading branch information
zeux authored Sep 1, 2022
1 parent 42c24f9 commit ae35ada
Show file tree
Hide file tree
Showing 75 changed files with 1,498 additions and 782 deletions.
3 changes: 2 additions & 1 deletion Analysis/include/Luau/Anyification.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ using ScopePtr = std::shared_ptr<Scope>;
// A substitution which replaces free types by any
struct Anyification : Substitution
{
Anyification(TypeArena* arena, NotNull<Scope> scope, InternalErrorReporter* iceHandler, TypeId anyType, TypePackId anyTypePack);
Anyification(TypeArena* arena, const ScopePtr& scope, InternalErrorReporter* iceHandler, TypeId anyType, TypePackId anyTypePack);
NotNull<Scope> scope;
InternalErrorReporter* iceHandler;
Expand All @@ -35,4 +36,4 @@ struct Anyification : Substitution
bool ignoreChildren(TypePackId ty) override;
};

}
} // namespace Luau
1 change: 1 addition & 0 deletions Analysis/include/Luau/BuiltinDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ TypeId makeFunction( // Polymorphic
std::initializer_list<TypeId> paramTypes, std::initializer_list<std::string> paramNames, std::initializer_list<TypeId> retTypes);

void attachMagicFunction(TypeId ty, MagicFunction fn);
void attachDcrMagicFunction(TypeId ty, DcrMagicFunction fn);

Property makeProperty(TypeId ty, std::optional<std::string> documentationSymbol = std::nullopt);
void assignPropDocumentationSymbols(TableTypeVar::Props& props, const std::string& baseName);
Expand Down
31 changes: 27 additions & 4 deletions Analysis/include/Luau/Constraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ struct UnaryConstraint
TypeId resultType;
};

// let L : leftType
// let R : rightType
// in
// L op R : resultType
struct BinaryConstraint
{
AstExprBinary::Op op;
Expand All @@ -64,6 +68,14 @@ struct BinaryConstraint
TypeId resultType;
};

// iteratee is iterable
// iterators is the iteration types.
struct IterableConstraint
{
TypePackId iterator;
TypePackId variables;
};

// name(namedType) = name
struct NameConstraint
{
Expand All @@ -78,20 +90,31 @@ struct TypeAliasExpansionConstraint
TypeId target;
};

using ConstraintV = Variant<SubtypeConstraint, PackSubtypeConstraint, GeneralizationConstraint, InstantiationConstraint, UnaryConstraint,
BinaryConstraint, NameConstraint, TypeAliasExpansionConstraint>;
using ConstraintPtr = std::unique_ptr<struct Constraint>;

struct FunctionCallConstraint
{
std::vector<NotNull<const Constraint>> innerConstraints;
TypeId fn;
TypePackId result;
class AstExprCall* astFragment;
};

using ConstraintV = Variant<SubtypeConstraint, PackSubtypeConstraint, GeneralizationConstraint, InstantiationConstraint, UnaryConstraint,
BinaryConstraint, IterableConstraint, NameConstraint, TypeAliasExpansionConstraint, FunctionCallConstraint>;

struct Constraint
{
Constraint(ConstraintV&& c, NotNull<Scope> scope);
Constraint(NotNull<Scope> scope, const Location& location, ConstraintV&& c);

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

NotNull<Scope> scope;
Location location;
ConstraintV c;

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

inline Constraint& asMutable(const Constraint& c)
Expand Down
11 changes: 7 additions & 4 deletions Analysis/include/Luau/ConstraintGraphBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Luau/Ast.h"
#include "Luau/Constraint.h"
#include "Luau/Module.h"
#include "Luau/ModuleResolver.h"
#include "Luau/NotNull.h"
#include "Luau/Symbol.h"
#include "Luau/TypeVar.h"
Expand Down Expand Up @@ -51,12 +52,15 @@ struct ConstraintGraphBuilder
// It is pretty uncommon for constraint generation to itself produce errors, but it can happen.
std::vector<TypeError> errors;

// Needed to resolve modules to make 'require' import types properly.
NotNull<ModuleResolver> moduleResolver;
// Occasionally constraint generation needs to produce an ICE.
const NotNull<InternalErrorReporter> ice;

ScopePtr globalScope;

ConstraintGraphBuilder(const ModuleName& moduleName, ModulePtr module, TypeArena* arena, NotNull<InternalErrorReporter> ice, const ScopePtr& globalScope);
ConstraintGraphBuilder(const ModuleName& moduleName, ModulePtr module, TypeArena* arena, NotNull<ModuleResolver> moduleResolver,
NotNull<InternalErrorReporter> ice, const ScopePtr& globalScope);

/**
* Fabricates a new free type belonging to a given scope.
Expand All @@ -82,7 +86,7 @@ struct ConstraintGraphBuilder
* @param scope the scope to add the constraint to.
* @param cv the constraint variant to add.
*/
void addConstraint(const ScopePtr& scope, ConstraintV cv);
void addConstraint(const ScopePtr& scope, const Location& location, ConstraintV cv);

/**
* Adds a constraint to a given scope.
Expand All @@ -104,6 +108,7 @@ struct ConstraintGraphBuilder
void visit(const ScopePtr& scope, AstStatBlock* block);
void visit(const ScopePtr& scope, AstStatLocal* local);
void visit(const ScopePtr& scope, AstStatFor* for_);
void visit(const ScopePtr& scope, AstStatForIn* forIn);
void visit(const ScopePtr& scope, AstStatWhile* while_);
void visit(const ScopePtr& scope, AstStatRepeat* repeat);
void visit(const ScopePtr& scope, AstStatLocalFunction* function);
Expand All @@ -117,8 +122,6 @@ struct ConstraintGraphBuilder
void visit(const ScopePtr& scope, AstStatDeclareClass* declareClass);
void visit(const ScopePtr& scope, AstStatDeclareFunction* declareFunction);

TypePackId checkExprList(const ScopePtr& scope, const AstArray<AstExpr*>& exprs);

TypePackId checkPack(const ScopePtr& scope, AstArray<AstExpr*> exprs);
TypePackId checkPack(const ScopePtr& scope, AstExpr* expr);

Expand Down
39 changes: 37 additions & 2 deletions Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace Luau
// never dereference this pointer.
using BlockedConstraintId = const void*;

struct ModuleResolver;

struct InstantiationSignature
{
TypeFun fn;
Expand All @@ -42,6 +44,7 @@ struct ConstraintSolver
// The entire set of constraints that the solver is trying to resolve.
std::vector<NotNull<Constraint>> constraints;
NotNull<Scope> rootScope;
ModuleName currentModuleName;

// Constraints that the solver has generated, rather than sourcing from the
// scope tree.
Expand All @@ -63,9 +66,13 @@ struct ConstraintSolver
// Recorded errors that take place within the solver.
ErrorVec errors;

NotNull<ModuleResolver> moduleResolver;
std::vector<RequireCycle> requireCycles;

ConstraintSolverLogger logger;

explicit ConstraintSolver(TypeArena* arena, NotNull<Scope> rootScope);
explicit ConstraintSolver(TypeArena* arena, NotNull<Scope> rootScope, ModuleName moduleName, NotNull<ModuleResolver> moduleResolver,
std::vector<RequireCycle> requireCycles);

/**
* Attempts to dispatch all pending constraints and reach a type solution
Expand All @@ -86,8 +93,17 @@ struct ConstraintSolver
bool tryDispatch(const InstantiationConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const UnaryConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const BinaryConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const IterableConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const NameConstraint& c, NotNull<const Constraint> constraint);
bool tryDispatch(const TypeAliasExpansionConstraint& c, NotNull<const Constraint> constraint);
bool tryDispatch(const FunctionCallConstraint& c, NotNull<const Constraint> constraint);

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

// for a, ... in next_function, t, ... do
bool tryDispatchIterableFunction(
TypeId nextTy, TypeId tableTy, TypeId firstIndexTy, const IterableConstraint& c, NotNull<const Constraint> constraint, bool force);

void block(NotNull<const Constraint> target, NotNull<const Constraint> constraint);
/**
Expand All @@ -108,6 +124,11 @@ struct ConstraintSolver
*/
bool isBlocked(TypeId ty);

/**
* @returns true if the TypePackId is in a blocked state.
*/
bool isBlocked(TypePackId tp);

/**
* Returns whether the constraint is blocked on anything.
* @param constraint the constraint to check.
Expand All @@ -133,10 +154,22 @@ struct ConstraintSolver
/** Pushes a new solver constraint to the solver.
* @param cv the body of the constraint.
**/
void pushConstraint(ConstraintV cv, NotNull<Scope> scope);
void pushConstraint(NotNull<Scope> scope, const Location& location, ConstraintV cv);

/**
* Attempts to resolve a module from its module information. Returns the
* module-level return type of the module, or the error type if one cannot
* be found. Reports errors to the solver if the module cannot be found or
* the require is illegal.
* @param module the module information to look up.
* @param location the location where the require is taking place; used for
* error locations.
**/
TypeId resolveModule(const ModuleInfo& module, const Location& location);

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 All @@ -154,6 +187,8 @@ struct ConstraintSolver
* @param progressed the type or type pack pointer that has progressed.
**/
void unblock_(BlockedConstraintId progressed);

ToStringOptions opts;
};

void dump(NotNull<Scope> rootScope, struct ToStringOptions& opts);
Expand Down
3 changes: 2 additions & 1 deletion Analysis/include/Luau/ConstraintSolverLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ struct ConstraintSolverLogger
{
std::string compileOutput();
void captureBoundarySnapshot(const Scope* rootScope, std::vector<NotNull<const Constraint>>& unsolvedConstraints);
void prepareStepSnapshot(const Scope* rootScope, NotNull<const Constraint> current, std::vector<NotNull<const Constraint>>& unsolvedConstraints, bool force);
void prepareStepSnapshot(
const Scope* rootScope, NotNull<const Constraint> current, std::vector<NotNull<const Constraint>>& unsolvedConstraints, bool force);
void commitPreparedStepSnapshot();

private:
Expand Down
2 changes: 1 addition & 1 deletion Analysis/include/Luau/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ struct Frontend
ScopePtr getGlobalScope();

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

std::pair<SourceNode*, SourceModule*> getSourceNode(CheckResult& checkResult, const ModuleName& name);
SourceModule parse(const ModuleName& name, std::string_view src, const ParseOptions& parseOptions);
Expand Down
3 changes: 3 additions & 0 deletions Analysis/include/Luau/Scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ struct Scope
std::optional<TypePackId> varargPack;
// All constraints belonging to this scope.
std::vector<ConstraintPtr> constraints;
// Constraints belonging to this scope that are queued manually by other
// constraints.
std::vector<ConstraintPtr> unqueuedConstraints;

TypeLevel level;

Expand Down
1 change: 0 additions & 1 deletion Analysis/include/Luau/ToString.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ inline std::string toString(const Constraint& c)
return toString(c, ToStringOptions{});
}


std::string toString(const TypeVar& tv, ToStringOptions& opts);
std::string toString(const TypePackVar& tp, ToStringOptions& opts);

Expand Down
3 changes: 2 additions & 1 deletion Analysis/include/Luau/TypeArena.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ struct TypeArena
TypeId addTV(TypeVar&& tv);

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

TypePackId addTypePack(std::initializer_list<TypeId> types);
TypePackId addTypePack(std::vector<TypeId> types);
TypePackId addTypePack(std::vector<TypeId> types, std::optional<TypePackId> tail = {});
TypePackId addTypePack(TypePack pack);
TypePackId addTypePack(TypePackVar pack);

Expand Down
3 changes: 2 additions & 1 deletion Analysis/include/Luau/TypeInfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ struct TypeChecker
*/
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);
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.
Expand Down
14 changes: 13 additions & 1 deletion Analysis/include/Luau/TypePack.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ struct TypeArena;

struct TypePack;
struct VariadicTypePack;
struct BlockedTypePack;

struct TypePackVar;

Expand All @@ -24,7 +25,7 @@ using TypePackId = const TypePackVar*;
using FreeTypePack = Unifiable::Free;
using BoundTypePack = Unifiable::Bound<TypePackId>;
using GenericTypePack = Unifiable::Generic;
using TypePackVariant = Unifiable::Variant<TypePackId, TypePack, VariadicTypePack>;
using TypePackVariant = Unifiable::Variant<TypePackId, 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 All @@ -43,6 +44,17 @@ struct VariadicTypePack
bool hidden = false; // if true, we don't display this when toString()ing a pack with this variadic as its tail.
};

/**
* Analogous to a BlockedTypeVar.
*/
struct BlockedTypePack
{
BlockedTypePack();
size_t index;

static size_t nextIndex;
};

struct TypePackVar
{
explicit TypePackVar(const TypePackVariant& ty);
Expand Down
10 changes: 7 additions & 3 deletions Analysis/include/Luau/TypeUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@
namespace Luau
{

struct TxnLog;

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

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);
std::optional<TypeId> getIndexTypeFromType(const ScopePtr& scope, ErrorVec& errors, TypeArena* arena, TypeId type, const std::string& prop,
const Location& location, bool addErrors, InternalErrorReporter& handle);

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

} // namespace Luau
12 changes: 9 additions & 3 deletions Analysis/include/Luau/TypeVar.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once

#include "Luau/Ast.h"
#include "Luau/DenseHash.h"
#include "Luau/Predicate.h"
#include "Luau/Unifiable.h"
#include "Luau/Variant.h"
#include "Luau/Common.h"
#include "Luau/NotNull.h"

#include <set>
#include <string>
Expand Down Expand Up @@ -262,6 +264,8 @@ 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 FunctionTypeVar
{
// Global monomorphic function
Expand All @@ -287,7 +291,8 @@ struct FunctionTypeVar
std::vector<std::optional<FunctionArgument>> argNames;
TypePackId retTypes;
std::optional<FunctionDefinition> definition;
MagicFunction magicFunction = nullptr; // Function pointer, can be nullptr.
MagicFunction magicFunction = nullptr; // Function pointer, can be nullptr.
DcrMagicFunction dcrMagicFunction = nullptr; // can be nullptr
bool hasSelf;
Tags tags;
bool hasNoGenerics = false;
Expand Down Expand Up @@ -462,8 +467,9 @@ struct TypeFun
*/
struct PendingExpansionTypeVar
{
PendingExpansionTypeVar(TypeFun fn, std::vector<TypeId> typeArguments, std::vector<TypePackId> packArguments);
TypeFun fn;
PendingExpansionTypeVar(std::optional<AstName> prefix, AstName name, std::vector<TypeId> typeArguments, std::vector<TypePackId> packArguments);
std::optional<AstName> prefix;
AstName name;
std::vector<TypeId> typeArguments;
std::vector<TypePackId> packArguments;
size_t index;
Expand Down
Loading

0 comments on commit ae35ada

Please sign in to comment.