From 69728e87cf8614b749c6f87ee3bc0449b8ac6f72 Mon Sep 17 00:00:00 2001 From: Vyacheslav Egorov Date: Fri, 8 Dec 2023 17:42:54 +0200 Subject: [PATCH] Sync to upstream/release/606 --- Analysis/include/Luau/ConstraintGenerator.h | 2 +- Analysis/include/Luau/DataFlowGraph.h | 31 ++- Analysis/include/Luau/Def.h | 1 + Analysis/src/ConstraintGenerator.cpp | 44 +++-- Analysis/src/DataFlowGraph.cpp | 182 ++++++++++++------ Analysis/src/Def.cpp | 19 +- Analysis/src/Frontend.cpp | 108 +++-------- CLI/Bytecode.cpp | 2 +- CodeGen/src/CodeGen.cpp | 27 ++- CodeGen/src/CodeGenLower.h | 13 +- CodeGen/src/EmitCommon.h | 3 - bench/bench_support.lua | 3 +- bench/gc/test_BinaryTree.lua | 3 +- bench/gc/test_GC_Boehm_Trees.lua | 3 +- bench/gc/test_GC_Tree_Pruning_Eager.lua | 3 +- bench/gc/test_GC_Tree_Pruning_Gen.lua | 3 +- bench/gc/test_GC_Tree_Pruning_Lazy.lua | 3 +- bench/gc/test_GC_hashtable_Keyval.lua | 3 +- bench/gc/test_LB_mandel.lua | 3 +- bench/gc/test_LargeTableCtor_array.lua | 3 +- bench/gc/test_LargeTableCtor_hash.lua | 3 +- bench/gc/test_Pcall_pcall_yield.lua | 3 +- bench/gc/test_SunSpider_3d-raytrace.lua | 3 +- bench/gc/test_TableCreate_nil.lua | 3 +- bench/gc/test_TableCreate_number.lua | 3 +- bench/gc/test_TableCreate_zerofill.lua | 3 +- bench/gc/test_TableMarshal_select.lua | 3 +- bench/gc/test_TableMarshal_table_pack.lua | 3 +- bench/gc/test_TableMarshal_varargs.lua | 3 +- bench/micro_tests/test_AbsSum_abs.lua | 3 +- bench/micro_tests/test_AbsSum_and_or.lua | 3 +- bench/micro_tests/test_AbsSum_math_abs.lua | 3 +- bench/micro_tests/test_Assert.lua | 3 +- bench/micro_tests/test_Factorial.lua | 3 +- .../micro_tests/test_Failure_pcall_a_bar.lua | 3 +- .../test_Failure_pcall_game_Foo.lua | 3 +- .../micro_tests/test_Failure_xpcall_a_bar.lua | 3 +- .../test_Failure_xpcall_game_Foo.lua | 3 +- .../micro_tests/test_LargeTableCtor_array.lua | 3 +- .../micro_tests/test_LargeTableCtor_hash.lua | 3 +- .../test_LargeTableSum_loop_index.lua | 3 +- .../test_LargeTableSum_loop_ipairs.lua | 3 +- .../test_LargeTableSum_loop_iter.lua | 3 +- .../test_LargeTableSum_loop_pairs.lua | 3 +- bench/micro_tests/test_MethodCalls.lua | 3 +- bench/micro_tests/test_OOP_constructor.lua | 3 +- bench/micro_tests/test_OOP_method_call.lua | 3 +- .../test_OOP_virtual_constructor.lua | 3 +- bench/micro_tests/test_Pcall_call_return.lua | 3 +- bench/micro_tests/test_Pcall_pcall_return.lua | 3 +- bench/micro_tests/test_Pcall_pcall_yield.lua | 3 +- .../micro_tests/test_Pcall_xpcall_return.lua | 3 +- bench/micro_tests/test_SqrtSum_exponent.lua | 3 +- bench/micro_tests/test_SqrtSum_math_sqrt.lua | 3 +- bench/micro_tests/test_SqrtSum_sqrt.lua | 3 +- .../micro_tests/test_SqrtSum_sqrt_getfenv.lua | 3 +- .../test_SqrtSum_sqrt_roundabout.lua | 3 +- bench/micro_tests/test_StringInterp.lua | 3 +- bench/micro_tests/test_TableCreate_nil.lua | 3 +- bench/micro_tests/test_TableCreate_number.lua | 3 +- .../micro_tests/test_TableCreate_zerofill.lua | 3 +- .../test_TableFind_loop_ipairs.lua | 3 +- .../micro_tests/test_TableFind_table_find.lua | 3 +- .../test_TableInsertion_index_cached.lua | 3 +- .../test_TableInsertion_index_len.lua | 3 +- .../test_TableInsertion_table_insert.lua | 3 +- ...test_TableInsertion_table_insert_index.lua | 3 +- bench/micro_tests/test_TableIteration.lua | 3 +- .../micro_tests/test_TableMarshal_select.lua | 3 +- .../test_TableMarshal_table_pack.lua | 3 +- .../test_TableMarshal_table_unpack_array.lua | 3 +- .../test_TableMarshal_table_unpack_range.lua | 3 +- .../micro_tests/test_TableMarshal_varargs.lua | 3 +- .../test_TableMove_empty_table.lua | 3 +- .../micro_tests/test_TableMove_same_table.lua | 3 +- .../test_TableMove_table_create.lua | 3 +- .../test_TableRemoval_table_remove.lua | 3 +- bench/micro_tests/test_TableSort.lua | 3 +- bench/micro_tests/test_ToNumberString.lua | 3 +- bench/micro_tests/test_UpvalueCapture.lua | 3 +- bench/micro_tests/test_VariadicSelect.lua | 3 +- bench/micro_tests/test_string_lib.lua | 3 +- bench/micro_tests/test_table_concat.lua | 3 +- bench/tests/base64.lua | 3 +- bench/tests/chess.lua | 3 +- bench/tests/life.lua | 3 +- bench/tests/matrixmult.lua | 3 +- bench/tests/mesh-normal-scalar.lua | 3 +- bench/tests/pcmmix.lua | 3 +- bench/tests/qsort.lua | 3 +- bench/tests/sha256.lua | 3 +- bench/tests/shootout/ack.lua | 3 +- bench/tests/shootout/binary-trees.lua | 3 +- bench/tests/shootout/fannkuch-redux.lua | 3 +- bench/tests/shootout/fixpoint-fact.lua | 3 +- bench/tests/shootout/heapsort.lua | 3 +- bench/tests/shootout/mandel.lua | 3 +- bench/tests/shootout/n-body.lua | 3 +- bench/tests/shootout/qt.lua | 3 +- bench/tests/shootout/queen.lua | 3 +- bench/tests/shootout/scimark.lua | 3 +- bench/tests/shootout/spectral-norm.lua | 3 +- bench/tests/sieve.lua | 3 +- bench/tests/sunspider/3d-cube.lua | 3 +- bench/tests/sunspider/3d-morph.lua | 3 +- bench/tests/sunspider/3d-raytrace.lua | 3 +- .../tests/sunspider/controlflow-recursive.lua | 3 +- bench/tests/sunspider/crypto-aes.lua | 3 +- bench/tests/sunspider/fannkuch.lua | 3 +- bench/tests/sunspider/math-cordic.lua | 3 +- bench/tests/sunspider/math-partial-sums.lua | 3 +- bench/tests/sunspider/n-body-oop.lua | 3 +- bench/tests/tictactoe.lua | 3 +- bench/tests/trig.lua | 3 +- bench/tests/voxelgen.lua | 3 +- fuzz/CMakeLists.txt | 5 +- tests/Conformance.test.cpp | 59 ++++++ tests/DataFlowGraph.test.cpp | 148 ++++++++++++++ tests/RequireByString.test.cpp | 18 +- tests/TypeInfer.functions.test.cpp | 1 - tests/TypeInfer.refinements.test.cpp | 17 +- tests/TypeInfer.typestates.test.cpp | 84 ++++++++ tools/faillist.txt | 15 ++ 123 files changed, 768 insertions(+), 323 deletions(-) diff --git a/Analysis/include/Luau/ConstraintGenerator.h b/Analysis/include/Luau/ConstraintGenerator.h index a3e1092f..0808e84c 100644 --- a/Analysis/include/Luau/ConstraintGenerator.h +++ b/Analysis/include/Luau/ConstraintGenerator.h @@ -150,7 +150,7 @@ private: */ ScopePtr childScope(AstNode* node, const ScopePtr& parent); - std::optional lookup(Scope* scope, DefId def); + std::optional lookup(Scope* scope, DefId def, bool prototype = true); /** * Adds a new constraint with no dependencies to a given scope. diff --git a/Analysis/include/Luau/DataFlowGraph.h b/Analysis/include/Luau/DataFlowGraph.h index 083e5046..1a983490 100644 --- a/Analysis/include/Luau/DataFlowGraph.h +++ b/Analysis/include/Luau/DataFlowGraph.h @@ -74,8 +74,15 @@ private: struct DfgScope { + enum ScopeType + { + Linear, + Loop, + Function, + }; + DfgScope* parent; - bool isLoopScope; + ScopeType scopeType; using Bindings = DenseHashMap; using Props = DenseHashMap>; @@ -117,7 +124,17 @@ private: std::vector> scopes; - DfgScope* childScope(DfgScope* scope, bool isLoopScope = false); + struct FunctionCapture + { + std::vector captureDefs; + std::vector allVersions; + size_t versionOffset = 0; + }; + + DenseHashMap captures{Symbol{}}; + void resolveCaptures(); + + DfgScope* childScope(DfgScope* scope, DfgScope::ScopeType scopeType = DfgScope::Linear); void join(DfgScope* p, DfgScope* a, DfgScope* b); void joinBindings(DfgScope::Bindings& p, const DfgScope::Bindings& a, const DfgScope::Bindings& b); @@ -167,11 +184,11 @@ private: DataFlowResult visitExpr(DfgScope* scope, AstExprError* error); void visitLValue(DfgScope* scope, AstExpr* e, DefId incomingDef, bool isCompoundAssignment = false); - void visitLValue(DfgScope* scope, AstExprLocal* l, DefId incomingDef, bool isCompoundAssignment); - void visitLValue(DfgScope* scope, AstExprGlobal* g, DefId incomingDef, bool isCompoundAssignment); - void visitLValue(DfgScope* scope, AstExprIndexName* i, DefId incomingDef); - void visitLValue(DfgScope* scope, AstExprIndexExpr* i, DefId incomingDef); - void visitLValue(DfgScope* scope, AstExprError* e, DefId incomingDef); + DefId visitLValue(DfgScope* scope, AstExprLocal* l, DefId incomingDef, bool isCompoundAssignment); + DefId visitLValue(DfgScope* scope, AstExprGlobal* g, DefId incomingDef, bool isCompoundAssignment); + DefId visitLValue(DfgScope* scope, AstExprIndexName* i, DefId incomingDef); + DefId visitLValue(DfgScope* scope, AstExprIndexExpr* i, DefId incomingDef); + DefId visitLValue(DfgScope* scope, AstExprError* e, DefId incomingDef); void visitType(DfgScope* scope, AstType* t); void visitType(DfgScope* scope, AstTypeReference* r); diff --git a/Analysis/include/Luau/Def.h b/Analysis/include/Luau/Def.h index e3fec9b6..9627f998 100644 --- a/Analysis/include/Luau/Def.h +++ b/Analysis/include/Luau/Def.h @@ -73,6 +73,7 @@ const T* get(DefId def) } bool containsSubscriptedDefinition(DefId def); +void collectOperands(DefId def, std::vector* operands); struct DefArena { diff --git a/Analysis/src/ConstraintGenerator.cpp b/Analysis/src/ConstraintGenerator.cpp index cdfe9a7f..311cf9a3 100644 --- a/Analysis/src/ConstraintGenerator.cpp +++ b/Analysis/src/ConstraintGenerator.cpp @@ -205,7 +205,7 @@ ScopePtr ConstraintGenerator::childScope(AstNode* node, const ScopePtr& parent) return scope; } -std::optional ConstraintGenerator::lookup(Scope* scope, DefId def) +std::optional ConstraintGenerator::lookup(Scope* scope, DefId def, bool prototype) { if (get(def)) return scope->lookup(def); @@ -213,22 +213,24 @@ std::optional ConstraintGenerator::lookup(Scope* scope, DefId def) { if (auto found = scope->lookup(def)) return *found; + else if (!prototype) + return std::nullopt; TypeId res = builtinTypes->neverType; for (DefId operand : phi->operands) { - // `scope->lookup(operand)` may return nothing because it could be a phi node of globals, but one of - // the operand of that global has never been assigned a type, and so it should be an error. - // e.g. - // ``` - // if foo() then - // g = 5 - // end - // -- `g` here is a phi node of the assignment to `g`, or the original revision of `g` before the branch. - // ``` - TypeId ty = scope->lookup(operand).value_or(builtinTypes->errorRecoveryType()); - res = simplifyUnion(builtinTypes, arena, res, ty).result; + // `scope->lookup(operand)` may return nothing because we only bind a type to that operand + // once we've seen that particular `DefId`. In this case, we need to prototype those types + // and use those at a later time. + std::optional ty = lookup(scope, operand, /*prototype*/false); + if (!ty) + { + ty = arena->addType(BlockedType{}); + rootScope->lvalueTypes[operand] = *ty; + } + + res = simplifyUnion(builtinTypes, arena, res, *ty).result; } scope->lvalueTypes[def] = res; @@ -861,7 +863,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatFunction* f DenseHashSet excludeList{nullptr}; DefId def = dfg->getDef(function->name); - std::optional existingFunctionTy = scope->lookup(def); + std::optional existingFunctionTy = lookup(scope.get(), def); if (AstExprLocal* localName = function->name->as()) { @@ -1724,16 +1726,14 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprGlobal* globa /* prepopulateGlobalScope() has already added all global functions to the environment by this point, so any * global that is not already in-scope is definitely an unknown symbol. */ - if (auto ty = lookup(scope.get(), def)) - return Inference{*ty, refinementArena.proposition(key, builtinTypes->truthyType)}; - else if (auto ty = scope->lookup(global->name)) + if (auto ty = lookup(scope.get(), def, /*prototype=*/false)) { rootScope->lvalueTypes[def] = *ty; return Inference{*ty, refinementArena.proposition(key, builtinTypes->truthyType)}; } else { - reportError(global->location, UnknownSymbol{global->name.value}); + reportError(global->location, UnknownSymbol{global->name.value, UnknownSymbol::Binding}); return Inference{builtinTypes->errorRecoveryType()}; } } @@ -3110,6 +3110,16 @@ struct GlobalPrepopulator : AstVisitor return true; } + + bool visit(AstType*) override + { + return true; + } + + bool visit(class AstTypePack* node) override + { + return true; + } }; void ConstraintGenerator::prepopulateGlobalScope(const ScopePtr& globalScope, AstStatBlock* program) diff --git a/Analysis/src/DataFlowGraph.cpp b/Analysis/src/DataFlowGraph.cpp index bdefd7f0..b331474e 100644 --- a/Analysis/src/DataFlowGraph.cpp +++ b/Analysis/src/DataFlowGraph.cpp @@ -116,7 +116,7 @@ bool DfgScope::canUpdateDefinition(Symbol symbol) const { if (current->bindings.find(symbol)) return true; - else if (current->isLoopScope) + else if (current->scopeType == DfgScope::Loop) return false; } @@ -129,7 +129,7 @@ bool DfgScope::canUpdateDefinition(DefId def, const std::string& key) const { if (auto props = current->props.find(def)) return true; - else if (current->isLoopScope) + else if (current->scopeType == DfgScope::Loop) return false; } @@ -144,6 +144,7 @@ DataFlowGraph DataFlowGraphBuilder::build(AstStatBlock* block, NotNull operands; + for (size_t i = capture.versionOffset; i < capture.allVersions.size(); ++i) + collectOperands(capture.allVersions[i], &operands); + + for (DefId captureDef : capture.captureDefs) + { + Phi* phi = const_cast(get(captureDef)); + LUAU_ASSERT(phi); + LUAU_ASSERT(phi->operands.empty()); + phi->operands = operands; + } + } +} + +DfgScope* DataFlowGraphBuilder::childScope(DfgScope* scope, DfgScope::ScopeType scopeType) +{ + return scopes.emplace_back(new DfgScope{scope, scopeType}).get(); } void DataFlowGraphBuilder::join(DfgScope* p, DfgScope* a, DfgScope* b) @@ -227,24 +246,44 @@ void DataFlowGraphBuilder::joinProps(DfgScope::Props& p, const DfgScope::Props& DefId DataFlowGraphBuilder::lookup(DfgScope* scope, Symbol symbol) { - if (auto found = scope->lookup(symbol)) - return *found; - else + for (DfgScope* current = scope; current; current = current->parent) { - DefId result = defArena->freshCell(); - if (symbol.local) - scope->bindings[symbol] = result; - else - moduleScope->bindings[symbol] = result; - return result; + if (auto found = current->bindings.find(symbol)) + return NotNull{*found}; + else if (current->scopeType == DfgScope::Function) + { + FunctionCapture& capture = captures[symbol]; + DefId captureDef = defArena->phi({}); + capture.captureDefs.push_back(captureDef); + scope->bindings[symbol] = captureDef; + return NotNull{captureDef}; + } } + + DefId result = defArena->freshCell(); + scope->bindings[symbol] = result; + captures[symbol].allVersions.push_back(result); + return result; } DefId DataFlowGraphBuilder::lookup(DfgScope* scope, DefId def, const std::string& key) { - if (auto found = scope->lookup(def, key)) - return *found; - else if (auto phi = get(def)) + for (DfgScope* current = scope; current; current = current->parent) + { + if (auto props = current->props.find(def)) + { + if (auto it = props->find(key); it != props->end()) + return NotNull{it->second}; + } + else if (auto phi = get(def); phi && phi->operands.empty()) // Unresolved phi nodes + { + DefId result = defArena->freshCell(); + scope->props[def][key] = result; + return result; + } + } + + if (auto phi = get(def)) { std::vector defs; for (DefId operand : phi->operands) @@ -361,7 +400,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatIf* i) ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatWhile* w) { // TODO(controlflow): entry point has a back edge from exit point - DfgScope* whileScope = childScope(scope, /*isLoopScope=*/true); + DfgScope* whileScope = childScope(scope, DfgScope::Loop); visitExpr(whileScope, w->condition); visit(whileScope, w->body); @@ -373,7 +412,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatWhile* w) ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatRepeat* r) { // TODO(controlflow): entry point has a back edge from exit point - DfgScope* repeatScope = childScope(scope, /*isLoopScope=*/true); + DfgScope* repeatScope = childScope(scope, DfgScope::Loop); visitBlockWithoutChildScope(repeatScope, r->body); visitExpr(repeatScope, r->condition); @@ -429,6 +468,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatLocal* l) DefId def = defArena->freshCell(subscripted); graph.localDefs[local] = def; scope->bindings[local] = def; + captures[local].allVersions.push_back(def); } return ControlFlow::None; @@ -436,7 +476,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatLocal* l) ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatFor* f) { - DfgScope* forScope = childScope(scope, /*isLoopScope=*/true); + DfgScope* forScope = childScope(scope, DfgScope::Loop); visitExpr(scope, f->from); visitExpr(scope, f->to); @@ -449,6 +489,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatFor* f) DefId def = defArena->freshCell(); graph.localDefs[f->var] = def; scope->bindings[f->var] = def; + captures[f->var].allVersions.push_back(def); // TODO(controlflow): entry point has a back edge from exit point visit(forScope, f->body); @@ -460,7 +501,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatFor* f) ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatForIn* f) { - DfgScope* forScope = childScope(scope, /*isLoopScope=*/true); + DfgScope* forScope = childScope(scope, DfgScope::Loop); for (AstLocal* local : f->vars) { @@ -470,6 +511,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatForIn* f) DefId def = defArena->freshCell(); graph.localDefs[local] = def; forScope->bindings[local] = def; + captures[local].allVersions.push_back(def); } // TODO(controlflow): entry point has a back edge from exit point @@ -527,10 +569,21 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatFunction* f) // // which is evidence that references to variables must be a phi node of all possible definitions, // but for bug compatibility, we'll assume the same thing here. - DefId prototype = defArena->freshCell(); - visitLValue(scope, f->name, prototype); + visitLValue(scope, f->name, defArena->freshCell()); visitExpr(scope, f->func); + if (auto local = f->name->as()) + { + // local f + // function f() + // if cond() then + // f() -- should reference only the function version and other future version, and nothing prior + // end + // end + FunctionCapture& capture = captures[local->local]; + capture.versionOffset = capture.allVersions.size() - 1; + } + return ControlFlow::None; } @@ -539,6 +592,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatLocalFunction* l DefId def = defArena->freshCell(); graph.localDefs[l->name] = def; scope->bindings[l->name] = def; + captures[l->name].allVersions.push_back(def); visitExpr(scope, l->func); return ControlFlow::None; @@ -559,6 +613,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatDeclareGlobal* d DefId def = defArena->freshCell(); graph.declaredDefs[d] = def; scope->bindings[d->name] = def; + captures[d->name].allVersions.push_back(def); visitType(scope, d->type); @@ -570,6 +625,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatDeclareFunction* DefId def = defArena->freshCell(); graph.declaredDefs[d] = def; scope->bindings[d->name] = def; + captures[d->name].allVersions.push_back(def); DfgScope* unreachable = childScope(scope); visitGenerics(unreachable, d->generics); @@ -669,14 +725,9 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprGroup* gr DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprLocal* l) { - // DfgScope::lookup is intentional here: we want to be able to ice. - if (auto def = scope->lookup(l->local)) - { - const RefinementKey* key = keyArena->leaf(*def); - return {*def, key}; - } - - handle->ice("DFG: AstExprLocal came before its declaration?"); + DefId def = lookup(scope, l->local); + const RefinementKey* key = keyArena->leaf(def); + return {def, key}; } DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprGlobal* g) @@ -723,7 +774,7 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprIndexExpr DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprFunction* f) { - DfgScope* signatureScope = childScope(scope); + DfgScope* signatureScope = childScope(scope, DfgScope::Function); if (AstLocal* self = f->self) { @@ -733,6 +784,7 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprFunction* DefId def = defArena->freshCell(); graph.localDefs[self] = def; signatureScope->bindings[self] = def; + captures[self].allVersions.push_back(def); } for (AstLocal* param : f->args) @@ -743,6 +795,7 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprFunction* DefId def = defArena->freshCell(); graph.localDefs[param] = def; signatureScope->bindings[param] = def; + captures[param].allVersions.push_back(def); } if (f->varargAnnotation) @@ -827,41 +880,46 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprError* er void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExpr* e, DefId incomingDef, bool isCompoundAssignment) { - if (auto l = e->as()) - return visitLValue(scope, l, incomingDef, isCompoundAssignment); - else if (auto g = e->as()) - return visitLValue(scope, g, incomingDef, isCompoundAssignment); - else if (auto i = e->as()) - return visitLValue(scope, i, incomingDef); - else if (auto i = e->as()) - return visitLValue(scope, i, incomingDef); - else if (auto error = e->as()) - return visitLValue(scope, error, incomingDef); - else - handle->ice("Unknown AstExpr in DataFlowGraphBuilder::visitLValue"); + auto go = [&]() { + if (auto l = e->as()) + return visitLValue(scope, l, incomingDef, isCompoundAssignment); + else if (auto g = e->as()) + return visitLValue(scope, g, incomingDef, isCompoundAssignment); + else if (auto i = e->as()) + return visitLValue(scope, i, incomingDef); + else if (auto i = e->as()) + return visitLValue(scope, i, incomingDef); + else if (auto error = e->as()) + return visitLValue(scope, error, incomingDef); + else + handle->ice("Unknown AstExpr in DataFlowGraphBuilder::visitLValue"); + }; + + graph.astDefs[e] = go(); } -void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprLocal* l, DefId incomingDef, bool isCompoundAssignment) +DefId DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprLocal* l, DefId incomingDef, bool isCompoundAssignment) { // We need to keep the previous def around for a compound assignment. if (isCompoundAssignment) { - if (auto def = scope->lookup(l->local)) - graph.compoundAssignDefs[l] = *def; + DefId def = lookup(scope, l->local); + graph.compoundAssignDefs[l] = def; } // In order to avoid alias tracking, we need to clip the reference to the parent def. if (scope->canUpdateDefinition(l->local)) { DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef)); - graph.astDefs[l] = updated; scope->bindings[l->local] = updated; + captures[l->local].allVersions.push_back(updated); + return updated; } else - visitExpr(scope, static_cast(l)); + return visitExpr(scope, static_cast(l)).def; } -void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprGlobal* g, DefId incomingDef, bool isCompoundAssignment) +DefId DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprGlobal* g, DefId incomingDef, bool isCompoundAssignment) { // We need to keep the previous def around for a compound assignment. if (isCompoundAssignment) @@ -874,28 +932,29 @@ void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprGlobal* g, DefId if (scope->canUpdateDefinition(g->name)) { DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef)); - graph.astDefs[g] = updated; scope->bindings[g->name] = updated; + captures[g->name].allVersions.push_back(updated); + return updated; } else - visitExpr(scope, static_cast(g)); + return visitExpr(scope, static_cast(g)).def; } -void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprIndexName* i, DefId incomingDef) +DefId DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprIndexName* i, DefId incomingDef) { DefId parentDef = visitExpr(scope, i->expr).def; if (scope->canUpdateDefinition(parentDef, i->index.value)) { DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef)); - graph.astDefs[i] = updated; scope->props[parentDef][i->index.value] = updated; + return updated; } else - visitExpr(scope, static_cast(i)); + return visitExpr(scope, static_cast(i)).def; } -void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprIndexExpr* i, DefId incomingDef) +DefId DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprIndexExpr* i, DefId incomingDef) { DefId parentDef = visitExpr(scope, i->expr).def; visitExpr(scope, i->index); @@ -905,20 +964,19 @@ void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprIndexExpr* i, Def if (scope->canUpdateDefinition(parentDef, string->value.data)) { DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef)); - graph.astDefs[i] = updated; scope->props[parentDef][string->value.data] = updated; + return updated; } else - visitExpr(scope, static_cast(i)); + return visitExpr(scope, static_cast(i)).def; } - - graph.astDefs[i] = defArena->freshCell(); + else + return defArena->freshCell(/*subscripted=*/true); } -void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprError* error, DefId incomingDef) +DefId DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprError* error, DefId incomingDef) { - DefId def = visitExpr(scope, error).def; - graph.astDefs[error] = def; + return visitExpr(scope, error).def; } void DataFlowGraphBuilder::visitType(DfgScope* scope, AstType* t) diff --git a/Analysis/src/Def.cpp b/Analysis/src/Def.cpp index 2b3bbeac..1ecaca22 100644 --- a/Analysis/src/Def.cpp +++ b/Analysis/src/Def.cpp @@ -19,17 +19,13 @@ bool containsSubscriptedDefinition(DefId def) return false; } -DefId DefArena::freshCell(bool subscripted) +void collectOperands(DefId def, std::vector* operands) { - return NotNull{allocator.allocate(Def{Cell{subscripted}})}; -} - -static void collectOperands(DefId def, std::vector& operands) -{ - if (std::find(operands.begin(), operands.end(), def) != operands.end()) + LUAU_ASSERT(operands); + if (std::find(operands->begin(), operands->end(), def) != operands->end()) return; else if (get(def)) - operands.push_back(def); + operands->push_back(def); else if (auto phi = get(def)) { for (const Def* operand : phi->operands) @@ -37,6 +33,11 @@ static void collectOperands(DefId def, std::vector& operands) } } +DefId DefArena::freshCell(bool subscripted) +{ + return NotNull{allocator.allocate(Def{Cell{subscripted}})}; +} + DefId DefArena::phi(DefId a, DefId b) { return phi({a, b}); @@ -46,7 +47,7 @@ DefId DefArena::phi(const std::vector& defs) { std::vector operands; for (DefId operand : defs) - collectOperands(operand, operands); + collectOperands(operand, &operands); // There's no need to allocate a Phi node for a singleton set. if (operands.size() == 1) diff --git a/Analysis/src/Frontend.cpp b/Analysis/src/Frontend.cpp index 125f2457..59ef9373 100644 --- a/Analysis/src/Frontend.cpp +++ b/Analysis/src/Frontend.cpp @@ -32,11 +32,9 @@ LUAU_FASTINT(LuauTypeInferRecursionLimit) LUAU_FASTINT(LuauTarjanChildLimit) LUAU_FASTFLAG(LuauInferInNoCheckMode) LUAU_FASTFLAGVARIABLE(LuauKnowsTheDataModel3, false) -LUAU_FASTINTVARIABLE(LuauAutocompleteCheckTimeoutMs, 100) // TODO: Remove with FFlagLuauTypecheckLimitControls LUAU_FASTFLAGVARIABLE(DebugLuauDeferredConstraintResolution, false) LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJson, false) LUAU_FASTFLAGVARIABLE(DebugLuauReadWriteProperties, false) -LUAU_FASTFLAGVARIABLE(LuauTypecheckLimitControls, false) LUAU_FASTFLAGVARIABLE(CorrectEarlyReturnInMarkDirty, false) LUAU_FASTFLAGVARIABLE(LuauDefinitionFileSetModuleName, false) @@ -902,82 +900,41 @@ void Frontend::checkBuildQueueItem(BuildQueueItem& item) TypeCheckLimits typeCheckLimits; - if (FFlag::LuauTypecheckLimitControls) + if (item.options.moduleTimeLimitSec) + typeCheckLimits.finishTime = TimeTrace::getClock() + *item.options.moduleTimeLimitSec; + else + typeCheckLimits.finishTime = std::nullopt; + + // TODO: This is a dirty ad hoc solution for autocomplete timeouts + // We are trying to dynamically adjust our existing limits to lower total typechecking time under the limit + // so that we'll have type information for the whole file at lower quality instead of a full abort in the middle + if (item.options.applyInternalLimitScaling) { - if (item.options.moduleTimeLimitSec) - typeCheckLimits.finishTime = TimeTrace::getClock() + *item.options.moduleTimeLimitSec; + if (FInt::LuauTarjanChildLimit > 0) + typeCheckLimits.instantiationChildLimit = std::max(1, int(FInt::LuauTarjanChildLimit * sourceNode.autocompleteLimitsMult)); else - typeCheckLimits.finishTime = std::nullopt; + typeCheckLimits.instantiationChildLimit = std::nullopt; - // TODO: This is a dirty ad hoc solution for autocomplete timeouts - // We are trying to dynamically adjust our existing limits to lower total typechecking time under the limit - // so that we'll have type information for the whole file at lower quality instead of a full abort in the middle - if (item.options.applyInternalLimitScaling) - { - if (FInt::LuauTarjanChildLimit > 0) - typeCheckLimits.instantiationChildLimit = std::max(1, int(FInt::LuauTarjanChildLimit * sourceNode.autocompleteLimitsMult)); - else - typeCheckLimits.instantiationChildLimit = std::nullopt; - - if (FInt::LuauTypeInferIterationLimit > 0) - typeCheckLimits.unifierIterationLimit = std::max(1, int(FInt::LuauTypeInferIterationLimit * sourceNode.autocompleteLimitsMult)); - else - typeCheckLimits.unifierIterationLimit = std::nullopt; - } - - typeCheckLimits.cancellationToken = item.options.cancellationToken; + if (FInt::LuauTypeInferIterationLimit > 0) + typeCheckLimits.unifierIterationLimit = std::max(1, int(FInt::LuauTypeInferIterationLimit * sourceNode.autocompleteLimitsMult)); + else + typeCheckLimits.unifierIterationLimit = std::nullopt; } + typeCheckLimits.cancellationToken = item.options.cancellationToken; + if (item.options.forAutocomplete) { - double autocompleteTimeLimit = FInt::LuauAutocompleteCheckTimeoutMs / 1000.0; - - if (!FFlag::LuauTypecheckLimitControls) - { - // The autocomplete typecheck is always in strict mode with DM awareness - // to provide better type information for IDE features - - if (autocompleteTimeLimit != 0.0) - typeCheckLimits.finishTime = TimeTrace::getClock() + autocompleteTimeLimit; - else - typeCheckLimits.finishTime = std::nullopt; - - // TODO: This is a dirty ad hoc solution for autocomplete timeouts - // We are trying to dynamically adjust our existing limits to lower total typechecking time under the limit - // so that we'll have type information for the whole file at lower quality instead of a full abort in the middle - if (FInt::LuauTarjanChildLimit > 0) - typeCheckLimits.instantiationChildLimit = std::max(1, int(FInt::LuauTarjanChildLimit * sourceNode.autocompleteLimitsMult)); - else - typeCheckLimits.instantiationChildLimit = std::nullopt; - - if (FInt::LuauTypeInferIterationLimit > 0) - typeCheckLimits.unifierIterationLimit = std::max(1, int(FInt::LuauTypeInferIterationLimit * sourceNode.autocompleteLimitsMult)); - else - typeCheckLimits.unifierIterationLimit = std::nullopt; - - typeCheckLimits.cancellationToken = item.options.cancellationToken; - } - // The autocomplete typecheck is always in strict mode with DM awareness to provide better type information for IDE features ModulePtr moduleForAutocomplete = check(sourceModule, Mode::Strict, requireCycles, environmentScope, /*forAutocomplete*/ true, /*recordJsonLog*/ false, typeCheckLimits); double duration = getTimestamp() - timestamp; - if (FFlag::LuauTypecheckLimitControls) - { - moduleForAutocomplete->checkDurationSec = duration; + moduleForAutocomplete->checkDurationSec = duration; - if (item.options.moduleTimeLimitSec && item.options.applyInternalLimitScaling) - applyInternalLimitScaling(sourceNode, moduleForAutocomplete, *item.options.moduleTimeLimitSec); - } - else - { - if (moduleForAutocomplete->timeout) - sourceNode.autocompleteLimitsMult = sourceNode.autocompleteLimitsMult / 2.0; - else if (duration < autocompleteTimeLimit / 2.0) - sourceNode.autocompleteLimitsMult = std::min(sourceNode.autocompleteLimitsMult * 2.0, 1.0); - } + if (item.options.moduleTimeLimitSec && item.options.applyInternalLimitScaling) + applyInternalLimitScaling(sourceNode, moduleForAutocomplete, *item.options.moduleTimeLimitSec); item.stats.timeCheck += duration; item.stats.filesStrict += 1; @@ -986,29 +943,16 @@ void Frontend::checkBuildQueueItem(BuildQueueItem& item) return; } - if (!FFlag::LuauTypecheckLimitControls) - { - typeCheckLimits.cancellationToken = item.options.cancellationToken; - } - ModulePtr module = check(sourceModule, mode, requireCycles, environmentScope, /*forAutocomplete*/ false, item.recordJsonLog, typeCheckLimits); - if (FFlag::LuauTypecheckLimitControls) - { - double duration = getTimestamp() - timestamp; + double duration = getTimestamp() - timestamp; - module->checkDurationSec = duration; + module->checkDurationSec = duration; - if (item.options.moduleTimeLimitSec && item.options.applyInternalLimitScaling) - applyInternalLimitScaling(sourceNode, module, *item.options.moduleTimeLimitSec); - - item.stats.timeCheck += duration; - } - else - { - item.stats.timeCheck += getTimestamp() - timestamp; - } + if (item.options.moduleTimeLimitSec && item.options.applyInternalLimitScaling) + applyInternalLimitScaling(sourceNode, module, *item.options.moduleTimeLimitSec); + item.stats.timeCheck += duration; item.stats.filesStrict += mode == Mode::Strict; item.stats.filesNonstrict += mode == Mode::Nonstrict; diff --git a/CLI/Bytecode.cpp b/CLI/Bytecode.cpp index 5002ce1d..76faa6fe 100644 --- a/CLI/Bytecode.cpp +++ b/CLI/Bytecode.cpp @@ -124,7 +124,7 @@ static bool analyzeFile(const char* name, const unsigned nestingLimit, std::vect { Luau::BytecodeBuilder bcb; - compileOrThrow(bcb, source.value(), copts()); + compileOrThrow(bcb, *source, copts()); const std::string& bytecode = bcb.getBytecode(); diff --git a/CodeGen/src/CodeGen.cpp b/CodeGen/src/CodeGen.cpp index 3e6f5e8b..84d3f900 100644 --- a/CodeGen/src/CodeGen.cpp +++ b/CodeGen/src/CodeGen.cpp @@ -42,8 +42,18 @@ LUAU_FASTFLAGVARIABLE(DebugCodegenNoOpt, false) LUAU_FASTFLAGVARIABLE(DebugCodegenOptSize, false) LUAU_FASTFLAGVARIABLE(DebugCodegenSkipNumbering, false) + +// Per-module IR instruction count limit LUAU_FASTINTVARIABLE(CodegenHeuristicsInstructionLimit, 1'048'576) // 1 M -LUAU_FASTINTVARIABLE(CodegenHeuristicsBlockLimit, 65'536) // 64 K + +// Per-function IR block limit +// Current value is based on some member variables being limited to 16 bits +// Because block check is made before optimization passes and optimization can generate new blocks, limit is lowered 2x +// The limit will probably be adjusted in the future to avoid performance issues with analysis that's more complex than O(n) +LUAU_FASTINTVARIABLE(CodegenHeuristicsBlockLimit, 32'768) // 32 K + +// Per-function IR instruction limit +// Current value is based on some member variables being limited to 16 bits LUAU_FASTINTVARIABLE(CodegenHeuristicsBlockInstructionLimit, 65'536) // 64 K namespace Luau @@ -104,11 +114,18 @@ static void logPerfFunction(Proto* p, uintptr_t addr, unsigned size) } template -static std::optional createNativeFunction(AssemblyBuilder& build, ModuleHelpers& helpers, Proto* proto) +static std::optional createNativeFunction(AssemblyBuilder& build, ModuleHelpers& helpers, Proto* proto, uint32_t& totalIrInstCount) { IrBuilder ir; ir.buildFunctionIr(proto); + unsigned instCount = unsigned(ir.function.instructions.size()); + + if (totalIrInstCount + instCount >= unsigned(FInt::CodegenHeuristicsInstructionLimit.value)) + return std::nullopt; + + totalIrInstCount += instCount; + if (!lowerFunction(ir, build, helpers, proto, {}, /* stats */ nullptr)) return std::nullopt; @@ -291,9 +308,13 @@ CodeGenCompilationResult compile(lua_State* L, int idx, unsigned int flags, Comp std::vector results; results.reserve(protos.size()); + uint32_t totalIrInstCount = 0; + for (Proto* p : protos) - if (std::optional np = createNativeFunction(build, helpers, p)) + { + if (std::optional np = createNativeFunction(build, helpers, p, totalIrInstCount)) results.push_back(*np); + } // Very large modules might result in overflowing a jump offset; in this case we currently abandon the entire module if (!build.finalize()) diff --git a/CodeGen/src/CodeGenLower.h b/CodeGen/src/CodeGenLower.h index 2ebe4349..3075ac9a 100644 --- a/CodeGen/src/CodeGenLower.h +++ b/CodeGen/src/CodeGenLower.h @@ -253,11 +253,6 @@ inline bool lowerIr(A64::AssemblyBuilderA64& build, IrBuilder& ir, const std::ve template inline bool lowerFunction(IrBuilder& ir, AssemblyBuilder& build, ModuleHelpers& helpers, Proto* proto, AssemblyOptions options, LoweringStats* stats) { - helpers.bytecodeInstructionCount += unsigned(ir.function.instructions.size()); - - if (helpers.bytecodeInstructionCount >= unsigned(FInt::CodegenHeuristicsInstructionLimit.value)) - return false; - killUnusedBlocks(ir.function); unsigned preOptBlockCount = 0; @@ -268,9 +263,7 @@ inline bool lowerFunction(IrBuilder& ir, AssemblyBuilder& build, ModuleHelpers& preOptBlockCount += (block.kind != IrBlockKind::Dead); unsigned blockInstructions = block.finish - block.start; maxBlockInstructions = std::max(maxBlockInstructions, blockInstructions); - }; - - helpers.preOptBlockCount += preOptBlockCount; + } // we update stats before checking the heuristic so that even if we bail out // our stats include information about the limit that was exceeded. @@ -280,9 +273,7 @@ inline bool lowerFunction(IrBuilder& ir, AssemblyBuilder& build, ModuleHelpers& stats->maxBlockInstructions = maxBlockInstructions; } - // we use helpers.blocksPreOpt instead of stats.blocksPreOpt since - // stats can be null across some code paths. - if (helpers.preOptBlockCount >= unsigned(FInt::CodegenHeuristicsBlockLimit.value)) + if (preOptBlockCount >= unsigned(FInt::CodegenHeuristicsBlockLimit.value)) return false; if (maxBlockInstructions >= unsigned(FInt::CodegenHeuristicsBlockInstructionLimit.value)) diff --git a/CodeGen/src/EmitCommon.h b/CodeGen/src/EmitCommon.h index f0e14103..013ba88f 100644 --- a/CodeGen/src/EmitCommon.h +++ b/CodeGen/src/EmitCommon.h @@ -31,9 +31,6 @@ struct ModuleHelpers // A64 Label continueCall; // x0: closure - - unsigned bytecodeInstructionCount = 0; - unsigned preOptBlockCount = 0; }; } // namespace CodeGen diff --git a/bench/bench_support.lua b/bench/bench_support.lua index 9e415fc1..da637ac9 100644 --- a/bench/bench_support.lua +++ b/bench/bench_support.lua @@ -66,7 +66,8 @@ end -- and 'false' otherwise. -- -- Example usage: --- local bench = script and require(script.Parent.bench_support) or require("bench_support") +-- local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +-- local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") -- function testFunc() -- ... -- end diff --git a/bench/gc/test_BinaryTree.lua b/bench/gc/test_BinaryTree.lua index 2a797382..36dff9de 100644 --- a/bench/gc/test_BinaryTree.lua +++ b/bench/gc/test_BinaryTree.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/gc/test_GC_Boehm_Trees.lua b/bench/gc/test_GC_Boehm_Trees.lua index 08af2742..8170103d 100644 --- a/bench/gc/test_GC_Boehm_Trees.lua +++ b/bench/gc/test_GC_Boehm_Trees.lua @@ -1,5 +1,6 @@ --!nonstrict -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") local stretchTreeDepth = 18 -- about 16Mb local longLivedTreeDepth = 16 -- about 4Mb diff --git a/bench/gc/test_GC_Tree_Pruning_Eager.lua b/bench/gc/test_GC_Tree_Pruning_Eager.lua index 2111d9ff..38aa7626 100644 --- a/bench/gc/test_GC_Tree_Pruning_Eager.lua +++ b/bench/gc/test_GC_Tree_Pruning_Eager.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() local count = 1 diff --git a/bench/gc/test_GC_Tree_Pruning_Gen.lua b/bench/gc/test_GC_Tree_Pruning_Gen.lua index f88bd7f4..85081f70 100644 --- a/bench/gc/test_GC_Tree_Pruning_Gen.lua +++ b/bench/gc/test_GC_Tree_Pruning_Gen.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() local count = 1 diff --git a/bench/gc/test_GC_Tree_Pruning_Lazy.lua b/bench/gc/test_GC_Tree_Pruning_Lazy.lua index 3ea6bbef..834ec1ab 100644 --- a/bench/gc/test_GC_Tree_Pruning_Lazy.lua +++ b/bench/gc/test_GC_Tree_Pruning_Lazy.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() local count = 1 diff --git a/bench/gc/test_GC_hashtable_Keyval.lua b/bench/gc/test_GC_hashtable_Keyval.lua index fcb24826..aa7481d3 100644 --- a/bench/gc/test_GC_hashtable_Keyval.lua +++ b/bench/gc/test_GC_hashtable_Keyval.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() local t = {} diff --git a/bench/gc/test_LB_mandel.lua b/bench/gc/test_LB_mandel.lua index fe5b4eb2..a8beb4fd 100644 --- a/bench/gc/test_LB_mandel.lua +++ b/bench/gc/test_LB_mandel.lua @@ -21,7 +21,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/gc/test_LargeTableCtor_array.lua b/bench/gc/test_LargeTableCtor_array.lua index 535877f7..016dfd2d 100644 --- a/bench/gc/test_LargeTableCtor_array.lua +++ b/bench/gc/test_LargeTableCtor_array.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/gc/test_LargeTableCtor_hash.lua b/bench/gc/test_LargeTableCtor_hash.lua index 6faf766a..c46a7ab4 100644 --- a/bench/gc/test_LargeTableCtor_hash.lua +++ b/bench/gc/test_LargeTableCtor_hash.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/gc/test_Pcall_pcall_yield.lua b/bench/gc/test_Pcall_pcall_yield.lua index ac46c79e..ae0a4b46 100644 --- a/bench/gc/test_Pcall_pcall_yield.lua +++ b/bench/gc/test_Pcall_pcall_yield.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/gc/test_SunSpider_3d-raytrace.lua b/bench/gc/test_SunSpider_3d-raytrace.lua index 60e4f61e..3c050df7 100644 --- a/bench/gc/test_SunSpider_3d-raytrace.lua +++ b/bench/gc/test_SunSpider_3d-raytrace.lua @@ -22,7 +22,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/gc/test_TableCreate_nil.lua b/bench/gc/test_TableCreate_nil.lua index 1eff20e9..707a2750 100644 --- a/bench/gc/test_TableCreate_nil.lua +++ b/bench/gc/test_TableCreate_nil.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/gc/test_TableCreate_number.lua b/bench/gc/test_TableCreate_number.lua index 620b5624..3e4305bd 100644 --- a/bench/gc/test_TableCreate_number.lua +++ b/bench/gc/test_TableCreate_number.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/gc/test_TableCreate_zerofill.lua b/bench/gc/test_TableCreate_zerofill.lua index 08c6c91b..fed439b4 100644 --- a/bench/gc/test_TableCreate_zerofill.lua +++ b/bench/gc/test_TableCreate_zerofill.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/gc/test_TableMarshal_select.lua b/bench/gc/test_TableMarshal_select.lua index 110d9125..9869da60 100644 --- a/bench/gc/test_TableMarshal_select.lua +++ b/bench/gc/test_TableMarshal_select.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/gc/test_TableMarshal_table_pack.lua b/bench/gc/test_TableMarshal_table_pack.lua index 45810a3f..3da855f5 100644 --- a/bench/gc/test_TableMarshal_table_pack.lua +++ b/bench/gc/test_TableMarshal_table_pack.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/gc/test_TableMarshal_varargs.lua b/bench/gc/test_TableMarshal_varargs.lua index 19ef81fc..64b41b43 100644 --- a/bench/gc/test_TableMarshal_varargs.lua +++ b/bench/gc/test_TableMarshal_varargs.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_AbsSum_abs.lua b/bench/micro_tests/test_AbsSum_abs.lua index 33b6d7a3..7e85646e 100644 --- a/bench/micro_tests/test_AbsSum_abs.lua +++ b/bench/micro_tests/test_AbsSum_abs.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_AbsSum_and_or.lua b/bench/micro_tests/test_AbsSum_and_or.lua index a613c466..c6ef3dea 100644 --- a/bench/micro_tests/test_AbsSum_and_or.lua +++ b/bench/micro_tests/test_AbsSum_and_or.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_AbsSum_math_abs.lua b/bench/micro_tests/test_AbsSum_math_abs.lua index 2f529c6a..e95ea674 100644 --- a/bench/micro_tests/test_AbsSum_math_abs.lua +++ b/bench/micro_tests/test_AbsSum_math_abs.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_Assert.lua b/bench/micro_tests/test_Assert.lua index fcc99b49..014de8dc 100644 --- a/bench/micro_tests/test_Assert.lua +++ b/bench/micro_tests/test_Assert.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_Factorial.lua b/bench/micro_tests/test_Factorial.lua index 1742c4cf..90cff22a 100644 --- a/bench/micro_tests/test_Factorial.lua +++ b/bench/micro_tests/test_Factorial.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_Failure_pcall_a_bar.lua b/bench/micro_tests/test_Failure_pcall_a_bar.lua index 16dd1bf7..5b6108ba 100644 --- a/bench/micro_tests/test_Failure_pcall_a_bar.lua +++ b/bench/micro_tests/test_Failure_pcall_a_bar.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_Failure_pcall_game_Foo.lua b/bench/micro_tests/test_Failure_pcall_game_Foo.lua index 90fb3fc8..6bd209ae 100644 --- a/bench/micro_tests/test_Failure_pcall_game_Foo.lua +++ b/bench/micro_tests/test_Failure_pcall_game_Foo.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_Failure_xpcall_a_bar.lua b/bench/micro_tests/test_Failure_xpcall_a_bar.lua index 50bff4ba..e00a3ca6 100644 --- a/bench/micro_tests/test_Failure_xpcall_a_bar.lua +++ b/bench/micro_tests/test_Failure_xpcall_a_bar.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_Failure_xpcall_game_Foo.lua b/bench/micro_tests/test_Failure_xpcall_game_Foo.lua index 5e91e38f..86dadc90 100644 --- a/bench/micro_tests/test_Failure_xpcall_game_Foo.lua +++ b/bench/micro_tests/test_Failure_xpcall_game_Foo.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_LargeTableCtor_array.lua b/bench/micro_tests/test_LargeTableCtor_array.lua index 535877f7..016dfd2d 100644 --- a/bench/micro_tests/test_LargeTableCtor_array.lua +++ b/bench/micro_tests/test_LargeTableCtor_array.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_LargeTableCtor_hash.lua b/bench/micro_tests/test_LargeTableCtor_hash.lua index 6faf766a..c46a7ab4 100644 --- a/bench/micro_tests/test_LargeTableCtor_hash.lua +++ b/bench/micro_tests/test_LargeTableCtor_hash.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_LargeTableSum_loop_index.lua b/bench/micro_tests/test_LargeTableSum_loop_index.lua index 2b65073c..2aae109e 100644 --- a/bench/micro_tests/test_LargeTableSum_loop_index.lua +++ b/bench/micro_tests/test_LargeTableSum_loop_index.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_LargeTableSum_loop_ipairs.lua b/bench/micro_tests/test_LargeTableSum_loop_ipairs.lua index b0c1085f..29205e26 100644 --- a/bench/micro_tests/test_LargeTableSum_loop_ipairs.lua +++ b/bench/micro_tests/test_LargeTableSum_loop_ipairs.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_LargeTableSum_loop_iter.lua b/bench/micro_tests/test_LargeTableSum_loop_iter.lua index 057420f6..ea2b157c 100644 --- a/bench/micro_tests/test_LargeTableSum_loop_iter.lua +++ b/bench/micro_tests/test_LargeTableSum_loop_iter.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_LargeTableSum_loop_pairs.lua b/bench/micro_tests/test_LargeTableSum_loop_pairs.lua index 55b84867..8d789fcf 100644 --- a/bench/micro_tests/test_LargeTableSum_loop_pairs.lua +++ b/bench/micro_tests/test_LargeTableSum_loop_pairs.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_MethodCalls.lua b/bench/micro_tests/test_MethodCalls.lua index fa56005f..f8b44527 100644 --- a/bench/micro_tests/test_MethodCalls.lua +++ b/bench/micro_tests/test_MethodCalls.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_OOP_constructor.lua b/bench/micro_tests/test_OOP_constructor.lua index 6e3633ce..9fec3b67 100644 --- a/bench/micro_tests/test_OOP_constructor.lua +++ b/bench/micro_tests/test_OOP_constructor.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_OOP_method_call.lua b/bench/micro_tests/test_OOP_method_call.lua index c2c6c4ed..1e5249c5 100644 --- a/bench/micro_tests/test_OOP_method_call.lua +++ b/bench/micro_tests/test_OOP_method_call.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_OOP_virtual_constructor.lua b/bench/micro_tests/test_OOP_virtual_constructor.lua index 48b1e559..df99e13b 100644 --- a/bench/micro_tests/test_OOP_virtual_constructor.lua +++ b/bench/micro_tests/test_OOP_virtual_constructor.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_Pcall_call_return.lua b/bench/micro_tests/test_Pcall_call_return.lua index 9d07708c..2a612175 100644 --- a/bench/micro_tests/test_Pcall_call_return.lua +++ b/bench/micro_tests/test_Pcall_call_return.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_Pcall_pcall_return.lua b/bench/micro_tests/test_Pcall_pcall_return.lua index a6ff3599..16bdfdd3 100644 --- a/bench/micro_tests/test_Pcall_pcall_return.lua +++ b/bench/micro_tests/test_Pcall_pcall_return.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_Pcall_pcall_yield.lua b/bench/micro_tests/test_Pcall_pcall_yield.lua index ac46c79e..ae0a4b46 100644 --- a/bench/micro_tests/test_Pcall_pcall_yield.lua +++ b/bench/micro_tests/test_Pcall_pcall_yield.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_Pcall_xpcall_return.lua b/bench/micro_tests/test_Pcall_xpcall_return.lua index a64eddfd..8ac2f0eb 100644 --- a/bench/micro_tests/test_Pcall_xpcall_return.lua +++ b/bench/micro_tests/test_Pcall_xpcall_return.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_SqrtSum_exponent.lua b/bench/micro_tests/test_SqrtSum_exponent.lua index eaddbfdd..bfd6fd72 100644 --- a/bench/micro_tests/test_SqrtSum_exponent.lua +++ b/bench/micro_tests/test_SqrtSum_exponent.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_SqrtSum_math_sqrt.lua b/bench/micro_tests/test_SqrtSum_math_sqrt.lua index 44b61cc9..1e1f42c7 100644 --- a/bench/micro_tests/test_SqrtSum_math_sqrt.lua +++ b/bench/micro_tests/test_SqrtSum_math_sqrt.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_SqrtSum_sqrt.lua b/bench/micro_tests/test_SqrtSum_sqrt.lua index 34d8b385..96880e7b 100644 --- a/bench/micro_tests/test_SqrtSum_sqrt.lua +++ b/bench/micro_tests/test_SqrtSum_sqrt.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_SqrtSum_sqrt_getfenv.lua b/bench/micro_tests/test_SqrtSum_sqrt_getfenv.lua index 242edb85..55f29e2e 100644 --- a/bench/micro_tests/test_SqrtSum_sqrt_getfenv.lua +++ b/bench/micro_tests/test_SqrtSum_sqrt_getfenv.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_SqrtSum_sqrt_roundabout.lua b/bench/micro_tests/test_SqrtSum_sqrt_roundabout.lua index fa8bfd0a..bbe48a64 100644 --- a/bench/micro_tests/test_SqrtSum_sqrt_roundabout.lua +++ b/bench/micro_tests/test_SqrtSum_sqrt_roundabout.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_StringInterp.lua b/bench/micro_tests/test_StringInterp.lua index 1e7ccbc7..55430519 100644 --- a/bench/micro_tests/test_StringInterp.lua +++ b/bench/micro_tests/test_StringInterp.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") bench.runCode(function() for j=1,1e6 do diff --git a/bench/micro_tests/test_TableCreate_nil.lua b/bench/micro_tests/test_TableCreate_nil.lua index 1eff20e9..707a2750 100644 --- a/bench/micro_tests/test_TableCreate_nil.lua +++ b/bench/micro_tests/test_TableCreate_nil.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableCreate_number.lua b/bench/micro_tests/test_TableCreate_number.lua index 620b5624..3e4305bd 100644 --- a/bench/micro_tests/test_TableCreate_number.lua +++ b/bench/micro_tests/test_TableCreate_number.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableCreate_zerofill.lua b/bench/micro_tests/test_TableCreate_zerofill.lua index 08c6c91b..fed439b4 100644 --- a/bench/micro_tests/test_TableCreate_zerofill.lua +++ b/bench/micro_tests/test_TableCreate_zerofill.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableFind_loop_ipairs.lua b/bench/micro_tests/test_TableFind_loop_ipairs.lua index f363013d..46560274 100644 --- a/bench/micro_tests/test_TableFind_loop_ipairs.lua +++ b/bench/micro_tests/test_TableFind_loop_ipairs.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableFind_table_find.lua b/bench/micro_tests/test_TableFind_table_find.lua index a7619fce..3f22122f 100644 --- a/bench/micro_tests/test_TableFind_table_find.lua +++ b/bench/micro_tests/test_TableFind_table_find.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableInsertion_index_cached.lua b/bench/micro_tests/test_TableInsertion_index_cached.lua index 7f75b022..0c34818f 100644 --- a/bench/micro_tests/test_TableInsertion_index_cached.lua +++ b/bench/micro_tests/test_TableInsertion_index_cached.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableInsertion_index_len.lua b/bench/micro_tests/test_TableInsertion_index_len.lua index b9f71e0e..120a5e28 100644 --- a/bench/micro_tests/test_TableInsertion_index_len.lua +++ b/bench/micro_tests/test_TableInsertion_index_len.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableInsertion_table_insert.lua b/bench/micro_tests/test_TableInsertion_table_insert.lua index 9efccd4d..1ad3fe22 100644 --- a/bench/micro_tests/test_TableInsertion_table_insert.lua +++ b/bench/micro_tests/test_TableInsertion_table_insert.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableInsertion_table_insert_index.lua b/bench/micro_tests/test_TableInsertion_table_insert_index.lua index af2292ba..41747139 100644 --- a/bench/micro_tests/test_TableInsertion_table_insert_index.lua +++ b/bench/micro_tests/test_TableInsertion_table_insert_index.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableIteration.lua b/bench/micro_tests/test_TableIteration.lua index 47a94a3b..5f78a48b 100644 --- a/bench/micro_tests/test_TableIteration.lua +++ b/bench/micro_tests/test_TableIteration.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableMarshal_select.lua b/bench/micro_tests/test_TableMarshal_select.lua index 110d9125..9869da60 100644 --- a/bench/micro_tests/test_TableMarshal_select.lua +++ b/bench/micro_tests/test_TableMarshal_select.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableMarshal_table_pack.lua b/bench/micro_tests/test_TableMarshal_table_pack.lua index 45810a3f..3da855f5 100644 --- a/bench/micro_tests/test_TableMarshal_table_pack.lua +++ b/bench/micro_tests/test_TableMarshal_table_pack.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableMarshal_table_unpack_array.lua b/bench/micro_tests/test_TableMarshal_table_unpack_array.lua index 67bc1efa..13d1d1c3 100644 --- a/bench/micro_tests/test_TableMarshal_table_unpack_array.lua +++ b/bench/micro_tests/test_TableMarshal_table_unpack_array.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableMarshal_table_unpack_range.lua b/bench/micro_tests/test_TableMarshal_table_unpack_range.lua index a678d8bf..e3aa68be 100644 --- a/bench/micro_tests/test_TableMarshal_table_unpack_range.lua +++ b/bench/micro_tests/test_TableMarshal_table_unpack_range.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableMarshal_varargs.lua b/bench/micro_tests/test_TableMarshal_varargs.lua index 19ef81fc..64b41b43 100644 --- a/bench/micro_tests/test_TableMarshal_varargs.lua +++ b/bench/micro_tests/test_TableMarshal_varargs.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableMove_empty_table.lua b/bench/micro_tests/test_TableMove_empty_table.lua index 75ce2729..39335564 100644 --- a/bench/micro_tests/test_TableMove_empty_table.lua +++ b/bench/micro_tests/test_TableMove_empty_table.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() local t = table.create(250001, 0) diff --git a/bench/micro_tests/test_TableMove_same_table.lua b/bench/micro_tests/test_TableMove_same_table.lua index 81576573..f62022b1 100644 --- a/bench/micro_tests/test_TableMove_same_table.lua +++ b/bench/micro_tests/test_TableMove_same_table.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() local t = table.create(5000001, 0) diff --git a/bench/micro_tests/test_TableMove_table_create.lua b/bench/micro_tests/test_TableMove_table_create.lua index 19dfd186..f03c4de7 100644 --- a/bench/micro_tests/test_TableMove_table_create.lua +++ b/bench/micro_tests/test_TableMove_table_create.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() local t = table.create(250001, 0) diff --git a/bench/micro_tests/test_TableRemoval_table_remove.lua b/bench/micro_tests/test_TableRemoval_table_remove.lua index 25acd541..13410116 100644 --- a/bench/micro_tests/test_TableRemoval_table_remove.lua +++ b/bench/micro_tests/test_TableRemoval_table_remove.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_TableSort.lua b/bench/micro_tests/test_TableSort.lua index 80031d1c..502cb2a5 100644 --- a/bench/micro_tests/test_TableSort.lua +++ b/bench/micro_tests/test_TableSort.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") local arr_months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"} diff --git a/bench/micro_tests/test_ToNumberString.lua b/bench/micro_tests/test_ToNumberString.lua index 61104783..842b7c22 100644 --- a/bench/micro_tests/test_ToNumberString.lua +++ b/bench/micro_tests/test_ToNumberString.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") bench.runCode(function() for j=1,1e6 do diff --git a/bench/micro_tests/test_UpvalueCapture.lua b/bench/micro_tests/test_UpvalueCapture.lua index 96e8f576..4a2608c4 100644 --- a/bench/micro_tests/test_UpvalueCapture.lua +++ b/bench/micro_tests/test_UpvalueCapture.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_VariadicSelect.lua b/bench/micro_tests/test_VariadicSelect.lua index 668956f4..5a62f2d8 100644 --- a/bench/micro_tests/test_VariadicSelect.lua +++ b/bench/micro_tests/test_VariadicSelect.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/micro_tests/test_string_lib.lua b/bench/micro_tests/test_string_lib.lua index 3994c778..041f5b15 100644 --- a/bench/micro_tests/test_string_lib.lua +++ b/bench/micro_tests/test_string_lib.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") bench.runCode(function() local src = string.rep("abcdefghijklmnopqrstuvwxyz", 100) diff --git a/bench/micro_tests/test_table_concat.lua b/bench/micro_tests/test_table_concat.lua index 430ad0ab..590b7d4a 100644 --- a/bench/micro_tests/test_table_concat.lua +++ b/bench/micro_tests/test_table_concat.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") bench.runCode(function() for outer=1,28,3 do diff --git a/bench/tests/base64.lua b/bench/tests/base64.lua index 3755c54f..e580c595 100644 --- a/bench/tests/base64.lua +++ b/bench/tests/base64.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/tests/chess.lua b/bench/tests/chess.lua index f6ae2cc6..f551139e 100644 --- a/bench/tests/chess.lua +++ b/bench/tests/chess.lua @@ -1,5 +1,6 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") local RANKS = "12345678" local FILES = "abcdefgh" diff --git a/bench/tests/life.lua b/bench/tests/life.lua index 51586ad7..d050b013 100644 --- a/bench/tests/life.lua +++ b/bench/tests/life.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/tests/matrixmult.lua b/bench/tests/matrixmult.lua index d8dd4cc3..af38cb64 100644 --- a/bench/tests/matrixmult.lua +++ b/bench/tests/matrixmult.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") local function mmul(matrix1, matrix2) local shapeRows = #matrix1 diff --git a/bench/tests/mesh-normal-scalar.lua b/bench/tests/mesh-normal-scalar.lua index 368fa2fd..05bef373 100644 --- a/bench/tests/mesh-normal-scalar.lua +++ b/bench/tests/mesh-normal-scalar.lua @@ -1,5 +1,6 @@ --!strict -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/tests/pcmmix.lua b/bench/tests/pcmmix.lua index a1760f67..c98cee2c 100644 --- a/bench/tests/pcmmix.lua +++ b/bench/tests/pcmmix.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") local samples = 100_000 diff --git a/bench/tests/qsort.lua b/bench/tests/qsort.lua index 99037176..566c1b98 100644 --- a/bench/tests/qsort.lua +++ b/bench/tests/qsort.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/tests/sha256.lua b/bench/tests/sha256.lua index a01e801e..2ac0ab33 100644 --- a/bench/tests/sha256.lua +++ b/bench/tests/sha256.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/tests/shootout/ack.lua b/bench/tests/shootout/ack.lua index 540e8594..f7fd43a8 100644 --- a/bench/tests/shootout/ack.lua +++ b/bench/tests/shootout/ack.lua @@ -23,7 +23,8 @@ SOFTWARE. ]] -- http://www.bagley.org/~doug/shootout/ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/shootout/binary-trees.lua b/bench/tests/shootout/binary-trees.lua index a3c5ae64..89c5933c 100644 --- a/bench/tests/shootout/binary-trees.lua +++ b/bench/tests/shootout/binary-trees.lua @@ -25,7 +25,8 @@ SOFTWARE. -- http://benchmarksgame.alioth.debian.org/ -- contributed by Mike Pall -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/shootout/fannkuch-redux.lua b/bench/tests/shootout/fannkuch-redux.lua index e23f3a26..43bc9e41 100644 --- a/bench/tests/shootout/fannkuch-redux.lua +++ b/bench/tests/shootout/fannkuch-redux.lua @@ -25,7 +25,8 @@ SOFTWARE. -- http://benchmarksgame.alioth.debian.org/ -- contributed by Mike Pall -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/shootout/fixpoint-fact.lua b/bench/tests/shootout/fixpoint-fact.lua index 8e60e920..112acb4a 100644 --- a/bench/tests/shootout/fixpoint-fact.lua +++ b/bench/tests/shootout/fixpoint-fact.lua @@ -21,7 +21,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/shootout/heapsort.lua b/bench/tests/shootout/heapsort.lua index fe85859b..0daf97ab 100644 --- a/bench/tests/shootout/heapsort.lua +++ b/bench/tests/shootout/heapsort.lua @@ -21,7 +21,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/shootout/mandel.lua b/bench/tests/shootout/mandel.lua index fe5b4eb2..a3bbb7e5 100644 --- a/bench/tests/shootout/mandel.lua +++ b/bench/tests/shootout/mandel.lua @@ -21,7 +21,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/shootout/n-body.lua b/bench/tests/shootout/n-body.lua index 40341587..e0f9c63c 100644 --- a/bench/tests/shootout/n-body.lua +++ b/bench/tests/shootout/n-body.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/shootout/qt.lua b/bench/tests/shootout/qt.lua index 79cbe38b..d9b4a517 100644 --- a/bench/tests/shootout/qt.lua +++ b/bench/tests/shootout/qt.lua @@ -23,7 +23,8 @@ SOFTWARE. ]] -- Julia sets via interval cell-mapping (quadtree version) -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/shootout/queen.lua b/bench/tests/shootout/queen.lua index 185dabd8..c3508d60 100644 --- a/bench/tests/shootout/queen.lua +++ b/bench/tests/shootout/queen.lua @@ -21,7 +21,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/shootout/scimark.lua b/bench/tests/shootout/scimark.lua index ad0557b1..1b66df53 100644 --- a/bench/tests/shootout/scimark.lua +++ b/bench/tests/shootout/scimark.lua @@ -33,7 +33,8 @@ -- Modification to be compatible with Lua 5.3 ------------------------------------------------------------------------------ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/shootout/spectral-norm.lua b/bench/tests/shootout/spectral-norm.lua index 6d217aa6..b5116612 100644 --- a/bench/tests/shootout/spectral-norm.lua +++ b/bench/tests/shootout/spectral-norm.lua @@ -25,7 +25,8 @@ SOFTWARE. -- http://benchmarksgame.alioth.debian.org/ -- contributed by Mike Pall -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/sieve.lua b/bench/tests/sieve.lua index 718ec488..1bb45d99 100644 --- a/bench/tests/sieve.lua +++ b/bench/tests/sieve.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/tests/sunspider/3d-cube.lua b/bench/tests/sunspider/3d-cube.lua index 77fa0854..aac7a156 100644 --- a/bench/tests/sunspider/3d-cube.lua +++ b/bench/tests/sunspider/3d-cube.lua @@ -2,7 +2,8 @@ -- http://www.speich.net/computer/moztesting/3d.htm -- Created by Simon Speich -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/sunspider/3d-morph.lua b/bench/tests/sunspider/3d-morph.lua index 79e91419..8263f015 100644 --- a/bench/tests/sunspider/3d-morph.lua +++ b/bench/tests/sunspider/3d-morph.lua @@ -23,7 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/sunspider/3d-raytrace.lua b/bench/tests/sunspider/3d-raytrace.lua index 3d5276c7..33d464b8 100644 --- a/bench/tests/sunspider/3d-raytrace.lua +++ b/bench/tests/sunspider/3d-raytrace.lua @@ -22,7 +22,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/sunspider/controlflow-recursive.lua b/bench/tests/sunspider/controlflow-recursive.lua index a2591b2f..1c78a3c2 100644 --- a/bench/tests/sunspider/controlflow-recursive.lua +++ b/bench/tests/sunspider/controlflow-recursive.lua @@ -3,7 +3,8 @@ http://shootout.alioth.debian.org/ contributed by Isaac Gouy ]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/sunspider/crypto-aes.lua b/bench/tests/sunspider/crypto-aes.lua index e3f54087..9692cf52 100644 --- a/bench/tests/sunspider/crypto-aes.lua +++ b/bench/tests/sunspider/crypto-aes.lua @@ -9,7 +9,8 @@ * returns byte-array encrypted value (16 bytes) */]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") -- Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [ยง5.1.1] local Sbox = { 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, diff --git a/bench/tests/sunspider/fannkuch.lua b/bench/tests/sunspider/fannkuch.lua index ad77e83b..08cdcc24 100644 --- a/bench/tests/sunspider/fannkuch.lua +++ b/bench/tests/sunspider/fannkuch.lua @@ -3,7 +3,8 @@ http://shootout.alioth.debian.org/ contributed by Isaac Gouy ]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/sunspider/math-cordic.lua b/bench/tests/sunspider/math-cordic.lua index cdb10fa2..2b622377 100644 --- a/bench/tests/sunspider/math-cordic.lua +++ b/bench/tests/sunspider/math-cordic.lua @@ -23,7 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] - local bench = script and require(script.Parent.bench_support) or require("bench_support") + local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/sunspider/math-partial-sums.lua b/bench/tests/sunspider/math-partial-sums.lua index 9977ceff..f0b4b0b7 100644 --- a/bench/tests/sunspider/math-partial-sums.lua +++ b/bench/tests/sunspider/math-partial-sums.lua @@ -3,7 +3,8 @@ http://shootout.alioth.debian.org/ contributed by Isaac Gouy ]] -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") function test() diff --git a/bench/tests/sunspider/n-body-oop.lua b/bench/tests/sunspider/n-body-oop.lua index adcc15a7..e04286c8 100644 --- a/bench/tests/sunspider/n-body-oop.lua +++ b/bench/tests/sunspider/n-body-oop.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") local PI = 3.141592653589793 local SOLAR_MASS = 4 * PI * PI diff --git a/bench/tests/tictactoe.lua b/bench/tests/tictactoe.lua index 91d38f95..673dcd48 100644 --- a/bench/tests/tictactoe.lua +++ b/bench/tests/tictactoe.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/tests/trig.lua b/bench/tests/trig.lua index 702e699e..64bf611c 100644 --- a/bench/tests/trig.lua +++ b/bench/tests/trig.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") function test() diff --git a/bench/tests/voxelgen.lua b/bench/tests/voxelgen.lua index ae2cd861..b50a4592 100644 --- a/bench/tests/voxelgen.lua +++ b/bench/tests/voxelgen.lua @@ -1,4 +1,5 @@ -local bench = script and require(script.Parent.bench_support) or require("bench_support") +local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") -- Based on voxel terrain generator by Stickmasterluke diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt index 13d1a2a4..c18fbba5 100644 --- a/fuzz/CMakeLists.txt +++ b/fuzz/CMakeLists.txt @@ -1,5 +1,8 @@ # This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -cmake_minimum_required(VERSION 3.26) +if(${CMAKE_VERSION} VERSION_LESS "3.26") + message(WARNING "Building the Luau fuzzer requires Clang version 3.26 of higher.") + return() +endif() include(FetchContent) diff --git a/tests/Conformance.test.cpp b/tests/Conformance.test.cpp index 514211e1..a9c5bc37 100644 --- a/tests/Conformance.test.cpp +++ b/tests/Conformance.test.cpp @@ -33,6 +33,7 @@ LUAU_FASTFLAG(LuauCodeGenFixByteLower); LUAU_FASTFLAG(LuauCompileBufferAnnotation); LUAU_FASTFLAG(LuauLoopInterruptFix); LUAU_DYNAMIC_FASTFLAG(LuauStricterUtf8); +LUAU_FASTINT(CodegenHeuristicsInstructionLimit); static lua_CompileOptions defaultOptions() { @@ -2020,6 +2021,64 @@ TEST_CASE("HugeFunction") CHECK(lua_tonumber(L, -1) == 42); } +TEST_CASE("IrInstructionLimit") +{ + if (!codegen || !luau_codegen_supported()) + return; + + ScopedFastInt codegenHeuristicsInstructionLimit{FInt::CodegenHeuristicsInstructionLimit, 50'000}; + + std::string source; + + // Generate a hundred fat functions + for (int fn = 0; fn < 100; fn++) + { + source += "local function fn" + std::to_string(fn) + "(...)\n"; + source += "if ... then\n"; + source += "local p1, p2 = ...\n"; + source += "local _ = {\n"; + + for (int i = 0; i < 100; ++i) + { + source += "p1*0." + std::to_string(i) + ","; + source += "p2+0." + std::to_string(i) + ","; + } + + source += "}\n"; + source += "return _\n"; + source += "end\n"; + source += "end\n"; + } + + StateRef globalState(luaL_newstate(), lua_close); + lua_State* L = globalState.get(); + + luau_codegen_create(L); + + luaL_openlibs(L); + luaL_sandbox(L); + luaL_sandboxthread(L); + + size_t bytecodeSize = 0; + char* bytecode = luau_compile(source.data(), source.size(), nullptr, &bytecodeSize); + int result = luau_load(L, "=HugeFunction", bytecode, bytecodeSize, 0); + free(bytecode); + + REQUIRE(result == 0); + + Luau::CodeGen::CompilationStats nativeStats = {}; + Luau::CodeGen::CodeGenCompilationResult nativeResult = Luau::CodeGen::compile(L, -1, Luau::CodeGen::CodeGen_ColdFunctions, &nativeStats); + + // Limit is not hit immediately, so with some functions compiled it should be a success + CHECK(nativeResult != Luau::CodeGen::CodeGenCompilationResult::CodeGenFailed); + + // We should be able to compile at least one of our functions + CHECK(nativeStats.functionsCompiled > 0); + + // But because of the limit, not all of them (101 because there's an extra global function) + CHECK(nativeStats.functionsCompiled < 101); +} + TEST_CASE("BytecodeDistributionPerFunctionTest") { const char* source = R"( diff --git a/tests/DataFlowGraph.test.cpp b/tests/DataFlowGraph.test.cpp index 3488b90b..2ed26d97 100644 --- a/tests/DataFlowGraph.test.cpp +++ b/tests/DataFlowGraph.test.cpp @@ -341,6 +341,7 @@ TEST_CASE_FIXTURE(DataFlowGraphFixture, "property_lookup_on_a_phi_node") const Phi* phi = get(x3); REQUIRE(phi); + REQUIRE(phi->operands.size() == 2); CHECK(phi->operands.at(0) == x1); CHECK(phi->operands.at(1) == x2); } @@ -368,6 +369,7 @@ TEST_CASE_FIXTURE(DataFlowGraphFixture, "property_lookup_on_a_phi_node_2") const Phi* phi = get(x3); REQUIRE(phi); + REQUIRE(phi->operands.size() == 2); CHECK(phi->operands.at(0) == x2); CHECK(phi->operands.at(1) == x1); } @@ -408,8 +410,154 @@ TEST_CASE_FIXTURE(DataFlowGraphFixture, "property_lookup_on_a_phi_node_3") const Phi* phi = get(x3); REQUIRE(phi); + REQUIRE(phi->operands.size() == 2); CHECK(phi->operands.at(0) == x1); CHECK(phi->operands.at(1) == x2); } +TEST_CASE_FIXTURE(DataFlowGraphFixture, "function_captures_are_phi_nodes_of_all_versions") +{ + dfg(R"( + local x = 5 + + function f() + print(x) + x = nil + end + + f() + x = "five" + )"); + + DefId x1 = graph->getDef(query(module)->vars.data[0]); + DefId x2 = getDef(); // print(x) + DefId x3 = getDef(); // x = nil + DefId x4 = getDef(); // x = "five" + + CHECK(x1 != x2); + CHECK(x2 != x3); + CHECK(x3 != x4); + + const Phi* phi = get(x2); + REQUIRE(phi); + REQUIRE(phi->operands.size() == 3); + CHECK(phi->operands.at(0) == x1); + CHECK(phi->operands.at(1) == x3); + CHECK(phi->operands.at(2) == x4); +} + +TEST_CASE_FIXTURE(DataFlowGraphFixture, "function_captures_are_phi_nodes_of_all_versions_properties") +{ + dfg(R"( + local t = {} + t.x = 5 + + function f() + print(t.x) + t.x = nil + end + + f() + t.x = "five" + )"); + + DefId x1 = getDef(); // t.x = 5 + DefId x2 = getDef(); // print(t.x) + DefId x3 = getDef(); // t.x = nil + DefId x4 = getDef(); // t.x = "five" + + CHECK(x1 != x2); + CHECK(x2 != x3); + CHECK(x3 != x4); + + // When a local is referenced within a function, it is not pointer identical. + // Instead, it's a phi node of all possible versions, including just one version. + DefId t1 = graph->getDef(query(module)->vars.data[0]); + DefId t2 = getDef(); // print(t.x) + + const Phi* phi = get(t2); + REQUIRE(phi); + REQUIRE(phi->operands.size() == 1); + CHECK(phi->operands.at(0) == t1); +} + +TEST_CASE_FIXTURE(DataFlowGraphFixture, "local_f_which_is_prototyped_enclosed_by_function") +{ + dfg(R"( + local f + function f() + if cond() then + f() + end + end + )"); + + DefId f1 = graph->getDef(query(module)->vars.data[0]); + DefId f2 = getDef(); // function f() + DefId f3 = getDef(); // f() + + CHECK(f1 != f2); + CHECK(f2 != f3); + + const Phi* phi = get(f3); + REQUIRE(phi); + REQUIRE(phi->operands.size() == 1); + CHECK(phi->operands.at(0) == f2); +} + +TEST_CASE_FIXTURE(DataFlowGraphFixture, "local_f_which_is_prototyped_enclosed_by_function_has_some_prior_versions") +{ + dfg(R"( + local f + f = 5 + function f() + if cond() then + f() + end + end + )"); + + DefId f1 = graph->getDef(query(module)->vars.data[0]); + DefId f2 = getDef(); // f = 5 + DefId f3 = getDef(); // function f() + DefId f4 = getDef(); // f() + + CHECK(f1 != f2); + CHECK(f2 != f3); + CHECK(f3 != f4); + + const Phi* phi = get(f4); + REQUIRE(phi); + REQUIRE(phi->operands.size() == 1); + CHECK(phi->operands.at(0) == f3); +} + +TEST_CASE_FIXTURE(DataFlowGraphFixture, "local_f_which_is_prototyped_enclosed_by_function_has_some_future_versions") +{ + dfg(R"( + local f + function f() + if cond() then + f() + end + end + f = 5 + )"); + + DefId f1 = graph->getDef(query(module)->vars.data[0]); + DefId f2 = getDef(); // function f() + DefId f3 = getDef(); // f() + DefId f4 = getDef(); // f = 5 + + CHECK(f1 != f2); + CHECK(f2 != f3); + CHECK(f3 != f4); + + const Phi* phi = get(f3); + REQUIRE(phi); + REQUIRE(phi->operands.size() == 2); + CHECK(phi->operands.at(0) == f2); + CHECK(phi->operands.at(1) == f4); +} + TEST_SUITE_END(); diff --git a/tests/RequireByString.test.cpp b/tests/RequireByString.test.cpp index 49ee5050..f04d7fdf 100644 --- a/tests/RequireByString.test.cpp +++ b/tests/RequireByString.test.cpp @@ -56,15 +56,21 @@ public: for (int i = 0; i < 20; ++i) { - if (isDirectory(luauDirAbs + "/Luau/tests") || isDirectory(luauDirAbs + "/Client/Luau/tests")) + bool engineTestDir = isDirectory(luauDirAbs + "/Client/Luau/tests"); + bool luauTestDir = isDirectory(luauDirAbs + "/luau/tests"); + if (engineTestDir || luauTestDir) { - if (isDirectory(luauDirAbs + "/Client/Luau/tests")) + if (engineTestDir) { - luauDirRel += "/Client"; - luauDirAbs += "/Client"; + luauDirRel += "/Client/Luau"; + luauDirAbs += "/Client/Luau"; } - luauDirRel += "/Luau"; - luauDirAbs += "/Luau"; + else + { + luauDirRel += "/luau"; + luauDirAbs += "/luau"; + } + if (type == PathType::Relative) return luauDirRel; diff --git a/tests/TypeInfer.functions.test.cpp b/tests/TypeInfer.functions.test.cpp index 3cda9120..bc6477ad 100644 --- a/tests/TypeInfer.functions.test.cpp +++ b/tests/TypeInfer.functions.test.cpp @@ -736,7 +736,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "mutual_recursion") )"); LUAU_REQUIRE_NO_ERRORS(result); - dumpErrors(result); } TEST_CASE_FIXTURE(BuiltinsFixture, "toposort_doesnt_break_mutual_recursion") diff --git a/tests/TypeInfer.refinements.test.cpp b/tests/TypeInfer.refinements.test.cpp index e199ab1b..6dab86cc 100644 --- a/tests/TypeInfer.refinements.test.cpp +++ b/tests/TypeInfer.refinements.test.cpp @@ -1925,13 +1925,10 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "refine_unknown_to_table") // this test is DCR-only as an instance of DCR fixing a bug in the old solver CheckResult result = check(R"( - local idx, val - local function f(a: unknown) if typeof(a) == "table" then for i, v in a do - idx = i - val = v + return i, v end end end @@ -1939,17 +1936,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "refine_unknown_to_table") LUAU_REQUIRE_NO_ERRORS(result); - if (FFlag::DebugLuauDeferredConstraintResolution) - { - // Bug: We do not simplify at the right time - CHECK_EQ("unknown?", toString(requireType("idx"))); - CHECK_EQ("unknown?", toString(requireType("val"))); - } - else - { - CHECK_EQ("unknown", toString(requireType("idx"))); - CHECK_EQ("unknown", toString(requireType("val"))); - } + CHECK_EQ("(unknown) -> (unknown, unknown)", toString(requireType("f"))); } TEST_CASE_FIXTURE(BuiltinsFixture, "conditional_refinement_should_stay_error_suppressing") diff --git a/tests/TypeInfer.typestates.test.cpp b/tests/TypeInfer.typestates.test.cpp index e8044968..f269e129 100644 --- a/tests/TypeInfer.typestates.test.cpp +++ b/tests/TypeInfer.typestates.test.cpp @@ -315,4 +315,88 @@ TEST_CASE_FIXTURE(TypeStateFixture, "local_t_is_assigned_a_fresh_table_with_x_as CHECK("boolean | number | number | string" == toString(requireType("x"))); } +TEST_CASE_FIXTURE(TypeStateFixture, "captured_locals_are_unions_of_all_assignments") +{ + CheckResult result = check(R"( + local x = nil + + function f() + print(x) + x = "five" + end + + x = 5 + f() + )"); + + LUAU_REQUIRE_NO_ERRORS(result); + CHECK("(number | string)?" == toString(requireTypeAtPosition({4, 18}))); +} + +TEST_CASE_FIXTURE(TypeStateFixture, "captured_locals_are_unions_of_all_assignments_2") +{ + CheckResult result = check(R"( + local t = {x = nil} + + function f() + print(t.x) + t = {x = "five"} + end + + t = {x = 5} + f() + )"); + + LUAU_REQUIRE_NO_ERRORS(result); + CHECK("{ x: nil } | { x: number } | { x: string }" == toString(requireTypeAtPosition({4, 18}), {true})); + CHECK("(number | string)?" == toString(requireTypeAtPosition({4, 20}))); +} + +TEST_CASE_FIXTURE(TypeStateFixture, "prototyped_recursive_functions") +{ + CheckResult result = check(R"( + local f + function f() + if math.random() > 0.5 then + f() + end + end + )"); + + LUAU_REQUIRE_NO_ERRORS(result); + CHECK("(() -> ())?" == toString(requireType("f"))); +} + +TEST_CASE_FIXTURE(TypeStateFixture, "prototyped_recursive_functions_but_has_future_assignments") +{ + CheckResult result = check(R"( + local f + function f() + if math.random() > 0.5 then + f() + end + end + f = 5 + )"); + + LUAU_REQUIRE_ERROR_COUNT(1, result); + CHECK("((() -> ()) | number)?" == toString(requireType("f"))); +} + +TEST_CASE_FIXTURE(TypeStateFixture, "prototyped_recursive_functions_but_has_previous_assignments") +{ + CheckResult result = check(R"( + local f + f = 5 + function f() + if math.random() > 0.5 then + f() + end + end + )"); + + LUAU_REQUIRE_NO_ERRORS(result); + CHECK("((() -> ()) | number)?" == toString(requireType("f"))); +} + TEST_SUITE_END(); diff --git a/tools/faillist.txt b/tools/faillist.txt index 0ba9c249..03b4d90d 100644 --- a/tools/faillist.txt +++ b/tools/faillist.txt @@ -268,9 +268,12 @@ ProvisionalTests.typeguard_inference_incomplete ProvisionalTests.while_body_are_also_refined ProvisionalTests.xpcall_returns_what_f_returns RefinementTest.assert_a_to_be_truthy_then_assert_a_to_be_number +RefinementTest.assert_non_binary_expressions_actually_resolve_constraints +RefinementTest.correctly_lookup_a_shadowed_local_that_which_was_previously_refined RefinementTest.correctly_lookup_property_whose_base_was_previously_refined RefinementTest.dataflow_analysis_can_tell_refinements_when_its_appropriate_to_refine_into_nil_or_never RefinementTest.discriminate_from_truthiness_of_x +RefinementTest.either_number_or_string RefinementTest.fail_to_refine_a_property_of_subscript_expression RefinementTest.falsiness_of_TruthyPredicate_narrows_into_nil RefinementTest.function_call_with_colon_after_refining_not_to_be_nil @@ -288,6 +291,7 @@ RefinementTest.string_not_equal_to_string_or_nil RefinementTest.truthy_constraint_on_properties RefinementTest.type_annotations_arent_relevant_when_doing_dataflow_analysis RefinementTest.type_comparison_ifelse_expression +RefinementTest.type_guard_narrowed_into_nothingness RefinementTest.type_narrow_to_vector RefinementTest.typeguard_cast_free_table_to_vector RefinementTest.typeguard_in_assert_position @@ -394,6 +398,7 @@ TableTests.table_unifies_into_map TableTests.top_table_type TableTests.type_mismatch_on_massive_table_is_cut_short TableTests.unification_of_unions_in_a_self_referential_type +TableTests.unifying_tables_shouldnt_uaf1 TableTests.used_colon_instead_of_dot TableTests.used_dot_instead_of_colon TableTests.used_dot_instead_of_colon_but_correctly @@ -403,6 +408,7 @@ ToDot.function ToString.exhaustive_toString_of_cyclic_table ToString.free_types ToString.named_metatable_toStringNamedFunction +ToString.no_parentheses_around_cyclic_function_type_in_intersection ToString.pick_distinct_names_for_mixed_explicit_and_implicit_generics ToString.primitive ToString.tostring_unsee_ttv_if_array @@ -466,6 +472,7 @@ TypeInfer.no_stack_overflow_from_isoptional TypeInfer.promote_tail_type_packs TypeInfer.recursive_function_that_invokes_itself_with_a_refinement_of_its_parameter TypeInfer.recursive_function_that_invokes_itself_with_a_refinement_of_its_parameter_2 +TypeInfer.statements_are_topologically_sorted TypeInfer.stringify_nested_unions_with_optionals TypeInfer.tc_after_error_recovery_no_replacement_name_in_error TypeInfer.type_infer_recursion_limit_no_ice @@ -481,6 +488,7 @@ TypeInferAnyError.for_in_loop_iterator_is_error TypeInferAnyError.for_in_loop_iterator_is_error2 TypeInferAnyError.for_in_loop_iterator_returns_any TypeInferAnyError.intersection_of_any_can_have_props +TypeInferAnyError.metatable_of_any_can_be_a_table TypeInferAnyError.quantify_any_does_not_bind_to_itself TypeInferAnyError.replace_every_free_type_when_unifying_a_complex_function_with_any TypeInferAnyError.type_error_addition @@ -502,6 +510,7 @@ TypeInferFunctions.apply_of_lambda_with_inferred_and_explicit_types TypeInferFunctions.calling_function_with_anytypepack_doesnt_leak_free_types TypeInferFunctions.cannot_hoist_interior_defns_into_signature TypeInferFunctions.check_function_bodies +TypeInferFunctions.complicated_return_types_require_an_explicit_annotation TypeInferFunctions.concrete_functions_are_not_supertypes_of_function TypeInferFunctions.dont_assert_when_the_tarjan_limit_is_exceeded_during_generalization TypeInferFunctions.dont_give_other_overloads_message_if_only_one_argument_matching_overload_exists @@ -538,7 +547,9 @@ TypeInferFunctions.it_is_ok_to_oversaturate_a_higher_order_function_argument TypeInferFunctions.list_all_overloads_if_no_overload_takes_given_argument_count TypeInferFunctions.list_only_alternative_overloads_that_match_argument_count TypeInferFunctions.luau_subtyping_is_np_hard +TypeInferFunctions.mutual_recursion TypeInferFunctions.no_lossy_function_type +TypeInferFunctions.num_is_solved_after_num_or_str TypeInferFunctions.occurs_check_failure_in_function_return_type TypeInferFunctions.other_things_are_not_related_to_function TypeInferFunctions.param_1_and_2_both_takes_the_same_generic_but_their_arguments_are_incompatible @@ -554,6 +565,7 @@ TypeInferFunctions.too_many_arguments TypeInferFunctions.too_many_arguments_error_location TypeInferFunctions.too_many_return_values_in_parentheses TypeInferFunctions.too_many_return_values_no_function +TypeInferFunctions.toposort_doesnt_break_mutual_recursion TypeInferFunctions.vararg_function_is_quantified TypeInferLoops.cli_68448_iterators_need_not_accept_nil TypeInferLoops.dcr_iteration_explore_raycast_minimization @@ -598,6 +610,7 @@ TypeInferOOP.dont_suggest_using_colon_rather_than_dot_if_another_overload_works TypeInferOOP.dont_suggest_using_colon_rather_than_dot_if_it_wont_help_2 TypeInferOOP.dont_suggest_using_colon_rather_than_dot_if_not_defined_with_colon TypeInferOOP.inferring_hundreds_of_self_calls_should_not_suffocate_memory +TypeInferOOP.method_depends_on_table TypeInferOOP.methods_are_topologically_sorted TypeInferOOP.object_constructor_can_refer_to_method_of_self TypeInferOOP.promise_type_error_too_complex @@ -662,6 +675,7 @@ UnionTypes.disallow_less_specific_assign2 UnionTypes.error_detailed_optional UnionTypes.error_detailed_union_all UnionTypes.error_detailed_union_part +UnionTypes.error_takes_optional_arguments UnionTypes.generic_function_with_optional_arg UnionTypes.index_on_a_union_type_with_missing_property UnionTypes.index_on_a_union_type_with_mixed_types @@ -681,6 +695,7 @@ UnionTypes.optional_union_follow UnionTypes.optional_union_functions UnionTypes.optional_union_members UnionTypes.optional_union_methods +UnionTypes.return_types_can_be_disjoint UnionTypes.table_union_write_indirect UnionTypes.unify_unsealed_table_union_check UnionTypes.union_of_functions