Skip to content

Commit

Permalink
Sync to upstream/release/549 (#707)
Browse files Browse the repository at this point in the history
* Reoptimized math.min/max/bit32 builtins assuming at least 2 arguments are used (1-2% lift on some benchmarks)
* Type errors that mention function types no longer have redundant parenthesis around return type
* Luau REPL now supports --compile=remarks which displays the source code with optimization remarks embedded as comments
* Builtin calls are slightly faster when called with 1-2 arguments (~1% improvement in some benchmarks)
  • Loading branch information
vegorov-rbx authored Oct 14, 2022
1 parent ff736fd commit 76070f8
Show file tree
Hide file tree
Showing 104 changed files with 4,099 additions and 2,223 deletions.
8 changes: 5 additions & 3 deletions Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ struct ConstraintSolver

DcrLogger* logger;

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

// Randomize the order in which to dispatch constraints
void randomize(unsigned seed);
Expand All @@ -88,7 +88,9 @@ struct ConstraintSolver
**/
void run();

bool done();
bool isDone();

void finalizeModule();

/** Attempt to dispatch a constraint. Returns true if it was successful. If
* tryDispatch() returns false, the constraint remains in the unsolved set
Expand Down
4 changes: 3 additions & 1 deletion Analysis/include/Luau/DcrLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,13 @@ struct DcrLogger
void popBlock(NotNull<const Constraint> block);

void captureInitialSolverState(const Scope* rootScope, const std::vector<NotNull<const Constraint>>& unsolvedConstraints);
StepSnapshot prepareStepSnapshot(const Scope* rootScope, NotNull<const Constraint> current, bool force, const std::vector<NotNull<const Constraint>>& unsolvedConstraints);
StepSnapshot prepareStepSnapshot(
const Scope* rootScope, NotNull<const Constraint> current, bool force, const std::vector<NotNull<const Constraint>>& unsolvedConstraints);
void commitStepSnapshot(StepSnapshot snapshot);
void captureFinalSolverState(const Scope* rootScope, const std::vector<NotNull<const Constraint>>& unsolvedConstraints);

void captureTypeCheckError(const TypeError& error);

private:
ConstraintGenerationLog generationLog;
std::unordered_map<NotNull<const Constraint>, std::vector<ConstraintBlockTarget>> constraintBlocks;
Expand Down
1 change: 0 additions & 1 deletion Analysis/include/Luau/Error.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ struct UnknownSymbol
{
Binding,
Type,
Generic
};
Name name;
Context context;
Expand Down
2 changes: 1 addition & 1 deletion Analysis/include/Luau/JsonEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ void write(JsonEmitter& emitter, const std::unordered_map<std::string, T>& map)

for (const auto& [k, v] : map)
o.writePair(k, v);

o.finish();
}

Expand Down
22 changes: 14 additions & 8 deletions Analysis/include/Luau/Normalize.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ struct SingletonTypes;

using ModulePtr = std::shared_ptr<Module>;

bool isSubtype(TypeId subTy, TypeId superTy, NotNull<Scope> scope, NotNull<SingletonTypes> singletonTypes, InternalErrorReporter& ice, bool anyIsTop = true);
bool isSubtype(TypePackId subTy, TypePackId superTy, NotNull<Scope> scope, NotNull<SingletonTypes> singletonTypes, InternalErrorReporter& ice, bool anyIsTop = true);
bool isSubtype(
TypeId subTy, TypeId superTy, NotNull<Scope> scope, NotNull<SingletonTypes> singletonTypes, InternalErrorReporter& ice, bool anyIsTop = true);
bool isSubtype(TypePackId subTy, TypePackId superTy, NotNull<Scope> scope, NotNull<SingletonTypes> singletonTypes, InternalErrorReporter& ice,
bool anyIsTop = true);

std::pair<TypeId, bool> normalize(
TypeId ty, NotNull<Scope> scope, TypeArena& arena, NotNull<SingletonTypes> singletonTypes, InternalErrorReporter& ice);
Expand Down Expand Up @@ -68,37 +70,41 @@ class TypeIds
insert(*it);
}

bool operator ==(const TypeIds& there) const;
bool operator==(const TypeIds& there) const;
size_t getHash() const;
};

} // namespace Luau

template<> struct std::hash<Luau::TypeIds>
template<>
struct std::hash<Luau::TypeIds>
{
std::size_t operator()(const Luau::TypeIds& tys) const
{
return tys.getHash();
}
};

template<> struct std::hash<const Luau::TypeIds*>
template<>
struct std::hash<const Luau::TypeIds*>
{
std::size_t operator()(const Luau::TypeIds* tys) const
{
return tys->getHash();
}
};

template<> struct std::equal_to<Luau::TypeIds>
template<>
struct std::equal_to<Luau::TypeIds>
{
bool operator()(const Luau::TypeIds& here, const Luau::TypeIds& there) const
{
return here == there;
}
};

template<> struct std::equal_to<const Luau::TypeIds*>
template<>
struct std::equal_to<const Luau::TypeIds*>
{
bool operator()(const Luau::TypeIds* here, const Luau::TypeIds* there) const
{
Expand Down Expand Up @@ -160,7 +166,7 @@ struct NormalizedType

// The string part of the type.
// This may be the `string` type, or a union of singletons.
NormalizedStringType strings = std::map<std::string,TypeId>{};
NormalizedStringType strings = std::map<std::string, TypeId>{};

// The thread part of the type.
// This type is either never or thread.
Expand Down
2 changes: 1 addition & 1 deletion Analysis/include/Luau/TypeInfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ struct TypeChecker
std::vector<std::pair<TypeId, ScopePtr>> deferredQuantification;
};

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

extern PrintLineProc luauPrintLine;

Expand Down
11 changes: 6 additions & 5 deletions Analysis/include/Luau/Unifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,15 @@ struct Unifier
ErrorVec errors;
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 normalize; // Normalize unions and intersections if necessary
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 normalize; // Normalize unions and intersections if necessary
bool useScopes = false; // If true, we use the scope hierarchy rather than TypeLevels
CountMismatch::Context ctx = CountMismatch::Arg;

UnifierSharedState& sharedState;

Unifier(NotNull<Normalizer> normalizer, Mode mode, NotNull<Scope> scope, const Location& location, Variance variance,
TxnLog* parentLog = nullptr);
Unifier(
NotNull<Normalizer> normalizer, Mode mode, NotNull<Scope> scope, const Location& location, Variance variance, TxnLog* parentLog = nullptr);

// Test whether the two type vars unify. Never commits the result.
ErrorVec canUnify(TypeId subTy, TypeId superTy);
Expand All @@ -87,7 +87,8 @@ struct Unifier
void tryUnifyTypeWithUnion(TypeId subTy, TypeId superTy, const UnionTypeVar* uv, bool cacheEnabled, bool isFunctionCall);
void tryUnifyTypeWithIntersection(TypeId subTy, TypeId superTy, const IntersectionTypeVar* uv);
void tryUnifyIntersectionWithType(TypeId subTy, const IntersectionTypeVar* uv, TypeId superTy, bool cacheEnabled, bool isFunctionCall);
void tryUnifyNormalizedTypes(TypeId subTy, TypeId superTy, const NormalizedType& subNorm, const NormalizedType& superNorm, std::string reason, std::optional<TypeError> error = std::nullopt);
void tryUnifyNormalizedTypes(TypeId subTy, TypeId superTy, const NormalizedType& subNorm, const NormalizedType& superNorm, std::string reason,
std::optional<TypeError> error = std::nullopt);
void tryUnifyPrimitives(TypeId subTy, TypeId superTy);
void tryUnifySingletons(TypeId subTy, TypeId superTy);
void tryUnifyFunctions(TypeId subTy, TypeId superTy, bool isFunctionCall = false);
Expand Down
5 changes: 3 additions & 2 deletions Analysis/src/BuiltinDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ static bool dcrMagicFunctionSelect(MagicFunctionCallContext context)
asMutable(context.result)->ty.emplace<BoundTypePack>(resTypePack);
}
else if (tail)
asMutable(context.result)->ty.emplace<BoundTypePack>(*tail);
asMutable(context.result)->ty.emplace<BoundTypePack>(*tail);

return true;
}
Expand All @@ -507,7 +507,8 @@ static bool dcrMagicFunctionSelect(MagicFunctionCallContext context)

if (AstExprConstantString* str = arg1->as<AstExprConstantString>())
{
if (str->value.size == 1 && str->value.data[0] == '#') {
if (str->value.size == 1 && str->value.data[0] == '#')
{
TypePackId numberTypePack = context.solver->arena->addTypePack({context.solver->singletonTypes->numberType});
asMutable(context.result)->ty.emplace<BoundTypePack>(numberTypePack);
return true;
Expand Down
5 changes: 3 additions & 2 deletions Analysis/src/ConstraintGraphBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ static bool matchSetmetatable(const AstExprCall& call)

if (call.args.size != 2)
return false;

const AstExprGlobal* funcAsGlobal = call.func->as<AstExprGlobal>();
if (!funcAsGlobal || funcAsGlobal->name != smt)
return false;
Expand All @@ -52,7 +52,8 @@ static bool matchSetmetatable(const AstExprCall& call)
}

ConstraintGraphBuilder::ConstraintGraphBuilder(const ModuleName& moduleName, ModulePtr module, TypeArena* arena,
NotNull<ModuleResolver> moduleResolver, NotNull<SingletonTypes> singletonTypes, NotNull<InternalErrorReporter> ice, const ScopePtr& globalScope, DcrLogger* logger)
NotNull<ModuleResolver> moduleResolver, NotNull<SingletonTypes> singletonTypes, NotNull<InternalErrorReporter> ice, const ScopePtr& globalScope,
DcrLogger* logger)
: moduleName(moduleName)
, module(module)
, singletonTypes(singletonTypes)
Expand Down
71 changes: 49 additions & 22 deletions Analysis/src/ConstraintSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
#include "Luau/VisitTypeVar.h"
#include "Luau/TypeUtils.h"

#include <random>

LUAU_FASTFLAGVARIABLE(DebugLuauLogSolver, false);
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJson, false);
LUAU_FASTFLAG(LuauFixNameMaps)
Expand Down Expand Up @@ -283,13 +281,27 @@ ConstraintSolver::ConstraintSolver(NotNull<Normalizer> normalizer, NotNull<Scope

void ConstraintSolver::randomize(unsigned seed)
{
std::mt19937 g(seed);
std::shuffle(begin(unsolvedConstraints), end(unsolvedConstraints), g);
if (unsolvedConstraints.empty())
return;

unsigned int rng = seed;

for (size_t i = unsolvedConstraints.size() - 1; i > 0; --i)
{
// Fisher-Yates shuffle
size_t j = rng % (i + 1);

std::swap(unsolvedConstraints[i], unsolvedConstraints[j]);

// LCG RNG, constants from Numerical Recipes
// This may occasionally result in skewed shuffles due to distribution properties, but this is a debugging tool so it should be good enough
rng = rng * 1664525 + 1013904223;
}
}

void ConstraintSolver::run()
{
if (done())
if (isDone())
return;

if (FFlag::DebugLuauLogSolver)
Expand Down Expand Up @@ -364,6 +376,8 @@ void ConstraintSolver::run()
progress |= runSolverPass(true);
} while (progress);

finalizeModule();

if (FFlag::DebugLuauLogSolver)
{
dumpBindings(rootScope, opts);
Expand All @@ -375,11 +389,24 @@ void ConstraintSolver::run()
}
}

bool ConstraintSolver::done()
bool ConstraintSolver::isDone()
{
return unsolvedConstraints.empty();
}

void ConstraintSolver::finalizeModule()
{
Anyification a{arena, rootScope, singletonTypes, &iceReporter, singletonTypes->anyType, singletonTypes->anyTypePack};
std::optional<TypePackId> returnType = a.substitute(rootScope->returnType);
if (!returnType)
{
reportError(CodeTooComplex{}, Location{});
rootScope->returnType = singletonTypes->errorTypePack;
}
else
rootScope->returnType = *returnType;
}

bool ConstraintSolver::tryDispatch(NotNull<const Constraint> constraint, bool force)
{
if (!force && isBlocked(constraint))
Expand Down Expand Up @@ -506,25 +533,25 @@ bool ConstraintSolver::tryDispatch(const UnaryConstraint& c, NotNull<const Const

switch (c.op)
{
case AstExprUnary::Not:
{
asMutable(c.resultType)->ty.emplace<BoundTypeVar>(singletonTypes->booleanType);
return true;
}
case AstExprUnary::Len:
case AstExprUnary::Not:
{
asMutable(c.resultType)->ty.emplace<BoundTypeVar>(singletonTypes->booleanType);
return true;
}
case AstExprUnary::Len:
{
asMutable(c.resultType)->ty.emplace<BoundTypeVar>(singletonTypes->numberType);
return true;
}
case AstExprUnary::Minus:
{
if (isNumber(operandType) || get<AnyTypeVar>(operandType) || get<ErrorTypeVar>(operandType))
{
asMutable(c.resultType)->ty.emplace<BoundTypeVar>(singletonTypes->numberType);
asMutable(c.resultType)->ty.emplace<BoundTypeVar>(c.operandType);
return true;
}
case AstExprUnary::Minus:
{
if (isNumber(operandType) || get<AnyTypeVar>(operandType) || get<ErrorTypeVar>(operandType))
{
asMutable(c.resultType)->ty.emplace<BoundTypeVar>(c.operandType);
return true;
}
break;
}
break;
}
}

LUAU_ASSERT(false); // TODO metatable handling
Expand Down
11 changes: 6 additions & 5 deletions Analysis/src/DcrLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void write(JsonEmitter& emitter, const ConstraintGenerationLog& log)
emitter.writeRaw(":");

ObjectEmitter locationEmitter = emitter.writeObject();

for (const auto& [id, location] : log.constraintLocations)
{
locationEmitter.writePair(id, location);
Expand Down Expand Up @@ -232,7 +232,7 @@ void DcrLogger::captureSource(std::string source)
void DcrLogger::captureGenerationError(const TypeError& error)
{
std::string stringifiedError = toString(error);
generationLog.errors.push_back(ErrorSnapshot {
generationLog.errors.push_back(ErrorSnapshot{
/* message */ stringifiedError,
/* location */ error.location,
});
Expand Down Expand Up @@ -298,7 +298,8 @@ void DcrLogger::captureInitialSolverState(const Scope* rootScope, const std::vec
}
}

