diff --git a/Analysis/include/Luau/Constraint.h b/Analysis/include/Luau/Constraint.h index 3f3ad641..6a86072d 100644 --- a/Analysis/include/Luau/Constraint.h +++ b/Analysis/include/Luau/Constraint.h @@ -202,6 +202,10 @@ struct AssignPropConstraint std::string propName; TypeId rhsType; + /// If a new property is to be inserted into a table type, it will be + /// ascribed this location. + std::optional propLocation; + /// The canonical write type of the property. It is _solely_ used to /// populate astTypes during constraint resolution. Nothing should ever /// block on it. diff --git a/Analysis/src/ConstraintGenerator.cpp b/Analysis/src/ConstraintGenerator.cpp index f1ae5eae..a449949a 100644 --- a/Analysis/src/ConstraintGenerator.cpp +++ b/Analysis/src/ConstraintGenerator.cpp @@ -1246,6 +1246,9 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatTypeAlias* return ControlFlow::None; } + scope->typeAliasLocations[alias->name.value] = alias->location; + scope->typeAliasNameLocations[alias->name.value] = alias->nameLocation; + ScopePtr* defnScope = astTypeAliasDefiningScopes.find(alias); std::unordered_map* typeBindings; @@ -2441,7 +2444,7 @@ void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprIndexName* e bool incremented = recordPropertyAssignment(lhsTy); - auto apc = addConstraint(scope, expr->location, AssignPropConstraint{lhsTy, expr->index.value, rhsType, propTy, incremented}); + auto apc = addConstraint(scope, expr->location, AssignPropConstraint{lhsTy, expr->index.value, rhsType, expr->indexLocation, propTy, incremented}); getMutable(propTy)->setOwner(apc); } @@ -2457,7 +2460,7 @@ void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprIndexExpr* e bool incremented = recordPropertyAssignment(lhsTy); - auto apc = addConstraint(scope, expr->location, AssignPropConstraint{lhsTy, std::move(propName), rhsType, propTy, incremented}); + auto apc = addConstraint(scope, expr->location, AssignPropConstraint{lhsTy, std::move(propName), rhsType, expr->index->location, propTy, incremented}); getMutable(propTy)->setOwner(apc); return; @@ -2478,6 +2481,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprTable* expr, LUAU_ASSERT(ttv); ttv->state = TableState::Unsealed; + ttv->definitionModuleName = module->name; ttv->scope = scope.get(); interiorTypes.back().push_back(ty); @@ -2509,7 +2513,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprTable* expr, if (AstExprConstantString* key = item.key->as()) { std::string propName{key->value.data, key->value.size}; - ttv->props[propName] = {itemTy}; + ttv->props[propName] = {itemTy, /*deprecated*/ false, {}, key->location}; } else { diff --git a/Analysis/src/ConstraintSolver.cpp b/Analysis/src/ConstraintSolver.cpp index 8756ec44..c77581a7 100644 --- a/Analysis/src/ConstraintSolver.cpp +++ b/Analysis/src/ConstraintSolver.cpp @@ -486,6 +486,9 @@ void ConstraintSolver::run() progress |= runSolverPass(true); } while (progress); + if (!unsolvedConstraints.empty()) + reportError(InternalError{"Type inference failed to complete, you may see some confusing types and type errors."}, Location{}); + // After we have run all the constraints, type families should be generalized // At this point, we can try to perform one final simplification to suss out // whether type families are truly uninhabited or if they can reduce @@ -1729,7 +1732,10 @@ bool ConstraintSolver::tryDispatch(const AssignPropConstraint& c, NotNullstate == TableState::Unsealed || lhsTable->state == TableState::Free) { bind(constraint, c.propType, rhsType); - lhsTable->props[propName] = Property::rw(rhsType); + Property& newProp = lhsTable->props[propName]; + newProp.readTy = rhsType; + newProp.writeTy = rhsType; + newProp.location = c.propLocation; if (lhsTable->state == TableState::Unsealed && c.decrementPropCount) { diff --git a/Analysis/src/Frontend.cpp b/Analysis/src/Frontend.cpp index 4339960d..af3a89cd 100644 --- a/Analysis/src/Frontend.cpp +++ b/Analysis/src/Frontend.cpp @@ -41,6 +41,7 @@ LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJsonFile, false) LUAU_FASTFLAGVARIABLE(DebugLuauForbidInternalTypes, false) LUAU_FASTFLAGVARIABLE(DebugLuauForceStrictMode, false) LUAU_FASTFLAGVARIABLE(DebugLuauForceNonStrictMode, false) +LUAU_FASTFLAGVARIABLE(LuauSourceModuleUpdatedWithSelectedMode, false) namespace Luau { @@ -918,6 +919,9 @@ void Frontend::checkBuildQueueItem(BuildQueueItem& item) mode = Mode::Nonstrict; else mode = sourceModule.mode.value_or(config.mode); + + if (FFlag::LuauSourceModuleUpdatedWithSelectedMode) + item.sourceModule->mode = {mode}; ScopePtr environmentScope = item.environmentScope; double timestamp = getTimestamp(); const std::vector& requireCycles = item.requireCycles; @@ -1240,9 +1244,7 @@ ModulePtr check(const SourceModule& sourceModule, Mode mode, const std::vector(); result->name = sourceModule.name; result->humanReadableName = sourceModule.humanReadableName; - - result->mode = sourceModule.mode.value_or(Mode::NoCheck); - + result->mode = mode; result->internalTypes.owningModule = result.get(); result->interfaceTypes.owningModule = result.get(); @@ -1323,10 +1325,19 @@ ModulePtr check(const SourceModule& sourceModule, Mode mode, const std::vectorinterfaceTypes); diff --git a/Analysis/src/Normalize.cpp b/Analysis/src/Normalize.cpp index 16fe9546..17be78a5 100644 --- a/Analysis/src/Normalize.cpp +++ b/Analysis/src/Normalize.cpp @@ -255,8 +255,10 @@ bool isSubtype(const NormalizedStringType& subStr, const NormalizedStringType& s void NormalizedClassType::pushPair(TypeId ty, TypeIds negations) { - ordering.push_back(ty); - classes.insert(std::make_pair(ty, std::move(negations))); + auto result = classes.insert(std::make_pair(ty, std::move(negations))); + if (result.second) + ordering.push_back(ty); + LUAU_ASSERT(ordering.size() == classes.size()); } void NormalizedClassType::resetToNever() diff --git a/Analysis/src/Substitution.cpp b/Analysis/src/Substitution.cpp index 4e5dae07..91103ccb 100644 --- a/Analysis/src/Substitution.cpp +++ b/Analysis/src/Substitution.cpp @@ -753,7 +753,12 @@ void Substitution::replaceChildren(TypeId ty) for (auto& [name, prop] : ttv->props) { if (FFlag::DebugLuauDeferredConstraintResolution) - prop = Property::create(replace(prop.readTy), replace(prop.writeTy)); + { + if (prop.readTy) + prop.readTy = replace(prop.readTy); + if (prop.writeTy) + prop.writeTy = replace(prop.writeTy); + } else prop.setType(replace(prop.type())); } diff --git a/CodeGen/include/Luau/IrDump.h b/CodeGen/include/Luau/IrDump.h index d989a6c7..8fcb85dd 100644 --- a/CodeGen/include/Luau/IrDump.h +++ b/CodeGen/include/Luau/IrDump.h @@ -31,10 +31,8 @@ void toString(IrToStringContext& ctx, IrOp op); void toString(std::string& result, IrConst constant); -const char* getBytecodeTypeName_DEPRECATED(uint8_t type); const char* getBytecodeTypeName(uint8_t type, const char* const* userdataTypes); -void toString_DEPRECATED(std::string& result, const BytecodeTypes& bcTypes); void toString(std::string& result, const BytecodeTypes& bcTypes, const char* const* userdataTypes); void toStringDetailed( diff --git a/CodeGen/src/BytecodeAnalysis.cpp b/CodeGen/src/BytecodeAnalysis.cpp index b99d6336..023960b8 100644 --- a/CodeGen/src/BytecodeAnalysis.cpp +++ b/CodeGen/src/BytecodeAnalysis.cpp @@ -11,7 +11,6 @@ #include -LUAU_FASTFLAGVARIABLE(LuauCodegenUserdataOps, false) LUAU_FASTFLAGVARIABLE(LuauCodegenFastcall3, false) namespace Luau @@ -749,50 +748,27 @@ void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks) regTags[ra] = LBC_TYPE_ANY; - if (FFlag::LuauCodegenUserdataOps) + TString* str = gco2ts(function.proto->k[kc].value.gc); + const char* field = getstr(str); + + if (bcType.a == LBC_TYPE_VECTOR) { - TString* str = gco2ts(function.proto->k[kc].value.gc); - const char* field = getstr(str); - - if (bcType.a == LBC_TYPE_VECTOR) + if (str->len == 1) { - if (str->len == 1) - { - // Same handling as LOP_GETTABLEKS block in lvmexecute.cpp - case-insensitive comparison with "X" / "Y" / "Z" - char ch = field[0] | ' '; + // Same handling as LOP_GETTABLEKS block in lvmexecute.cpp - case-insensitive comparison with "X" / "Y" / "Z" + char ch = field[0] | ' '; - if (ch == 'x' || ch == 'y' || ch == 'z') - regTags[ra] = LBC_TYPE_NUMBER; - } + if (ch == 'x' || ch == 'y' || ch == 'z') + regTags[ra] = LBC_TYPE_NUMBER; + } - if (regTags[ra] == LBC_TYPE_ANY && hostHooks.vectorAccessBytecodeType) - regTags[ra] = hostHooks.vectorAccessBytecodeType(field, str->len); - } - else if (isCustomUserdataBytecodeType(bcType.a)) - { - if (regTags[ra] == LBC_TYPE_ANY && hostHooks.userdataAccessBytecodeType) - regTags[ra] = hostHooks.userdataAccessBytecodeType(bcType.a, field, str->len); - } + if (regTags[ra] == LBC_TYPE_ANY && hostHooks.vectorAccessBytecodeType) + regTags[ra] = hostHooks.vectorAccessBytecodeType(field, str->len); } - else + else if (isCustomUserdataBytecodeType(bcType.a)) { - if (bcType.a == LBC_TYPE_VECTOR) - { - TString* str = gco2ts(function.proto->k[kc].value.gc); - const char* field = getstr(str); - - if (str->len == 1) - { - // Same handling as LOP_GETTABLEKS block in lvmexecute.cpp - case-insensitive comparison with "X" / "Y" / "Z" - char ch = field[0] | ' '; - - if (ch == 'x' || ch == 'y' || ch == 'z') - regTags[ra] = LBC_TYPE_NUMBER; - } - - if (regTags[ra] == LBC_TYPE_ANY && hostHooks.vectorAccessBytecodeType) - regTags[ra] = hostHooks.vectorAccessBytecodeType(field, str->len); - } + if (regTags[ra] == LBC_TYPE_ANY && hostHooks.userdataAccessBytecodeType) + regTags[ra] = hostHooks.userdataAccessBytecodeType(bcType.a, field, str->len); } bcType.result = regTags[ra]; @@ -829,7 +805,7 @@ void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks) regTags[ra] = LBC_TYPE_NUMBER; else if (bcType.a == LBC_TYPE_VECTOR && bcType.b == LBC_TYPE_VECTOR) regTags[ra] = LBC_TYPE_VECTOR; - else if (FFlag::LuauCodegenUserdataOps && hostHooks.userdataMetamethodBytecodeType && + else if (hostHooks.userdataMetamethodBytecodeType && (isCustomUserdataBytecodeType(bcType.a) || isCustomUserdataBytecodeType(bcType.b))) regTags[ra] = hostHooks.userdataMetamethodBytecodeType(bcType.a, bcType.b, opcodeToHostMetamethod(op)); @@ -861,7 +837,7 @@ void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks) if (bcType.b == LBC_TYPE_NUMBER || bcType.b == LBC_TYPE_VECTOR) regTags[ra] = LBC_TYPE_VECTOR; } - else if (FFlag::LuauCodegenUserdataOps && hostHooks.userdataMetamethodBytecodeType && + else if (hostHooks.userdataMetamethodBytecodeType && (isCustomUserdataBytecodeType(bcType.a) || isCustomUserdataBytecodeType(bcType.b))) { regTags[ra] = hostHooks.userdataMetamethodBytecodeType(bcType.a, bcType.b, opcodeToHostMetamethod(op)); @@ -884,7 +860,7 @@ void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks) if (bcType.a == LBC_TYPE_NUMBER && bcType.b == LBC_TYPE_NUMBER) regTags[ra] = LBC_TYPE_NUMBER; - else if (FFlag::LuauCodegenUserdataOps && hostHooks.userdataMetamethodBytecodeType && + else if (hostHooks.userdataMetamethodBytecodeType && (isCustomUserdataBytecodeType(bcType.a) || isCustomUserdataBytecodeType(bcType.b))) regTags[ra] = hostHooks.userdataMetamethodBytecodeType(bcType.a, bcType.b, opcodeToHostMetamethod(op)); @@ -907,7 +883,7 @@ void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks) regTags[ra] = LBC_TYPE_NUMBER; else if (bcType.a == LBC_TYPE_VECTOR && bcType.b == LBC_TYPE_VECTOR) regTags[ra] = LBC_TYPE_VECTOR; - else if (FFlag::LuauCodegenUserdataOps && hostHooks.userdataMetamethodBytecodeType && + else if (hostHooks.userdataMetamethodBytecodeType && (isCustomUserdataBytecodeType(bcType.a) || isCustomUserdataBytecodeType(bcType.b))) regTags[ra] = hostHooks.userdataMetamethodBytecodeType(bcType.a, bcType.b, opcodeToHostMetamethod(op)); @@ -939,7 +915,7 @@ void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks) if (bcType.b == LBC_TYPE_NUMBER || bcType.b == LBC_TYPE_VECTOR) regTags[ra] = LBC_TYPE_VECTOR; } - else if (FFlag::LuauCodegenUserdataOps && hostHooks.userdataMetamethodBytecodeType && + else if (hostHooks.userdataMetamethodBytecodeType && (isCustomUserdataBytecodeType(bcType.a) || isCustomUserdataBytecodeType(bcType.b))) { regTags[ra] = hostHooks.userdataMetamethodBytecodeType(bcType.a, bcType.b, opcodeToHostMetamethod(op)); @@ -962,7 +938,7 @@ void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks) if (bcType.a == LBC_TYPE_NUMBER && bcType.b == LBC_TYPE_NUMBER) regTags[ra] = LBC_TYPE_NUMBER; - else if (FFlag::LuauCodegenUserdataOps && hostHooks.userdataMetamethodBytecodeType && + else if (hostHooks.userdataMetamethodBytecodeType && (isCustomUserdataBytecodeType(bcType.a) || isCustomUserdataBytecodeType(bcType.b))) regTags[ra] = hostHooks.userdataMetamethodBytecodeType(bcType.a, bcType.b, opcodeToHostMetamethod(op)); @@ -984,7 +960,7 @@ void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks) regTags[ra] = LBC_TYPE_NUMBER; else if (bcType.a == LBC_TYPE_VECTOR && bcType.b == LBC_TYPE_VECTOR) regTags[ra] = LBC_TYPE_VECTOR; - else if (FFlag::LuauCodegenUserdataOps && hostHooks.userdataMetamethodBytecodeType && + else if (hostHooks.userdataMetamethodBytecodeType && (isCustomUserdataBytecodeType(bcType.a) || isCustomUserdataBytecodeType(bcType.b))) regTags[ra] = hostHooks.userdataMetamethodBytecodeType(bcType.a, bcType.b, opcodeToHostMetamethod(op)); @@ -1014,7 +990,7 @@ void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks) if (bcType.b == LBC_TYPE_NUMBER || bcType.b == LBC_TYPE_VECTOR) regTags[ra] = LBC_TYPE_VECTOR; } - else if (FFlag::LuauCodegenUserdataOps && hostHooks.userdataMetamethodBytecodeType && + else if (hostHooks.userdataMetamethodBytecodeType && (isCustomUserdataBytecodeType(bcType.a) || isCustomUserdataBytecodeType(bcType.b))) { regTags[ra] = hostHooks.userdataMetamethodBytecodeType(bcType.a, bcType.b, opcodeToHostMetamethod(op)); @@ -1047,7 +1023,7 @@ void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks) regTags[ra] = LBC_TYPE_NUMBER; else if (bcType.a == LBC_TYPE_VECTOR) regTags[ra] = LBC_TYPE_VECTOR; - else if (FFlag::LuauCodegenUserdataOps && hostHooks.userdataMetamethodBytecodeType && isCustomUserdataBytecodeType(bcType.a)) + else if (hostHooks.userdataMetamethodBytecodeType && isCustomUserdataBytecodeType(bcType.a)) regTags[ra] = hostHooks.userdataMetamethodBytecodeType(bcType.a, LBC_TYPE_ANY, HostMetamethod::Minus); bcType.result = regTags[ra]; @@ -1203,26 +1179,13 @@ void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks) bcType.result = LBC_TYPE_FUNCTION; - if (FFlag::LuauCodegenUserdataOps) - { - TString* str = gco2ts(function.proto->k[kc].value.gc); - const char* field = getstr(str); + TString* str = gco2ts(function.proto->k[kc].value.gc); + const char* field = getstr(str); - if (bcType.a == LBC_TYPE_VECTOR && hostHooks.vectorNamecallBytecodeType) - knownNextCallResult = LuauBytecodeType(hostHooks.vectorNamecallBytecodeType(field, str->len)); - else if (isCustomUserdataBytecodeType(bcType.a) && hostHooks.userdataNamecallBytecodeType) - knownNextCallResult = LuauBytecodeType(hostHooks.userdataNamecallBytecodeType(bcType.a, field, str->len)); - } - else - { - if (bcType.a == LBC_TYPE_VECTOR && hostHooks.vectorNamecallBytecodeType) - { - TString* str = gco2ts(function.proto->k[kc].value.gc); - const char* field = getstr(str); - - knownNextCallResult = LuauBytecodeType(hostHooks.vectorNamecallBytecodeType(field, str->len)); - } - } + if (bcType.a == LBC_TYPE_VECTOR && hostHooks.vectorNamecallBytecodeType) + knownNextCallResult = LuauBytecodeType(hostHooks.vectorNamecallBytecodeType(field, str->len)); + else if (isCustomUserdataBytecodeType(bcType.a) && hostHooks.userdataNamecallBytecodeType) + knownNextCallResult = LuauBytecodeType(hostHooks.userdataNamecallBytecodeType(bcType.a, field, str->len)); break; } case LOP_CALL: diff --git a/CodeGen/src/CodeGenAssembly.cpp b/CodeGen/src/CodeGenAssembly.cpp index de8dcecf..f78586e5 100644 --- a/CodeGen/src/CodeGenAssembly.cpp +++ b/CodeGen/src/CodeGenAssembly.cpp @@ -12,7 +12,6 @@ #include "lapi.h" -LUAU_FASTFLAG(LuauLoadUserdataInfo) LUAU_FASTFLAG(LuauNativeAttribute) namespace Luau @@ -83,54 +82,9 @@ static void logFunctionHeader(AssemblyBuilder& build, Proto* proto) build.logAppend("\n"); } -template -static void logFunctionTypes_DEPRECATED(AssemblyBuilder& build, const IrFunction& function) -{ - CODEGEN_ASSERT(!FFlag::LuauLoadUserdataInfo); - - const BytecodeTypeInfo& typeInfo = function.bcTypeInfo; - - for (size_t i = 0; i < typeInfo.argumentTypes.size(); i++) - { - uint8_t ty = typeInfo.argumentTypes[i]; - - if (ty != LBC_TYPE_ANY) - { - if (const char* name = tryFindLocalName(function.proto, int(i), 0)) - build.logAppend("; R%d: %s [argument '%s']\n", int(i), getBytecodeTypeName_DEPRECATED(ty), name); - else - build.logAppend("; R%d: %s [argument]\n", int(i), getBytecodeTypeName_DEPRECATED(ty)); - } - } - - for (size_t i = 0; i < typeInfo.upvalueTypes.size(); i++) - { - uint8_t ty = typeInfo.upvalueTypes[i]; - - if (ty != LBC_TYPE_ANY) - { - if (const char* name = tryFindUpvalueName(function.proto, int(i))) - build.logAppend("; U%d: %s ['%s']\n", int(i), getBytecodeTypeName_DEPRECATED(ty), name); - else - build.logAppend("; U%d: %s\n", int(i), getBytecodeTypeName_DEPRECATED(ty)); - } - } - - for (const BytecodeRegTypeInfo& el : typeInfo.regTypes) - { - // Using last active position as the PC because 'startpc' for type info is before local is initialized - if (const char* name = tryFindLocalName(function.proto, el.reg, el.endpc - 1)) - build.logAppend("; R%d: %s from %d to %d [local '%s']\n", el.reg, getBytecodeTypeName_DEPRECATED(el.type), el.startpc, el.endpc, name); - else - build.logAppend("; R%d: %s from %d to %d\n", el.reg, getBytecodeTypeName_DEPRECATED(el.type), el.startpc, el.endpc); - } -} - template static void logFunctionTypes(AssemblyBuilder& build, const IrFunction& function, const char* const* userdataTypes) { - CODEGEN_ASSERT(FFlag::LuauLoadUserdataInfo); - const BytecodeTypeInfo& typeInfo = function.bcTypeInfo; for (size_t i = 0; i < typeInfo.argumentTypes.size(); i++) @@ -238,12 +192,7 @@ static std::string getAssemblyImpl(AssemblyBuilder& build, const TValue* func, A logFunctionHeader(build, p); if (options.includeIrTypes) - { - if (FFlag::LuauLoadUserdataInfo) - logFunctionTypes(build, ir.function, options.compilationOptions.userdataTypes); - else - logFunctionTypes_DEPRECATED(build, ir.function); - } + logFunctionTypes(build, ir.function, options.compilationOptions.userdataTypes); CodeGenCompilationResult result = CodeGenCompilationResult::Success; diff --git a/CodeGen/src/CodeGenLower.h b/CodeGen/src/CodeGenLower.h index e7701361..daeaa251 100644 --- a/CodeGen/src/CodeGenLower.h +++ b/CodeGen/src/CodeGenLower.h @@ -27,7 +27,6 @@ LUAU_FASTFLAG(DebugCodegenSkipNumbering) LUAU_FASTINT(CodegenHeuristicsInstructionLimit) LUAU_FASTINT(CodegenHeuristicsBlockLimit) LUAU_FASTINT(CodegenHeuristicsBlockInstructionLimit) -LUAU_FASTFLAG(LuauLoadUserdataInfo) LUAU_FASTFLAG(LuauNativeAttribute) namespace Luau @@ -179,10 +178,7 @@ inline bool lowerImpl(AssemblyBuilder& build, IrLowering& lowering, IrFunction& if (bcTypes.result != LBC_TYPE_ANY || bcTypes.a != LBC_TYPE_ANY || bcTypes.b != LBC_TYPE_ANY || bcTypes.c != LBC_TYPE_ANY) { - if (FFlag::LuauLoadUserdataInfo) - toString(ctx.result, bcTypes, options.compilationOptions.userdataTypes); - else - toString_DEPRECATED(ctx.result, bcTypes); + toString(ctx.result, bcTypes, options.compilationOptions.userdataTypes); build.logAppend("\n"); } diff --git a/CodeGen/src/IrBuilder.cpp b/CodeGen/src/IrBuilder.cpp index 1f4342f6..061bf388 100644 --- a/CodeGen/src/IrBuilder.cpp +++ b/CodeGen/src/IrBuilder.cpp @@ -13,7 +13,6 @@ #include -LUAU_FASTFLAG(LuauLoadUserdataInfo) LUAU_FASTFLAG(LuauCodegenInstG) LUAU_FASTFLAG(LuauCodegenFastcall3) @@ -102,16 +101,13 @@ static void buildArgumentTypeChecks(IrBuilder& build) build.inst(IrCmd::CHECK_TAG, load, build.constTag(LUA_TBUFFER), build.vmExit(kVmExitEntryGuardPc)); break; default: - if (FFlag::LuauLoadUserdataInfo) + if (tag >= LBC_TYPE_TAGGED_USERDATA_BASE && tag < LBC_TYPE_TAGGED_USERDATA_END) { - if (tag >= LBC_TYPE_TAGGED_USERDATA_BASE && tag < LBC_TYPE_TAGGED_USERDATA_END) - { - build.inst(IrCmd::CHECK_TAG, load, build.constTag(LUA_TUSERDATA), build.vmExit(kVmExitEntryGuardPc)); - } - else - { - CODEGEN_ASSERT(!"unknown argument type tag"); - } + build.inst(IrCmd::CHECK_TAG, load, build.constTag(LUA_TUSERDATA), build.vmExit(kVmExitEntryGuardPc)); + } + else + { + CODEGEN_ASSERT(!"unknown argument type tag"); } break; } diff --git a/CodeGen/src/IrDump.cpp b/CodeGen/src/IrDump.cpp index c4114d89..e54c2661 100644 --- a/CodeGen/src/IrDump.cpp +++ b/CodeGen/src/IrDump.cpp @@ -7,7 +7,6 @@ #include -LUAU_FASTFLAG(LuauLoadUserdataInfo) LUAU_FASTFLAG(LuauCodegenInstG) namespace Luau @@ -492,44 +491,8 @@ void toString(std::string& result, IrConst constant) } } -const char* getBytecodeTypeName_DEPRECATED(uint8_t type) -{ - CODEGEN_ASSERT(!FFlag::LuauLoadUserdataInfo); - - switch (type & ~LBC_TYPE_OPTIONAL_BIT) - { - case LBC_TYPE_NIL: - return (type & LBC_TYPE_OPTIONAL_BIT) != 0 ? "nil?" : "nil"; - case LBC_TYPE_BOOLEAN: - return (type & LBC_TYPE_OPTIONAL_BIT) != 0 ? "boolean?" : "boolean"; - case LBC_TYPE_NUMBER: - return (type & LBC_TYPE_OPTIONAL_BIT) != 0 ? "number?" : "number"; - case LBC_TYPE_STRING: - return (type & LBC_TYPE_OPTIONAL_BIT) != 0 ? "string?" : "string"; - case LBC_TYPE_TABLE: - return (type & LBC_TYPE_OPTIONAL_BIT) != 0 ? "table?" : "table"; - case LBC_TYPE_FUNCTION: - return (type & LBC_TYPE_OPTIONAL_BIT) != 0 ? "function?" : "function"; - case LBC_TYPE_THREAD: - return (type & LBC_TYPE_OPTIONAL_BIT) != 0 ? "thread?" : "thread"; - case LBC_TYPE_USERDATA: - return (type & LBC_TYPE_OPTIONAL_BIT) != 0 ? "userdata?" : "userdata"; - case LBC_TYPE_VECTOR: - return (type & LBC_TYPE_OPTIONAL_BIT) != 0 ? "vector?" : "vector"; - case LBC_TYPE_BUFFER: - return (type & LBC_TYPE_OPTIONAL_BIT) != 0 ? "buffer?" : "buffer"; - case LBC_TYPE_ANY: - return (type & LBC_TYPE_OPTIONAL_BIT) != 0 ? "any?" : "any"; - } - - CODEGEN_ASSERT(!"Unhandled type in getBytecodeTypeName"); - return nullptr; -} - const char* getBytecodeTypeName(uint8_t type, const char* const* userdataTypes) { - CODEGEN_ASSERT(FFlag::LuauLoadUserdataInfo); - // Optional bit should be handled externally type = type & ~LBC_TYPE_OPTIONAL_BIT; @@ -571,22 +534,8 @@ const char* getBytecodeTypeName(uint8_t type, const char* const* userdataTypes) return nullptr; } -void toString_DEPRECATED(std::string& result, const BytecodeTypes& bcTypes) -{ - CODEGEN_ASSERT(!FFlag::LuauLoadUserdataInfo); - - if (bcTypes.c != LBC_TYPE_ANY) - append(result, "%s <- %s, %s, %s", getBytecodeTypeName_DEPRECATED(bcTypes.result), getBytecodeTypeName_DEPRECATED(bcTypes.a), - getBytecodeTypeName_DEPRECATED(bcTypes.b), getBytecodeTypeName_DEPRECATED(bcTypes.c)); - else - append(result, "%s <- %s, %s", getBytecodeTypeName_DEPRECATED(bcTypes.result), getBytecodeTypeName_DEPRECATED(bcTypes.a), - getBytecodeTypeName_DEPRECATED(bcTypes.b)); -} - void toString(std::string& result, const BytecodeTypes& bcTypes, const char* const* userdataTypes) { - CODEGEN_ASSERT(FFlag::LuauLoadUserdataInfo); - append(result, "%s%s", getBytecodeTypeName(bcTypes.result, userdataTypes), (bcTypes.result & LBC_TYPE_OPTIONAL_BIT) != 0 ? "?" : ""); append(result, " <- "); append(result, "%s%s", getBytecodeTypeName(bcTypes.a, userdataTypes), (bcTypes.a & LBC_TYPE_OPTIONAL_BIT) != 0 ? "?" : ""); diff --git a/CodeGen/src/IrLoweringA64.cpp b/CodeGen/src/IrLoweringA64.cpp index ef51a4b1..b718be32 100644 --- a/CodeGen/src/IrLoweringA64.cpp +++ b/CodeGen/src/IrLoweringA64.cpp @@ -11,9 +11,6 @@ #include "lstate.h" #include "lgc.h" -LUAU_FASTFLAG(LuauCodegenUserdataOps) -LUAU_FASTFLAGVARIABLE(LuauCodegenUserdataAlloc, false) -LUAU_FASTFLAGVARIABLE(LuauCodegenUserdataOpsFixA64, false) LUAU_FASTFLAG(LuauCodegenFastcall3) LUAU_FASTFLAG(LuauCodegenMathSign) @@ -1077,8 +1074,6 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) } case IrCmd::NEW_USERDATA: { - CODEGEN_ASSERT(FFlag::LuauCodegenUserdataAlloc); - regs.spill(build, index); build.mov(x0, rState); build.mov(x1, intOp(inst.a)); @@ -1708,18 +1703,11 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) } case IrCmd::CHECK_USERDATA_TAG: { - CODEGEN_ASSERT(FFlag::LuauCodegenUserdataOps); - Label fresh; // used when guard aborts execution or jumps to a VM exit Label& fail = getTargetLabel(inst.c, fresh); RegisterA64 temp = regs.allocTemp(KindA64::w); build.ldrb(temp, mem(regOp(inst.a), offsetof(Udata, tag))); - - if (FFlag::LuauCodegenUserdataOpsFixA64) - build.cmp(temp, intOp(inst.b)); - else - build.cmp(temp, tagOp(inst.b)); - + build.cmp(temp, intOp(inst.b)); build.b(ConditionA64::NotEqual, fail); finalizeTargetLabel(inst.c, fresh); break; @@ -2688,66 +2676,34 @@ AddressA64 IrLoweringA64::tempAddr(IrOp op, int offset) AddressA64 IrLoweringA64::tempAddrBuffer(IrOp bufferOp, IrOp indexOp, uint8_t tag) { - if (FFlag::LuauCodegenUserdataOps) + CODEGEN_ASSERT(tag == LUA_TUSERDATA || tag == LUA_TBUFFER); + int dataOffset = tag == LUA_TBUFFER ? offsetof(Buffer, data) : offsetof(Udata, data); + + if (indexOp.kind == IrOpKind::Inst) { - CODEGEN_ASSERT(tag == LUA_TUSERDATA || tag == LUA_TBUFFER); - int dataOffset = tag == LUA_TBUFFER ? offsetof(Buffer, data) : offsetof(Udata, data); + RegisterA64 temp = regs.allocTemp(KindA64::x); + build.add(temp, regOp(bufferOp), regOp(indexOp)); // implicit uxtw + return mem(temp, dataOffset); + } + else if (indexOp.kind == IrOpKind::Constant) + { + // Since the resulting address may be used to load any size, including 1 byte, from an unaligned offset, we are limited by unscaled + // encoding + if (unsigned(intOp(indexOp)) + dataOffset <= 255) + return mem(regOp(bufferOp), int(intOp(indexOp) + dataOffset)); - if (indexOp.kind == IrOpKind::Inst) - { - RegisterA64 temp = regs.allocTemp(KindA64::x); - build.add(temp, regOp(bufferOp), regOp(indexOp)); // implicit uxtw - return mem(temp, dataOffset); - } - else if (indexOp.kind == IrOpKind::Constant) - { - // Since the resulting address may be used to load any size, including 1 byte, from an unaligned offset, we are limited by unscaled - // encoding - if (unsigned(intOp(indexOp)) + dataOffset <= 255) - return mem(regOp(bufferOp), int(intOp(indexOp) + dataOffset)); + // indexOp can only be negative in dead code (since offsets are checked); this avoids assertion in emitAddOffset + if (intOp(indexOp) < 0) + return mem(regOp(bufferOp), dataOffset); - // indexOp can only be negative in dead code (since offsets are checked); this avoids assertion in emitAddOffset - if (intOp(indexOp) < 0) - return mem(regOp(bufferOp), dataOffset); - - RegisterA64 temp = regs.allocTemp(KindA64::x); - emitAddOffset(build, temp, regOp(bufferOp), size_t(intOp(indexOp))); - return mem(temp, dataOffset); - } - else - { - CODEGEN_ASSERT(!"Unsupported instruction form"); - return noreg; - } + RegisterA64 temp = regs.allocTemp(KindA64::x); + emitAddOffset(build, temp, regOp(bufferOp), size_t(intOp(indexOp))); + return mem(temp, dataOffset); } else { - if (indexOp.kind == IrOpKind::Inst) - { - RegisterA64 temp = regs.allocTemp(KindA64::x); - build.add(temp, regOp(bufferOp), regOp(indexOp)); // implicit uxtw - return mem(temp, offsetof(Buffer, data)); - } - else if (indexOp.kind == IrOpKind::Constant) - { - // Since the resulting address may be used to load any size, including 1 byte, from an unaligned offset, we are limited by unscaled - // encoding - if (unsigned(intOp(indexOp)) + offsetof(Buffer, data) <= 255) - return mem(regOp(bufferOp), int(intOp(indexOp) + offsetof(Buffer, data))); - - // indexOp can only be negative in dead code (since offsets are checked); this avoids assertion in emitAddOffset - if (intOp(indexOp) < 0) - return mem(regOp(bufferOp), offsetof(Buffer, data)); - - RegisterA64 temp = regs.allocTemp(KindA64::x); - emitAddOffset(build, temp, regOp(bufferOp), size_t(intOp(indexOp))); - return mem(temp, offsetof(Buffer, data)); - } - else - { - CODEGEN_ASSERT(!"Unsupported instruction form"); - return noreg; - } + CODEGEN_ASSERT(!"Unsupported instruction form"); + return noreg; } } diff --git a/CodeGen/src/IrLoweringX64.cpp b/CodeGen/src/IrLoweringX64.cpp index f372a7ec..f38370ce 100644 --- a/CodeGen/src/IrLoweringX64.cpp +++ b/CodeGen/src/IrLoweringX64.cpp @@ -15,8 +15,6 @@ #include "lstate.h" #include "lgc.h" -LUAU_FASTFLAG(LuauCodegenUserdataOps) -LUAU_FASTFLAG(LuauCodegenUserdataAlloc) LUAU_FASTFLAG(LuauCodegenFastcall3) LUAU_FASTFLAG(LuauCodegenMathSign) @@ -939,8 +937,6 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) } case IrCmd::NEW_USERDATA: { - CODEGEN_ASSERT(FFlag::LuauCodegenUserdataAlloc); - IrCallWrapperX64 callWrap(regs, build, index); callWrap.addArgument(SizeX64::qword, rState); callWrap.addArgument(SizeX64::qword, intOp(inst.a)); @@ -1421,8 +1417,6 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) } case IrCmd::CHECK_USERDATA_TAG: { - CODEGEN_ASSERT(FFlag::LuauCodegenUserdataOps); - build.cmp(byte[regOp(inst.a) + offsetof(Udata, tag)], intOp(inst.b)); jumpOrAbortOnUndef(ConditionX64::NotEqual, inst.c, next); break; @@ -2269,23 +2263,13 @@ RegisterX64 IrLoweringX64::regOp(IrOp op) OperandX64 IrLoweringX64::bufferAddrOp(IrOp bufferOp, IrOp indexOp, uint8_t tag) { - if (FFlag::LuauCodegenUserdataOps) - { - CODEGEN_ASSERT(tag == LUA_TUSERDATA || tag == LUA_TBUFFER); - int dataOffset = tag == LUA_TBUFFER ? offsetof(Buffer, data) : offsetof(Udata, data); + CODEGEN_ASSERT(tag == LUA_TUSERDATA || tag == LUA_TBUFFER); + int dataOffset = tag == LUA_TBUFFER ? offsetof(Buffer, data) : offsetof(Udata, data); - if (indexOp.kind == IrOpKind::Inst) - return regOp(bufferOp) + qwordReg(regOp(indexOp)) + dataOffset; - else if (indexOp.kind == IrOpKind::Constant) - return regOp(bufferOp) + intOp(indexOp) + dataOffset; - } - else - { - if (indexOp.kind == IrOpKind::Inst) - return regOp(bufferOp) + qwordReg(regOp(indexOp)) + offsetof(Buffer, data); - else if (indexOp.kind == IrOpKind::Constant) - return regOp(bufferOp) + intOp(indexOp) + offsetof(Buffer, data); - } + if (indexOp.kind == IrOpKind::Inst) + return regOp(bufferOp) + qwordReg(regOp(indexOp)) + dataOffset; + else if (indexOp.kind == IrOpKind::Constant) + return regOp(bufferOp) + intOp(indexOp) + dataOffset; CODEGEN_ASSERT(!"Unsupported instruction form"); return noreg; diff --git a/CodeGen/src/IrTranslation.cpp b/CodeGen/src/IrTranslation.cpp index db867fc9..59c616f9 100644 --- a/CodeGen/src/IrTranslation.cpp +++ b/CodeGen/src/IrTranslation.cpp @@ -13,7 +13,6 @@ #include "lstate.h" #include "ltm.h" -LUAU_FASTFLAG(LuauCodegenUserdataOps) LUAU_FASTFLAG(LuauCodegenFastcall3) namespace Luau @@ -444,7 +443,7 @@ static void translateInstBinaryNumeric(IrBuilder& build, int ra, int rb, int rc, return; } - if (FFlag::LuauCodegenUserdataOps && (isUserdataBytecodeType(bcTypes.a) || isUserdataBytecodeType(bcTypes.b))) + if (isUserdataBytecodeType(bcTypes.a) || isUserdataBytecodeType(bcTypes.b)) { if (build.hostHooks.userdataMetamethod && build.hostHooks.userdataMetamethod(build, bcTypes.a, bcTypes.b, ra, opb, opc, tmToHostMetamethod(tm), pcpos)) @@ -596,7 +595,7 @@ void translateInstMinus(IrBuilder& build, const Instruction* pc, int pcpos) return; } - if (FFlag::LuauCodegenUserdataOps && isUserdataBytecodeType(bcTypes.a)) + if (isUserdataBytecodeType(bcTypes.a)) { if (build.hostHooks.userdataMetamethod && build.hostHooks.userdataMetamethod(build, bcTypes.a, bcTypes.b, ra, build.vmReg(rb), {}, tmToHostMetamethod(TM_UNM), pcpos)) @@ -628,17 +627,7 @@ void translateInstMinus(IrBuilder& build, const Instruction* pc, int pcpos) FallbackStreamScope scope(build, fallback, next); build.inst(IrCmd::SET_SAVEDPC, build.constUint(pcpos + 1)); - - if (FFlag::LuauCodegenUserdataOps) - { - build.inst(IrCmd::DO_ARITH, build.vmReg(ra), build.vmReg(rb), build.vmReg(rb), build.constInt(TM_UNM)); - } - else - { - build.inst( - IrCmd::DO_ARITH, build.vmReg(LUAU_INSN_A(*pc)), build.vmReg(LUAU_INSN_B(*pc)), build.vmReg(LUAU_INSN_B(*pc)), build.constInt(TM_UNM)); - } - + build.inst(IrCmd::DO_ARITH, build.vmReg(ra), build.vmReg(rb), build.vmReg(rb), build.constInt(TM_UNM)); build.inst(IrCmd::JUMP, next); } } @@ -650,7 +639,7 @@ void translateInstLength(IrBuilder& build, const Instruction* pc, int pcpos) int ra = LUAU_INSN_A(*pc); int rb = LUAU_INSN_B(*pc); - if (FFlag::LuauCodegenUserdataOps && isUserdataBytecodeType(bcTypes.a)) + if (isUserdataBytecodeType(bcTypes.a)) { if (build.hostHooks.userdataMetamethod && build.hostHooks.userdataMetamethod(build, bcTypes.a, bcTypes.b, ra, build.vmReg(rb), {}, tmToHostMetamethod(TM_LEN), pcpos)) @@ -680,12 +669,7 @@ void translateInstLength(IrBuilder& build, const Instruction* pc, int pcpos) FallbackStreamScope scope(build, fallback, next); build.inst(IrCmd::SET_SAVEDPC, build.constUint(pcpos + 1)); - - if (FFlag::LuauCodegenUserdataOps) - build.inst(IrCmd::DO_LEN, build.vmReg(ra), build.vmReg(rb)); - else - build.inst(IrCmd::DO_LEN, build.vmReg(LUAU_INSN_A(*pc)), build.vmReg(LUAU_INSN_B(*pc))); - + build.inst(IrCmd::DO_LEN, build.vmReg(ra), build.vmReg(rb)); build.inst(IrCmd::JUMP, next); } @@ -1293,11 +1277,11 @@ void translateInstGetTableKS(IrBuilder& build, const Instruction* pc, int pcpos) return; } - if (FFlag::LuauCodegenUserdataOps ? isUserdataBytecodeType(bcTypes.a) : bcTypes.a == LBC_TYPE_USERDATA) + if (isUserdataBytecodeType(bcTypes.a)) { build.inst(IrCmd::CHECK_TAG, tb, build.constTag(LUA_TUSERDATA), build.vmExit(pcpos)); - if (FFlag::LuauCodegenUserdataOps && build.hostHooks.userdataAccess) + if (build.hostHooks.userdataAccess) { TString* str = gco2ts(build.function.proto->k[aux].value.gc); const char* field = getstr(str); @@ -1340,7 +1324,7 @@ void translateInstSetTableKS(IrBuilder& build, const Instruction* pc, int pcpos) IrOp tb = build.inst(IrCmd::LOAD_TAG, build.vmReg(rb)); - if (FFlag::LuauCodegenUserdataOps ? isUserdataBytecodeType(bcTypes.a) : bcTypes.a == LBC_TYPE_USERDATA) + if (isUserdataBytecodeType(bcTypes.a)) { build.inst(IrCmd::CHECK_TAG, tb, build.constTag(LUA_TUSERDATA), build.vmExit(pcpos)); @@ -1486,11 +1470,11 @@ bool translateInstNamecall(IrBuilder& build, const Instruction* pc, int pcpos) return false; } - if (FFlag::LuauCodegenUserdataOps ? isUserdataBytecodeType(bcTypes.a) : bcTypes.a == LBC_TYPE_USERDATA) + if (isUserdataBytecodeType(bcTypes.a)) { build.loadAndCheckTag(build.vmReg(rb), LUA_TUSERDATA, build.vmExit(pcpos)); - if (FFlag::LuauCodegenUserdataOps && build.hostHooks.userdataNamecall) + if (build.hostHooks.userdataNamecall) { Instruction call = pc[2]; CODEGEN_ASSERT(LUAU_INSN_OP(call) == LOP_CALL); diff --git a/CodeGen/src/NativeState.cpp b/CodeGen/src/NativeState.cpp index 7aa35f23..798ec314 100644 --- a/CodeGen/src/NativeState.cpp +++ b/CodeGen/src/NativeState.cpp @@ -14,8 +14,6 @@ #include #include -LUAU_FASTFLAG(LuauCodegenUserdataAlloc) - namespace Luau { namespace CodeGen @@ -91,9 +89,7 @@ void initFunctions(NativeContext& context) context.forgPrepXnextFallback = forgPrepXnextFallback; context.callProlog = callProlog; context.callEpilogC = callEpilogC; - - if (FFlag::LuauCodegenUserdataAlloc) - context.newUserdata = newUserdata; + context.newUserdata = newUserdata; context.callFallback = callFallback; diff --git a/CodeGen/src/OptimizeConstProp.cpp b/CodeGen/src/OptimizeConstProp.cpp index ac90f8e5..34a2a3d6 100644 --- a/CodeGen/src/OptimizeConstProp.cpp +++ b/CodeGen/src/OptimizeConstProp.cpp @@ -18,8 +18,6 @@ LUAU_FASTINTVARIABLE(LuauCodeGenMinLinearBlockPath, 3) LUAU_FASTINTVARIABLE(LuauCodeGenReuseSlotLimit, 64) LUAU_FASTINTVARIABLE(LuauCodeGenReuseUdataTagLimit, 64) LUAU_FASTFLAGVARIABLE(DebugLuauAbortingChecks, false) -LUAU_FASTFLAG(LuauCodegenUserdataOps) -LUAU_FASTFLAG(LuauCodegenUserdataAlloc) LUAU_FASTFLAG(LuauCodegenFastcall3) LUAU_FASTFLAG(LuauCodegenMathSign) @@ -425,9 +423,7 @@ struct ConstPropState invalidateValuePropagation(); invalidateHeapTableData(); invalidateHeapBufferData(); - - if (FFlag::LuauCodegenUserdataOps) - invalidateUserdataData(); + invalidateUserdataData(); } IrFunction& function; @@ -1051,8 +1047,6 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction& } case IrCmd::CHECK_USERDATA_TAG: { - CODEGEN_ASSERT(FFlag::LuauCodegenUserdataOps); - for (uint32_t prevIdx : state.useradataTagCache) { IrInst& prev = function.instructions[prevIdx]; @@ -1062,7 +1056,7 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction& if (prev.a != inst.a || prev.b != inst.b) continue; } - else if (FFlag::LuauCodegenUserdataAlloc && prev.cmd == IrCmd::NEW_USERDATA) + else if (prev.cmd == IrCmd::NEW_USERDATA) { if (inst.a.kind != IrOpKind::Inst || prevIdx != inst.a.index || prev.b != inst.b) continue; @@ -1244,8 +1238,6 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction& case IrCmd::TRY_CALL_FASTGETTM: break; case IrCmd::NEW_USERDATA: - CODEGEN_ASSERT(FFlag::LuauCodegenUserdataAlloc); - if (int(state.useradataTagCache.size()) < FInt::LuauCodeGenReuseUdataTagLimit) state.useradataTagCache.push_back(index); break; @@ -1532,9 +1524,7 @@ static void constPropInBlockChain(IrBuilder& build, std::vector& visite // Same for table and buffer data propagation state.invalidateHeapTableData(); state.invalidateHeapBufferData(); - - if (FFlag::LuauCodegenUserdataOps) - state.invalidateUserdataData(); + state.invalidateUserdataData(); // Blocks in a chain are guaranteed to follow each other // We force that by giving all blocks the same sorting key, but consecutive chain keys diff --git a/CodeGen/src/OptimizeDeadStore.cpp b/CodeGen/src/OptimizeDeadStore.cpp index 9fa6f062..34f647a7 100644 --- a/CodeGen/src/OptimizeDeadStore.cpp +++ b/CodeGen/src/OptimizeDeadStore.cpp @@ -9,8 +9,6 @@ #include "lobject.h" -LUAU_FASTFLAG(LuauCodegenUserdataOps) - // TODO: optimization can be improved by knowing which registers are live in at each VM exit namespace Luau @@ -596,8 +594,6 @@ static void markDeadStoresInInst(RemoveDeadStoreState& state, IrBuilder& build, state.checkLiveIns(inst.d); break; case IrCmd::CHECK_USERDATA_TAG: - CODEGEN_ASSERT(FFlag::LuauCodegenUserdataOps); - state.checkLiveIns(inst.c); break; diff --git a/VM/src/lvmload.cpp b/VM/src/lvmload.cpp index 112a7197..480c6f4e 100644 --- a/VM/src/lvmload.cpp +++ b/VM/src/lvmload.cpp @@ -13,8 +13,6 @@ #include -LUAU_FASTFLAGVARIABLE(LuauLoadUserdataInfo, false) - // TODO: RAII deallocation doesn't work for longjmp builds if a memory error happens template struct TempBuffer @@ -189,8 +187,6 @@ static void resolveImportSafe(lua_State* L, Table* env, TValue* k, uint32_t id) static void remapUserdataTypes(char* data, size_t size, uint8_t* userdataRemapping, uint32_t count) { - LUAU_ASSERT(FFlag::LuauLoadUserdataInfo); - size_t offset = 0; uint32_t typeSize = readVarInt(data, size, offset); @@ -287,16 +283,13 @@ int luau_load(lua_State* L, const char* chunkname, const char* data, size_t size { typesversion = read(data, size, offset); - if (FFlag::LuauLoadUserdataInfo) + if (typesversion < LBC_TYPE_VERSION_MIN || typesversion > LBC_TYPE_VERSION_MAX) { - if (typesversion < LBC_TYPE_VERSION_MIN || typesversion > LBC_TYPE_VERSION_MAX) - { - char chunkbuf[LUA_IDSIZE]; - const char* chunkid = luaO_chunkid(chunkbuf, sizeof(chunkbuf), chunkname, strlen(chunkname)); - lua_pushfstring(L, "%s: bytecode type version mismatch (expected [%d..%d], got %d)", chunkid, LBC_TYPE_VERSION_MIN, - LBC_TYPE_VERSION_MAX, typesversion); - return 1; - } + char chunkbuf[LUA_IDSIZE]; + const char* chunkid = luaO_chunkid(chunkbuf, sizeof(chunkbuf), chunkname, strlen(chunkname)); + lua_pushfstring(L, "%s: bytecode type version mismatch (expected [%d..%d], got %d)", chunkid, LBC_TYPE_VERSION_MIN, LBC_TYPE_VERSION_MAX, + typesversion); + return 1; } } @@ -317,7 +310,7 @@ int luau_load(lua_State* L, const char* chunkname, const char* data, size_t size const uint32_t userdataTypeLimit = LBC_TYPE_TAGGED_USERDATA_END - LBC_TYPE_TAGGED_USERDATA_BASE; uint8_t userdataRemapping[userdataTypeLimit]; - if (FFlag::LuauLoadUserdataInfo && typesversion == 3) + if (typesversion == 3) { memset(userdataRemapping, LBC_TYPE_USERDATA, userdataTypeLimit); @@ -393,7 +386,7 @@ int luau_load(lua_State* L, const char* chunkname, const char* data, size_t size offset += typesize; } - else if (typesversion == 2 || (FFlag::LuauLoadUserdataInfo && typesversion == 3)) + else if (typesversion == 2 || typesversion == 3) { uint32_t typesize = readVarInt(data, size, offset); @@ -406,7 +399,7 @@ int luau_load(lua_State* L, const char* chunkname, const char* data, size_t size memcpy(p->typeinfo, types, typesize); offset += typesize; - if (FFlag::LuauLoadUserdataInfo && typesversion == 3) + if (typesversion == 3) { remapUserdataTypes((char*)(uint8_t*)p->typeinfo, p->sizetypeinfo, userdataRemapping, userdataTypeLimit); } diff --git a/tests/Frontend.test.cpp b/tests/Frontend.test.cpp index 967dea43..9ae1a1de 100644 --- a/tests/Frontend.test.cpp +++ b/tests/Frontend.test.cpp @@ -1387,4 +1387,31 @@ TEST_CASE_FIXTURE(FrontendFixture, "no_separate_caches_with_the_new_solver") CHECK(module->mode == Mode::Nonstrict); } +TEST_CASE_FIXTURE(Fixture, "exported_tables_have_position_metadata") +{ + CheckResult result = check(R"( + return { abc = 22 } + )"); + + LUAU_REQUIRE_NO_ERRORS(result); + + ModulePtr mm = getMainModule(); + + TypePackId retTp = mm->getModuleScope()->returnType; + auto retHead = flatten(retTp).first; + REQUIRE(1 == retHead.size()); + + const TableType* tt = get(retHead[0]); + REQUIRE(tt); + + CHECK("MainModule" == tt->definitionModuleName); + + CHECK(1 == tt->props.size()); + CHECK(tt->props.count("abc")); + + const Property& prop = tt->props.find("abc")->second; + + CHECK(Location{Position{1, 17}, Position{1, 20}} == prop.location); +} + TEST_SUITE_END(); diff --git a/tests/IrLowering.test.cpp b/tests/IrLowering.test.cpp index 0ff8a12c..8af6d51b 100644 --- a/tests/IrLowering.test.cpp +++ b/tests/IrLowering.test.cpp @@ -16,9 +16,6 @@ #include LUAU_FASTFLAG(LuauCompileUserdataInfo) -LUAU_FASTFLAG(LuauLoadUserdataInfo) -LUAU_FASTFLAG(LuauCodegenUserdataOps) -LUAU_FASTFLAG(LuauCodegenUserdataAlloc) LUAU_FASTFLAG(LuauCompileFastcall3) LUAU_FASTFLAG(LuauCodegenFastcall3) @@ -1548,7 +1545,7 @@ TEST_CASE("CustomUserdataTypesTemp") if (!Luau::CodeGen::isSupported()) return; - ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, false}, {FFlag::LuauLoadUserdataInfo, true}}; + ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, false}}; CHECK_EQ("\n" + getCodegenHeader(R"( local function foo(v: vec2, x: mat3) @@ -1568,7 +1565,7 @@ TEST_CASE("CustomUserdataTypes") if (!Luau::CodeGen::isSupported()) return; - ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}, {FFlag::LuauLoadUserdataInfo, true}}; + ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}}; CHECK_EQ("\n" + getCodegenHeader(R"( local function foo(v: vec2, x: mat3) @@ -1588,7 +1585,7 @@ TEST_CASE("CustomUserdataPropertyAccess") if (!Luau::CodeGen::isSupported()) return; - ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}, {FFlag::LuauLoadUserdataInfo, true}, {FFlag::LuauCodegenUserdataOps, true}}; + ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}}; CHECK_EQ("\n" + getCodegenAssembly(R"( local function foo(v: vec2) @@ -1623,7 +1620,7 @@ TEST_CASE("CustomUserdataPropertyAccess2") if (!Luau::CodeGen::isSupported()) return; - ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}, {FFlag::LuauLoadUserdataInfo, true}, {FFlag::LuauCodegenUserdataOps, true}}; + ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}}; CHECK_EQ("\n" + getCodegenAssembly(R"( local function foo(a: mat3) @@ -1660,7 +1657,7 @@ TEST_CASE("CustomUserdataNamecall1") if (!Luau::CodeGen::isSupported()) return; - ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}, {FFlag::LuauLoadUserdataInfo, true}, {FFlag::LuauCodegenUserdataOps, true}}; + ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}}; CHECK_EQ("\n" + getCodegenAssembly(R"( local function foo(a: vec2, b: vec2) @@ -1706,8 +1703,7 @@ TEST_CASE("CustomUserdataNamecall2") if (!Luau::CodeGen::isSupported()) return; - ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}, {FFlag::LuauLoadUserdataInfo, true}, {FFlag::LuauCodegenUserdataOps, true}, - {FFlag::LuauCodegenUserdataAlloc, true}}; + ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}}; CHECK_EQ("\n" + getCodegenAssembly(R"( local function foo(a: vec2, b: vec2) @@ -1756,7 +1752,7 @@ TEST_CASE("CustomUserdataMetamethodDirectFlow") if (!Luau::CodeGen::isSupported()) return; - ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}, {FFlag::LuauLoadUserdataInfo, true}, {FFlag::LuauCodegenUserdataOps, true}}; + ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}}; CHECK_EQ("\n" + getCodegenAssembly(R"( local function foo(a: mat3, b: mat3) @@ -1788,7 +1784,7 @@ TEST_CASE("CustomUserdataMetamethodDirectFlow2") if (!Luau::CodeGen::isSupported()) return; - ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}, {FFlag::LuauLoadUserdataInfo, true}, {FFlag::LuauCodegenUserdataOps, true}}; + ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}}; CHECK_EQ("\n" + getCodegenAssembly(R"( local function foo(a: mat3) @@ -1818,7 +1814,7 @@ TEST_CASE("CustomUserdataMetamethodDirectFlow3") if (!Luau::CodeGen::isSupported()) return; - ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}, {FFlag::LuauLoadUserdataInfo, true}, {FFlag::LuauCodegenUserdataOps, true}}; + ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}}; CHECK_EQ("\n" + getCodegenAssembly(R"( local function foo(a: sequence) @@ -1848,8 +1844,7 @@ TEST_CASE("CustomUserdataMetamethod") if (!Luau::CodeGen::isSupported()) return; - ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}, {FFlag::LuauLoadUserdataInfo, true}, {FFlag::LuauCodegenUserdataOps, true}, - {FFlag::LuauCodegenUserdataAlloc, true}}; + ScopedFastFlag sffs[]{{FFlag::LuauCompileUserdataInfo, true}}; CHECK_EQ("\n" + getCodegenAssembly(R"( local function foo(a: vec2, b: vec2, c: vec2) diff --git a/tests/TypeInfer.aliases.test.cpp b/tests/TypeInfer.aliases.test.cpp index 54cf1cef..f84c13e3 100644 --- a/tests/TypeInfer.aliases.test.cpp +++ b/tests/TypeInfer.aliases.test.cpp @@ -4,6 +4,7 @@ #include "doctest.h" #include "Luau/BuiltinDefinitions.h" +#include "Luau/AstQuery.h" using namespace Luau; @@ -929,17 +930,19 @@ TEST_CASE_FIXTURE(Fixture, "type_alias_locations") )"); ModulePtr mod = getMainModule(); - REQUIRE(mod); - REQUIRE(mod->scopes.size() == 8); + REQUIRE(!mod->scopes.empty()); REQUIRE(mod->scopes[0].second->typeAliasNameLocations.count("T") > 0); CHECK(mod->scopes[0].second->typeAliasNameLocations["T"] == Location(Position(1, 13), 1)); - REQUIRE(mod->scopes[3].second->typeAliasNameLocations.count("T") > 0); - CHECK(mod->scopes[3].second->typeAliasNameLocations["T"] == Location(Position(4, 17), 1)); + ScopePtr doScope = findScopeAtPosition(*mod, Position{4, 0}); + REQUIRE(doScope); - REQUIRE(mod->scopes[3].second->typeAliasNameLocations.count("X") > 0); - CHECK(mod->scopes[3].second->typeAliasNameLocations["X"] == Location(Position(5, 17), 1)); + REQUIRE(doScope->typeAliasNameLocations.count("T") > 0); + CHECK(doScope->typeAliasNameLocations["T"] == Location(Position(4, 17), 1)); + + REQUIRE(doScope->typeAliasNameLocations.count("X") > 0); + CHECK(doScope->typeAliasNameLocations["X"] == Location(Position(5, 17), 1)); } /* diff --git a/tests/TypeInfer.loops.test.cpp b/tests/TypeInfer.loops.test.cpp index a58fb638..ab96f205 100644 --- a/tests/TypeInfer.loops.test.cpp +++ b/tests/TypeInfer.loops.test.cpp @@ -202,7 +202,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_loop_with_zero_iterators_dcr") for key in no_iter() do end )"); - LUAU_REQUIRE_ERROR_COUNT(1, result); + LUAU_REQUIRE_ERROR_COUNT(2, result); } TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_with_a_custom_iterator_should_type_check") @@ -465,7 +465,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "iter_constraint_before_loop_body") TEST_CASE_FIXTURE(BuiltinsFixture, "rbxl_place_file_crash_for_wrong_constraints") { CheckResult result = check(R"( -local VehicleParameters = { +local VehicleParameters = { -- These are default values in the case the package structure is broken StrutSpringStiffnessFront = 28000, } diff --git a/tests/TypeInfer.tables.test.cpp b/tests/TypeInfer.tables.test.cpp index 6f8b4f50..8ddfc190 100644 --- a/tests/TypeInfer.tables.test.cpp +++ b/tests/TypeInfer.tables.test.cpp @@ -2990,6 +2990,24 @@ c = b CHECK(0 == ttv->instantiatedTypeParams.size()); } +TEST_CASE_FIXTURE(Fixture, "record_location_of_inserted_table_properties") +{ + CheckResult result = check(R"( + local a = {} + a.foo = 1234 + )"); + + LUAU_REQUIRE_NO_ERRORS(result); + + const TableType* tt = get(requireType("a")); + REQUIRE(tt); + + REQUIRE(tt->props.count("foo")); + + const Property& prop = tt->props.find("foo")->second; + CHECK(Location{{2, 10}, {2, 13}} == prop.location); +} + TEST_CASE_FIXTURE(Fixture, "table_indexing_error_location") { CheckResult result = check(R"( diff --git a/tools/faillist.txt b/tools/faillist.txt index 834b24c0..0ada384d 100644 --- a/tools/faillist.txt +++ b/tools/faillist.txt @@ -245,11 +245,18 @@ TypeAliases.recursive_types_restriction_not_ok TypeAliases.report_shadowed_aliases TypeAliases.type_alias_local_mutation TypeAliases.type_alias_local_rename -TypeAliases.type_alias_locations TypeAliases.type_alias_of_an_imported_recursive_generic_type TypeFamilyTests.add_family_at_work +TypeFamilyTests.cyclic_add_family_at_work +TypeFamilyTests.cyclic_concat_family_at_work +TypeFamilyTests.didnt_quite_exceed_distributivity_limits +TypeFamilyTests.ensure_equivalence_with_distributivity TypeFamilyTests.family_as_fn_arg +TypeFamilyTests.index_type_family_works_w_generic_types TypeFamilyTests.internal_families_raise_errors +TypeFamilyTests.keyof_oss_crash_gh1161 +TypeFamilyTests.mul_family_with_union_of_multiplicatives +TypeFamilyTests.mul_family_with_union_of_multiplicatives_2 TypeFamilyTests.unsolvable_family TypeInfer.be_sure_to_use_active_txnlog_when_evaluating_a_variadic_overload TypeInfer.check_type_infer_recursion_count @@ -266,6 +273,7 @@ TypeInfer.no_stack_overflow_from_isoptional 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.tc_after_error_recovery_no_replacement_name_in_error +TypeInfer.tc_if_else_expressions_expected_type_3 TypeInfer.type_infer_recursion_limit_no_ice TypeInfer.type_infer_recursion_limit_normalizer TypeInfer.unify_nearly_identical_recursive_types @@ -335,6 +343,7 @@ TypeInferFunctions.too_many_return_values_in_parentheses TypeInferFunctions.too_many_return_values_no_function TypeInferFunctions.unifier_should_not_bind_free_types TypeInferLoops.cli_68448_iterators_need_not_accept_nil +TypeInferLoops.dcr_iteration_fragmented_keys TypeInferLoops.dcr_iteration_on_never_gives_never TypeInferLoops.dcr_xpath_candidates TypeInferLoops.for_in_loop @@ -343,11 +352,13 @@ TypeInferLoops.for_in_loop_error_on_iterator_requiring_args_but_none_given TypeInferLoops.for_in_loop_on_error TypeInferLoops.for_in_loop_on_non_function TypeInferLoops.for_in_loop_with_next +TypeInferLoops.for_in_with_just_one_iterator_is_ok TypeInferLoops.for_loop TypeInferLoops.ipairs_produces_integral_indices TypeInferLoops.iterate_over_properties TypeInferLoops.iteration_regression_issue_69967_alt TypeInferLoops.loop_iter_metamethod_nil +TypeInferLoops.loop_iter_metamethod_not_enough_returns TypeInferLoops.loop_iter_metamethod_ok TypeInferLoops.loop_iter_metamethod_ok_with_inference TypeInferLoops.loop_iter_no_indexer_strict