StepSnapshot DcrLogger::prepareStepSnapshot(const Scope* rootScope, NotNull<const Constraint> current, bool force, const std::vector<NotNull<const Constraint>>& unsolvedConstraints)
StepSnapshot DcrLogger::prepareStepSnapshot(
const Scope* rootScope, NotNull<const Constraint> current, bool force, const std::vector<NotNull<const Constraint>>& unsolvedConstraints)
{
ScopeSnapshot scopeSnapshot = snapshotScope(rootScope, opts);
std::string currentId = toPointerId(current);
Expand Down Expand Up @@ -344,7 +345,7 @@ void DcrLogger::captureFinalSolverState(const Scope* rootScope, const std::vecto
void DcrLogger::captureTypeCheckError(const TypeError& error)
{
std::string stringifiedError = toString(error);
checkLog.errors.push_back(ErrorSnapshot {
checkLog.errors.push_back(ErrorSnapshot{
/* message */ stringifiedError,
/* location */ error.location,
});
Expand All @@ -359,7 +360,7 @@ std::vector<ConstraintBlock> DcrLogger::snapshotBlocks(NotNull<const Constraint>
}

std::vector<ConstraintBlock> snapshot;

for (const ConstraintBlockTarget& target : it->second)
{
if (const TypeId* ty = get_if<TypeId>(&target))
Expand Down
Loading

0 comments on commit 76070f8

Please sign in to comment.