From a7299c3f0f15d70f0d869ae7c53d08d251b4ae21 Mon Sep 17 00:00:00 2001 From: Vighnesh-V Date: Fri, 19 Jul 2024 11:20:47 -0700 Subject: [PATCH] Sync to upstream/release/635 (#1337) # What's Changed? - Bugfixes in the new solver ## New Solver - Equality graphs(E-Graphs) data structures were added - Refactored even more instances of "type family" with "type function" - `table.insert` no longer spuriously warns while selecting an overload for reasonable arguments. - Add time tracing for the new solver - Miscellaneous fixes to unit tests --- ### Internal Contributors Co-authored-by: Aaron Weiss Co-authored-by: Alexander McCord Co-authored-by: Jeremy Yoo Co-authored-by: Vighnesh Vijay Co-authored-by: Vyacheslav Egorov --------- Co-authored-by: Aaron Weiss Co-authored-by: Alexander McCord Co-authored-by: Andy Friesen Co-authored-by: Aviral Goel Co-authored-by: David Cope Co-authored-by: Lily Brown Co-authored-by: Vyacheslav Egorov Co-authored-by: Junseo Yoo --- Analysis/include/Luau/ConstraintGenerator.h | 2 +- Analysis/include/Luau/ConstraintSolver.h | 12 +- Analysis/include/Luau/OverloadResolution.h | 2 +- Analysis/include/Luau/Subtyping.h | 6 +- Analysis/include/Luau/Type.h | 14 +- Analysis/include/Luau/TypeArena.h | 8 +- .../Luau/TypeFunctionReductionGuesser.h | 28 +-- Analysis/include/Luau/TypePack.h | 2 +- Analysis/include/Luau/Unifier2.h | 4 +- Analysis/src/ConstraintGenerator.cpp | 7 +- Analysis/src/ConstraintSolver.cpp | 36 ++-- Analysis/src/DataFlowGraph.cpp | 3 + Analysis/src/Error.cpp | 22 +-- Analysis/src/Frontend.cpp | 4 + Analysis/src/NonStrictTypeChecker.cpp | 9 +- Analysis/src/Substitution.cpp | 4 +- Analysis/src/Subtyping.cpp | 25 +-- Analysis/src/ToDot.cpp | 2 +- Analysis/src/ToString.cpp | 4 +- Analysis/src/Type.cpp | 2 +- Analysis/src/TypeArena.cpp | 16 +- Analysis/src/TypeAttach.cpp | 4 +- Analysis/src/TypeChecker2.cpp | 63 +++---- Analysis/src/TypeFunction.cpp | 168 +++++++++--------- Analysis/src/TypeFunctionReductionGuesser.cpp | 88 ++++----- Analysis/src/Unifier2.cpp | 10 +- EqSat/src/UnionFind.cpp | 1 - tests/Error.test.cpp | 4 +- tests/Frontend.test.cpp | 2 +- tests/Linter.test.cpp | 2 +- tests/Normalize.test.cpp | 12 +- tests/Subtyping.test.cpp | 80 +++++---- tests/TypeFunction.test.cpp | 108 +++++------ tests/TypeInfer.anyerror.test.cpp | 31 +++- tests/TypeInfer.generics.test.cpp | 2 +- tests/TypeInfer.operators.test.cpp | 6 +- tests/TypeInfer.tables.test.cpp | 25 ++- tools/faillist.txt | 29 ++- 38 files changed, 463 insertions(+), 384 deletions(-) diff --git a/Analysis/include/Luau/ConstraintGenerator.h b/Analysis/include/Luau/ConstraintGenerator.h index cb49eef3..510d9828 100644 --- a/Analysis/include/Luau/ConstraintGenerator.h +++ b/Analysis/include/Luau/ConstraintGenerator.h @@ -371,7 +371,7 @@ private: std::vector> getExpectedCallTypesForFunctionOverloads(const TypeId fnType); TypeId createTypeFunctionInstance( - const TypeFunction& family, std::vector typeArguments, std::vector packArguments, const ScopePtr& scope, Location location); + const TypeFunction& function, std::vector typeArguments, std::vector packArguments, const ScopePtr& scope, Location location); }; /** Borrow a vector of pointers from a vector of owning pointers to constraints. diff --git a/Analysis/include/Luau/ConstraintSolver.h b/Analysis/include/Luau/ConstraintSolver.h index 925be04e..eb6ed29f 100644 --- a/Analysis/include/Luau/ConstraintSolver.h +++ b/Analysis/include/Luau/ConstraintSolver.h @@ -91,8 +91,8 @@ struct ConstraintSolver // A mapping from free types to the number of unresolved constraints that mention them. DenseHashMap unresolvedConstraints{{}}; - // Irreducible/uninhabited type families or type pack families. - DenseHashSet uninhabitedTypeFamilies{{}}; + // Irreducible/uninhabited type functions or type pack functions. + DenseHashSet uninhabitedTypeFunctions{{}}; // The set of types that will definitely be unchanged by generalization. DenseHashSet generalizedTypes_{nullptr}; @@ -107,7 +107,7 @@ struct ConstraintSolver DcrLogger* logger; TypeCheckLimits limits; - DenseHashMap typeFamiliesToFinalize{nullptr}; + DenseHashMap typeFunctionsToFinalize{nullptr}; explicit ConstraintSolver(NotNull normalizer, NotNull rootScope, std::vector> constraints, ModuleName moduleName, NotNull moduleResolver, std::vector requireCycles, DcrLogger* logger, @@ -124,10 +124,10 @@ struct ConstraintSolver /** - * Attempts to perform one final reduction on type families after every constraint has been completed + * Attempts to perform one final reduction on type functions after every constraint has been completed * **/ - void finalizeTypeFamilies(); + void finalizeTypeFunctions(); bool isDone(); @@ -345,7 +345,7 @@ public: /** * Reproduces any constraints necessary for new types that are copied when applying a substitution. - * At the time of writing, this pertains only to type families. + * At the time of writing, this pertains only to type functions. * @param subst the substitution that was applied **/ void reproduceConstraints(NotNull scope, const Location& location, const Substitution& subst); diff --git a/Analysis/include/Luau/OverloadResolution.h b/Analysis/include/Luau/OverloadResolution.h index 58341fca..73cef264 100644 --- a/Analysis/include/Luau/OverloadResolution.h +++ b/Analysis/include/Luau/OverloadResolution.h @@ -85,7 +85,7 @@ struct SolveResult DenseHashMap> expandedFreeTypes{nullptr}; }; -// Helper utility, presently used for binary operator type families. +// Helper utility, presently used for binary operator type functions. // // Given a function and a set of arguments, select a suitable overload. SolveResult solveFunctionCall(NotNull arena, NotNull builtinTypes, NotNull normalizer, diff --git a/Analysis/include/Luau/Subtyping.h b/Analysis/include/Luau/Subtyping.h index 4c1d23bd..d72963cb 100644 --- a/Analysis/include/Luau/Subtyping.h +++ b/Analysis/include/Luau/Subtyping.h @@ -219,8 +219,8 @@ private: SubtypingResult isCovariantWith(SubtypingEnvironment& env, const TypeIds& subTypes, const TypeIds& superTypes); SubtypingResult isCovariantWith(SubtypingEnvironment& env, const VariadicTypePack* subVariadic, const VariadicTypePack* superVariadic); - SubtypingResult isCovariantWith(SubtypingEnvironment& env, const TypeFunctionInstanceType* subFamilyInstance, const TypeId superTy); - SubtypingResult isCovariantWith(SubtypingEnvironment& env, const TypeId subTy, const TypeFunctionInstanceType* superFamilyInstance); + SubtypingResult isCovariantWith(SubtypingEnvironment& env, const TypeFunctionInstanceType* subFunctionInstance, const TypeId superTy); + SubtypingResult isCovariantWith(SubtypingEnvironment& env, const TypeId subTy, const TypeFunctionInstanceType* superFunctionInstance); bool bindGeneric(SubtypingEnvironment& env, TypeId subTp, TypeId superTp); bool bindGeneric(SubtypingEnvironment& env, TypePackId subTp, TypePackId superTp); @@ -228,7 +228,7 @@ private: template TypeId makeAggregateType(const Container& container, TypeId orElse); - std::pair handleTypeFunctionReductionResult(const TypeFunctionInstanceType* familyInstance); + std::pair handleTypeFunctionReductionResult(const TypeFunctionInstanceType* functionInstance); [[noreturn]] void unexpected(TypeId ty); [[noreturn]] void unexpected(TypePackId tp); diff --git a/Analysis/include/Luau/Type.h b/Analysis/include/Luau/Type.h index dfcf8b6b..28ca076e 100644 --- a/Analysis/include/Luau/Type.h +++ b/Analysis/include/Luau/Type.h @@ -540,27 +540,27 @@ struct ClassType */ struct TypeFunctionInstanceType { - NotNull family; + NotNull function; std::vector typeArguments; std::vector packArguments; - TypeFunctionInstanceType(NotNull family, std::vector typeArguments, std::vector packArguments) - : family(family) + TypeFunctionInstanceType(NotNull function, std::vector typeArguments, std::vector packArguments) + : function(function) , typeArguments(typeArguments) , packArguments(packArguments) { } - TypeFunctionInstanceType(const TypeFunction& family, std::vector typeArguments) - : family{&family} + TypeFunctionInstanceType(const TypeFunction& function, std::vector typeArguments) + : function{&function} , typeArguments(typeArguments) , packArguments{} { } - TypeFunctionInstanceType(const TypeFunction& family, std::vector typeArguments, std::vector packArguments) - : family{&family} + TypeFunctionInstanceType(const TypeFunction& function, std::vector typeArguments, std::vector packArguments) + : function{&function} , typeArguments(typeArguments) , packArguments(packArguments) { diff --git a/Analysis/include/Luau/TypeArena.h b/Analysis/include/Luau/TypeArena.h index 5a28aa25..4f8aea87 100644 --- a/Analysis/include/Luau/TypeArena.h +++ b/Analysis/include/Luau/TypeArena.h @@ -49,10 +49,10 @@ struct TypeArena return addTypePack(TypePackVar(std::move(tp))); } - TypeId addTypeFunction(const TypeFunction& family, std::initializer_list types); - TypeId addTypeFunction(const TypeFunction& family, std::vector typeArguments, std::vector packArguments = {}); - TypePackId addTypePackFunction(const TypePackFunction& family, std::initializer_list types); - TypePackId addTypePackFunction(const TypePackFunction& family, std::vector typeArguments, std::vector packArguments = {}); + TypeId addTypeFunction(const TypeFunction& function, std::initializer_list types); + TypeId addTypeFunction(const TypeFunction& function, std::vector typeArguments, std::vector packArguments = {}); + TypePackId addTypePackFunction(const TypePackFunction& function, std::initializer_list types); + TypePackId addTypePackFunction(const TypePackFunction& function, std::vector typeArguments, std::vector packArguments = {}); }; void freeze(TypeArena& arena); diff --git a/Analysis/include/Luau/TypeFunctionReductionGuesser.h b/Analysis/include/Luau/TypeFunctionReductionGuesser.h index 62206efc..b6d4a74c 100644 --- a/Analysis/include/Luau/TypeFunctionReductionGuesser.h +++ b/Analysis/include/Luau/TypeFunctionReductionGuesser.h @@ -29,13 +29,13 @@ struct TypeFunctionReductionGuessResult struct TypeFunctionInferenceResult { std::vector operandInference; - TypeId familyResultInference; + TypeId functionResultInference; }; struct TypeFunctionReductionGuesser { // Tracks our hypothesis about what a type function reduces to - DenseHashMap familyReducesTo{nullptr}; + DenseHashMap functionReducesTo{nullptr}; // Tracks our constraints on type function operands DenseHashMap substitutable{nullptr}; // List of instances to try progress @@ -57,14 +57,14 @@ private: std::optional guessType(TypeId arg); void dumpGuesses(); - bool isNumericBinopFamily(const TypeFunctionInstanceType& instance); - bool isComparisonFamily(const TypeFunctionInstanceType& instance); - bool isOrAndFamily(const TypeFunctionInstanceType& instance); - bool isNotFamily(const TypeFunctionInstanceType& instance); - bool isLenFamily(const TypeFunctionInstanceType& instance); + bool isNumericBinopFunction(const TypeFunctionInstanceType& instance); + bool isComparisonFunction(const TypeFunctionInstanceType& instance); + bool isOrAndFunction(const TypeFunctionInstanceType& instance); + bool isNotFunction(const TypeFunctionInstanceType& instance); + bool isLenFunction(const TypeFunctionInstanceType& instance); bool isUnaryMinus(const TypeFunctionInstanceType& instance); - // Operand is assignable if it looks like a cyclic family instance, or a generic type + // Operand is assignable if it looks like a cyclic type function instance, or a generic type bool operandIsAssignable(TypeId ty); std::optional tryAssignOperandType(TypeId ty); @@ -75,11 +75,11 @@ private: bool isFunctionGenericsSaturated(const FunctionType& ftv, DenseHashSet& instanceArgs); void inferTypeFunctionSubstitutions(TypeId ty, const TypeFunctionInstanceType* instance); - TypeFunctionInferenceResult inferNumericBinopFamily(const TypeFunctionInstanceType* instance); - TypeFunctionInferenceResult inferComparisonFamily(const TypeFunctionInstanceType* instance); - TypeFunctionInferenceResult inferOrAndFamily(const TypeFunctionInstanceType* instance); - TypeFunctionInferenceResult inferNotFamily(const TypeFunctionInstanceType* instance); - TypeFunctionInferenceResult inferLenFamily(const TypeFunctionInstanceType* instance); - TypeFunctionInferenceResult inferUnaryMinusFamily(const TypeFunctionInstanceType* instance); + TypeFunctionInferenceResult inferNumericBinopFunction(const TypeFunctionInstanceType* instance); + TypeFunctionInferenceResult inferComparisonFunction(const TypeFunctionInstanceType* instance); + TypeFunctionInferenceResult inferOrAndFunction(const TypeFunctionInstanceType* instance); + TypeFunctionInferenceResult inferNotFunction(const TypeFunctionInstanceType* instance); + TypeFunctionInferenceResult inferLenFunction(const TypeFunctionInstanceType* instance); + TypeFunctionInferenceResult inferUnaryMinusFunction(const TypeFunctionInstanceType* instance); }; } // namespace Luau diff --git a/Analysis/include/Luau/TypePack.h b/Analysis/include/Luau/TypePack.h index 5d10454d..1065b947 100644 --- a/Analysis/include/Luau/TypePack.h +++ b/Analysis/include/Luau/TypePack.h @@ -92,7 +92,7 @@ struct BlockedTypePack */ struct TypeFunctionInstanceTypePack { - NotNull family; + NotNull function; std::vector typeArguments; std::vector packArguments; diff --git a/Analysis/include/Luau/Unifier2.h b/Analysis/include/Luau/Unifier2.h index bbf3a63a..13c2d7f5 100644 --- a/Analysis/include/Luau/Unifier2.h +++ b/Analysis/include/Luau/Unifier2.h @@ -49,11 +49,11 @@ struct Unifier2 std::vector incompleteSubtypes; // null if not in a constraint solving context - DenseHashSet* uninhabitedTypeFamilies; + DenseHashSet* uninhabitedTypeFunctions; Unifier2(NotNull arena, NotNull builtinTypes, NotNull scope, NotNull ice); Unifier2(NotNull arena, NotNull builtinTypes, NotNull scope, NotNull ice, - DenseHashSet* uninhabitedTypeFamilies); + DenseHashSet* uninhabitedTypeFunctions); /** Attempt to commit the subtype relation subTy <: superTy to the type * graph. diff --git a/Analysis/src/ConstraintGenerator.cpp b/Analysis/src/ConstraintGenerator.cpp index bcfc21dd..9f776b64 100644 --- a/Analysis/src/ConstraintGenerator.cpp +++ b/Analysis/src/ConstraintGenerator.cpp @@ -15,6 +15,7 @@ #include "Luau/Simplify.h" #include "Luau/StringUtils.h" #include "Luau/TableLiteralInference.h" +#include "Luau/TimeTrace.h" #include "Luau/Type.h" #include "Luau/TypeFunction.h" #include "Luau/TypePack.h" @@ -211,6 +212,8 @@ ConstraintGenerator::ConstraintGenerator(ModulePtr module, NotNull n void ConstraintGenerator::visitModuleRoot(AstStatBlock* block) { + LUAU_TIMETRACE_SCOPE("ConstraintGenerator::visitModuleRoot", "Typechecking"); + LUAU_ASSERT(scopes.empty()); LUAU_ASSERT(rootScope == nullptr); ScopePtr scope = std::make_shared(globalScope); @@ -3356,9 +3359,9 @@ std::vector> ConstraintGenerator::getExpectedCallTypesForF } TypeId ConstraintGenerator::createTypeFunctionInstance( - const TypeFunction& family, std::vector typeArguments, std::vector packArguments, const ScopePtr& scope, Location location) + const TypeFunction& function, std::vector typeArguments, std::vector packArguments, const ScopePtr& scope, Location location) { - TypeId result = arena->addTypeFunction(family, typeArguments, packArguments); + TypeId result = arena->addTypeFunction(function, typeArguments, packArguments); addConstraint(scope, location, ReduceConstraint{result}); return result; } diff --git a/Analysis/src/ConstraintSolver.cpp b/Analysis/src/ConstraintSolver.cpp index 15f150e8..cba198e6 100644 --- a/Analysis/src/ConstraintSolver.cpp +++ b/Analysis/src/ConstraintSolver.cpp @@ -366,6 +366,8 @@ void ConstraintSolver::randomize(unsigned seed) void ConstraintSolver::run() { + LUAU_TIMETRACE_SCOPE("ConstraintSolver::run", "Typechecking"); + if (isDone()) return; @@ -489,11 +491,11 @@ void ConstraintSolver::run() 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 + // After we have run all the constraints, type functions 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 + // whether type functions are truly uninhabited or if they can reduce - finalizeTypeFamilies(); + finalizeTypeFunctions(); if (FFlag::DebugLuauLogSolver || FFlag::DebugLuauLogBindings) dumpBindings(rootScope, opts); @@ -504,10 +506,10 @@ void ConstraintSolver::run() } } -void ConstraintSolver::finalizeTypeFamilies() +void ConstraintSolver::finalizeTypeFunctions() { // At this point, we've generalized. Let's try to finish reducing as much as we can, we'll leave warning to the typechecker - for (auto [t, constraint] : typeFamiliesToFinalize) + for (auto [t, constraint] : typeFunctionsToFinalize) { TypeId ty = follow(t); if (get(ty)) @@ -721,7 +723,7 @@ bool ConstraintSolver::tryDispatch(const IterableConstraint& c, NotNull(*res); LUAU_ASSERT(ftv); - // we've potentially copied type families here, so we need to reproduce their reduce constraint. + // we've potentially copied type functions here, so we need to reproduce their reduce constraint. reproduceConstraints(constraint->scope, constraint->location, replacer); } } @@ -1975,17 +1977,17 @@ bool ConstraintSolver::tryDispatch(const ReduceConstraint& c, NotNull(ty)) - typeFamiliesToFinalize[ty] = constraint; + typeFunctionsToFinalize[ty] = constraint; if (force || reductionFinished) { - // if we're completely dispatching this constraint, we want to record any uninhabited type families to unblock. + // if we're completely dispatching this constraint, we want to record any uninhabited type functions to unblock. for (auto error : result.errors) { if (auto utf = get(error)) - uninhabitedTypeFamilies.insert(utf->ty); + uninhabitedTypeFunctions.insert(utf->ty); else if (auto utpf = get(error)) - uninhabitedTypeFamilies.insert(utpf->tp); + uninhabitedTypeFunctions.insert(utpf->tp); } } @@ -2017,13 +2019,13 @@ bool ConstraintSolver::tryDispatch(const ReducePackConstraint& c, NotNull(error)) - uninhabitedTypeFamilies.insert(utf->ty); + uninhabitedTypeFunctions.insert(utf->ty); else if (auto utpf = get(error)) - uninhabitedTypeFamilies.insert(utpf->tp); + uninhabitedTypeFunctions.insert(utpf->tp); } } @@ -2498,7 +2500,7 @@ std::pair, std::optional> ConstraintSolver::lookupTa template bool ConstraintSolver::unify(NotNull constraint, TID subTy, TID superTy) { - Unifier2 u2{NotNull{arena}, builtinTypes, constraint->scope, NotNull{&iceReporter}, &uninhabitedTypeFamilies}; + Unifier2 u2{NotNull{arena}, builtinTypes, constraint->scope, NotNull{&iceReporter}, &uninhabitedTypeFunctions}; const bool ok = u2.unify(subTy, superTy); @@ -2735,7 +2737,7 @@ bool ConstraintSolver::isBlocked(TypeId ty) ty = follow(ty); if (auto tfit = get(ty)) - return uninhabitedTypeFamilies.contains(ty) == false; + return uninhabitedTypeFunctions.contains(ty) == false; return nullptr != get(ty) || nullptr != get(ty); } @@ -2745,7 +2747,7 @@ bool ConstraintSolver::isBlocked(TypePackId tp) tp = follow(tp); if (auto tfitp = get(tp)) - return uninhabitedTypeFamilies.contains(tp) == false; + return uninhabitedTypeFunctions.contains(tp) == false; return nullptr != get(tp); } diff --git a/Analysis/src/DataFlowGraph.cpp b/Analysis/src/DataFlowGraph.cpp index 0a0a64d3..708001cd 100644 --- a/Analysis/src/DataFlowGraph.cpp +++ b/Analysis/src/DataFlowGraph.cpp @@ -5,6 +5,7 @@ #include "Luau/Def.h" #include "Luau/Common.h" #include "Luau/Error.h" +#include "Luau/TimeTrace.h" #include @@ -136,6 +137,8 @@ bool DfgScope::canUpdateDefinition(DefId def, const std::string& key) const DataFlowGraph DataFlowGraphBuilder::build(AstStatBlock* block, NotNull handle) { + LUAU_TIMETRACE_SCOPE("DataFlowGraphBuilder::build", "Typechecking"); + LUAU_ASSERT(FFlag::DebugLuauDeferredConstraintResolution); DataFlowGraphBuilder builder; diff --git a/Analysis/src/Error.cpp b/Analysis/src/Error.cpp index 6e778e57..f69efe80 100644 --- a/Analysis/src/Error.cpp +++ b/Analysis/src/Error.cpp @@ -585,7 +585,7 @@ struct ErrorConverter return "Unexpected type " + Luau::toString(e.ty) + " flagged as an uninhabited type function."; // unary operators - if (auto unaryString = kUnaryOps.find(tfit->family->name); unaryString != kUnaryOps.end()) + if (auto unaryString = kUnaryOps.find(tfit->function->name); unaryString != kUnaryOps.end()) { std::string result = "Operator '" + std::string(unaryString->second) + "' could not be applied to "; @@ -593,8 +593,8 @@ struct ErrorConverter { result += "operand of type " + Luau::toString(tfit->typeArguments[0]); - if (tfit->family->name != "not") - result += "; there is no corresponding overload for __" + tfit->family->name; + if (tfit->function->name != "not") + result += "; there is no corresponding overload for __" + tfit->function->name; } else { @@ -619,7 +619,7 @@ struct ErrorConverter } // binary operators - if (auto binaryString = kBinaryOps.find(tfit->family->name); binaryString != kBinaryOps.end()) + if (auto binaryString = kBinaryOps.find(tfit->function->name); binaryString != kBinaryOps.end()) { std::string result = "Operator '" + std::string(binaryString->second) + "' could not be applied to operands of types "; @@ -646,14 +646,14 @@ struct ErrorConverter result += ", " + Luau::toString(packArg); } - result += "; there is no corresponding overload for __" + tfit->family->name; + result += "; there is no corresponding overload for __" + tfit->function->name; return result; } // miscellaneous - if ("keyof" == tfit->family->name || "rawkeyof" == tfit->family->name) + if ("keyof" == tfit->function->name || "rawkeyof" == tfit->function->name) { if (tfit->typeArguments.size() == 1 && tfit->packArguments.empty()) return "Type '" + toString(tfit->typeArguments[0]) + "' does not have keys, so '" + Luau::toString(e.ty) + "' is invalid"; @@ -661,19 +661,19 @@ struct ErrorConverter return "Type function instance " + Luau::toString(e.ty) + " is ill-formed, and thus invalid"; } - if ("index" == tfit->family->name || "rawget" == tfit->family->name) + if ("index" == tfit->function->name || "rawget" == tfit->function->name) { if (tfit->typeArguments.size() != 2) return "Type function instance " + Luau::toString(e.ty) + " is ill-formed, and thus invalid"; if (auto errType = get(tfit->typeArguments[1])) // Second argument to (index | rawget)<_,_> is not a type - return "Second argument to " + tfit->family->name + "<" + Luau::toString(tfit->typeArguments[0]) + ", _> is not a valid index type"; + return "Second argument to " + tfit->function->name + "<" + Luau::toString(tfit->typeArguments[0]) + ", _> is not a valid index type"; else // Property `indexer` does not exist on type `indexee` return "Property '" + Luau::toString(tfit->typeArguments[1]) + "' does not exist on type '" + Luau::toString(tfit->typeArguments[0]) + "'"; } - if (kUnreachableTypeFunctions.count(tfit->family->name)) + if (kUnreachableTypeFunctions.count(tfit->function->name)) { return "Type function instance " + Luau::toString(e.ty) + " is uninhabited\n" + "This is likely to be a bug, please report it at https://github.com/luau-lang/luau/issues"; @@ -706,7 +706,7 @@ struct ErrorConverter std::string operator()(const UninhabitedTypePackFunction& e) const { - return "Type pack family instance " + Luau::toString(e.tp) + " is uninhabited"; + return "Type pack function instance " + Luau::toString(e.tp) + " is uninhabited"; } std::string operator()(const WhereClauseNeeded& e) const @@ -718,7 +718,7 @@ struct ErrorConverter std::string operator()(const PackWhereClauseNeeded& e) const { - return "Type pack family instance " + Luau::toString(e.tp) + + return "Type pack function instance " + Luau::toString(e.tp) + " depends on generic function parameters but does not appear in the function signature; this construct cannot be type-checked at this " "time"; } diff --git a/Analysis/src/Frontend.cpp b/Analysis/src/Frontend.cpp index 391ece8c..9f59eeb8 100644 --- a/Analysis/src/Frontend.cpp +++ b/Analysis/src/Frontend.cpp @@ -1249,6 +1249,10 @@ ModulePtr check(const SourceModule& sourceModule, Mode mode, const std::vector prepareModuleScope, FrontendOptions options, TypeCheckLimits limits, bool recordJsonLog, std::function writeJsonLog) { + LUAU_TIMETRACE_SCOPE("Frontend::check", "Typechecking"); + LUAU_TIMETRACE_ARGUMENT("module", sourceModule.name.c_str()); + LUAU_TIMETRACE_ARGUMENT("name", sourceModule.humanReadableName.c_str()); + ModulePtr result = std::make_shared(); result->name = sourceModule.name; result->humanReadableName = sourceModule.humanReadableName; diff --git a/Analysis/src/NonStrictTypeChecker.cpp b/Analysis/src/NonStrictTypeChecker.cpp index ea617279..f567bf05 100644 --- a/Analysis/src/NonStrictTypeChecker.cpp +++ b/Analysis/src/NonStrictTypeChecker.cpp @@ -9,6 +9,7 @@ #include "Luau/Subtyping.h" #include "Luau/Normalize.h" #include "Luau/Error.h" +#include "Luau/TimeTrace.h" #include "Luau/TypeArena.h" #include "Luau/TypeFunction.h" #include "Luau/Def.h" @@ -206,7 +207,7 @@ struct NonStrictTypeChecker } - TypeId checkForFamilyInhabitance(TypeId instance, Location location) + TypeId checkForTypeFunctionInhabitance(TypeId instance, Location location) { if (noTypeFunctionErrors.find(instance)) return instance; @@ -227,11 +228,11 @@ struct NonStrictTypeChecker { TypeId* ty = module->astTypes.find(expr); if (ty) - return checkForFamilyInhabitance(follow(*ty), expr->location); + return checkForTypeFunctionInhabitance(follow(*ty), expr->location); TypePackId* tp = module->astTypePacks.find(expr); if (tp) - return checkForFamilyInhabitance(flattenPack(*tp), expr->location); + return checkForTypeFunctionInhabitance(flattenPack(*tp), expr->location); return builtinTypes->anyType; } @@ -728,6 +729,8 @@ private: void checkNonStrict(NotNull builtinTypes, NotNull ice, NotNull unifierState, NotNull dfg, NotNull limits, const SourceModule& sourceModule, Module* module) { + LUAU_TIMETRACE_SCOPE("checkNonStrict", "Typechecking"); + NonStrictTypeChecker typeChecker{NotNull{&module->internalTypes}, builtinTypes, ice, unifierState, dfg, limits, module}; typeChecker.visit(sourceModule.root); unfreeze(module->interfaceTypes); diff --git a/Analysis/src/Substitution.cpp b/Analysis/src/Substitution.cpp index a0128b41..9b8561a1 100644 --- a/Analysis/src/Substitution.cpp +++ b/Analysis/src/Substitution.cpp @@ -127,7 +127,7 @@ static TypeId shallowClone(TypeId ty, TypeArena& dest, const TxnLog* log, bool a return dest.addType(NegationType{a.ty}); else if constexpr (std::is_same_v) { - TypeFunctionInstanceType clone{a.family, a.typeArguments, a.packArguments}; + TypeFunctionInstanceType clone{a.function, a.typeArguments, a.packArguments}; return dest.addType(std::move(clone)); } else @@ -672,7 +672,7 @@ TypePackId Substitution::clone(TypePackId tp) else if (const TypeFunctionInstanceTypePack* tfitp = get(tp)) { TypeFunctionInstanceTypePack clone{ - tfitp->family, std::vector(tfitp->typeArguments.size()), std::vector(tfitp->packArguments.size())}; + tfitp->function, std::vector(tfitp->typeArguments.size()), std::vector(tfitp->packArguments.size())}; clone.typeArguments.assign(tfitp->typeArguments.begin(), tfitp->typeArguments.end()); clone.packArguments.assign(tfitp->packArguments.begin(), tfitp->packArguments.end()); return addTypePack(std::move(clone)); diff --git a/Analysis/src/Subtyping.cpp b/Analysis/src/Subtyping.cpp index d6b4e31d..3182fb7c 100644 --- a/Analysis/src/Subtyping.cpp +++ b/Analysis/src/Subtyping.cpp @@ -530,6 +530,11 @@ SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, TypeId sub } else if (get(superTy)) result = {true}; + + // We have added this as an exception - the set of inhabitants of any is exactly the set of inhabitants of unknown (since error has no + // inhabitants). any = err | unknown, so under semantic subtyping, {} U unknown = unknown + else if (get(subTy) && get(superTy)) + result = {true}; else if (get(subTy)) { // any = unknown | error, so we rewrite this to match. @@ -1584,19 +1589,19 @@ bool Subtyping::bindGeneric(SubtypingEnvironment& env, TypeId subTy, TypeId supe return true; } -SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, const TypeFunctionInstanceType* subFamilyInstance, const TypeId superTy) +SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, const TypeFunctionInstanceType* subFunctionInstance, const TypeId superTy) { // Reduce the type function instance - auto [ty, errors] = handleTypeFunctionReductionResult(subFamilyInstance); + auto [ty, errors] = handleTypeFunctionReductionResult(subFunctionInstance); // If we return optional, that means the type function was irreducible - we can reduce that to never return isCovariantWith(env, ty, superTy).withErrors(errors).withSubComponent(TypePath::Reduction{ty}); } -SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, const TypeId subTy, const TypeFunctionInstanceType* superFamilyInstance) +SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, const TypeId subTy, const TypeFunctionInstanceType* superFunctionInstance) { // Reduce the type function instance - auto [ty, errors] = handleTypeFunctionReductionResult(superFamilyInstance); + auto [ty, errors] = handleTypeFunctionReductionResult(superFunctionInstance); return isCovariantWith(env, subTy, ty).withErrors(errors).withSuperComponent(TypePath::Reduction{ty}); } @@ -1632,19 +1637,19 @@ TypeId Subtyping::makeAggregateType(const Container& container, TypeId orElse) return arena->addType(T{std::vector(begin(container), end(container))}); } -std::pair Subtyping::handleTypeFunctionReductionResult(const TypeFunctionInstanceType* familyInstance) +std::pair Subtyping::handleTypeFunctionReductionResult(const TypeFunctionInstanceType* functionInstance) { TypeFunctionContext context{arena, builtinTypes, scope, normalizer, iceReporter, NotNull{&limits}}; - TypeId family = arena->addType(*familyInstance); - FunctionGraphReductionResult result = reduceTypeFunctions(family, {}, context, true); + TypeId function = arena->addType(*functionInstance); + FunctionGraphReductionResult result = reduceTypeFunctions(function, {}, context, true); ErrorVec errors; if (result.blockedTypes.size() != 0 || result.blockedPacks.size() != 0) { - errors.push_back(TypeError{{}, UninhabitedTypeFunction{family}}); + errors.push_back(TypeError{{}, UninhabitedTypeFunction{function}}); return {builtinTypes->neverType, errors}; } - if (result.reducedTypes.contains(family)) - return {family, errors}; + if (result.reducedTypes.contains(function)) + return {function, errors}; return {builtinTypes->neverType, errors}; } diff --git a/Analysis/src/ToDot.cpp b/Analysis/src/ToDot.cpp index 055ed7ad..66c91e39 100644 --- a/Analysis/src/ToDot.cpp +++ b/Analysis/src/ToDot.cpp @@ -345,7 +345,7 @@ void StateDot::visitChildren(TypeId ty, int index) } else if constexpr (std::is_same_v) { - formatAppend(result, "TypeFunctionInstanceType %s %d", t.family->name.c_str(), index); + formatAppend(result, "TypeFunctionInstanceType %s %d", t.function->name.c_str(), index); finishNodeLabel(ty); finishNode(); diff --git a/Analysis/src/ToString.cpp b/Analysis/src/ToString.cpp index 3440c3d7..55a48baa 100644 --- a/Analysis/src/ToString.cpp +++ b/Analysis/src/ToString.cpp @@ -1033,7 +1033,7 @@ struct TypeStringifier void operator()(TypeId, const TypeFunctionInstanceType& tfitv) { - state.emit(tfitv.family->name); + state.emit(tfitv.function->name); state.emit("<"); bool comma = false; @@ -1234,7 +1234,7 @@ struct TypePackStringifier void operator()(TypePackId, const TypeFunctionInstanceTypePack& tfitp) { - state.emit(tfitp.family->name); + state.emit(tfitp.function->name); state.emit("<"); bool comma = false; diff --git a/Analysis/src/Type.cpp b/Analysis/src/Type.cpp index 9479d0ef..ce09e510 100644 --- a/Analysis/src/Type.cpp +++ b/Analysis/src/Type.cpp @@ -424,7 +424,7 @@ bool maybeSingleton(TypeId ty) if (maybeSingleton(part)) // will i regret this? return true; if (const TypeFunctionInstanceType* tfit = get(ty)) - if (tfit->family->name == "keyof" || tfit->family->name == "rawkeyof") + if (tfit->function->name == "keyof" || tfit->function->name == "rawkeyof") return true; return false; } diff --git a/Analysis/src/TypeArena.cpp b/Analysis/src/TypeArena.cpp index ef19196c..6cf81471 100644 --- a/Analysis/src/TypeArena.cpp +++ b/Analysis/src/TypeArena.cpp @@ -94,24 +94,24 @@ TypePackId TypeArena::addTypePack(TypePackVar tp) return allocated; } -TypeId TypeArena::addTypeFunction(const TypeFunction& family, std::initializer_list types) +TypeId TypeArena::addTypeFunction(const TypeFunction& function, std::initializer_list types) { - return addType(TypeFunctionInstanceType{family, std::move(types)}); + return addType(TypeFunctionInstanceType{function, std::move(types)}); } -TypeId TypeArena::addTypeFunction(const TypeFunction& family, std::vector typeArguments, std::vector packArguments) +TypeId TypeArena::addTypeFunction(const TypeFunction& function, std::vector typeArguments, std::vector packArguments) { - return addType(TypeFunctionInstanceType{family, std::move(typeArguments), std::move(packArguments)}); + return addType(TypeFunctionInstanceType{function, std::move(typeArguments), std::move(packArguments)}); } -TypePackId TypeArena::addTypePackFunction(const TypePackFunction& family, std::initializer_list types) +TypePackId TypeArena::addTypePackFunction(const TypePackFunction& function, std::initializer_list types) { - return addTypePack(TypeFunctionInstanceTypePack{NotNull{&family}, std::move(types)}); + return addTypePack(TypeFunctionInstanceTypePack{NotNull{&function}, std::move(types)}); } -TypePackId TypeArena::addTypePackFunction(const TypePackFunction& family, std::vector typeArguments, std::vector packArguments) +TypePackId TypeArena::addTypePackFunction(const TypePackFunction& function, std::vector typeArguments, std::vector packArguments) { - return addTypePack(TypeFunctionInstanceTypePack{NotNull{&family}, std::move(typeArguments), std::move(packArguments)}); + return addTypePack(TypeFunctionInstanceTypePack{NotNull{&function}, std::move(typeArguments), std::move(packArguments)}); } void freeze(TypeArena& arena) diff --git a/Analysis/src/TypeAttach.cpp b/Analysis/src/TypeAttach.cpp index 6dc5b02d..0ef128d1 100644 --- a/Analysis/src/TypeAttach.cpp +++ b/Analysis/src/TypeAttach.cpp @@ -382,7 +382,7 @@ public: } AstType* operator()(const TypeFunctionInstanceType& tfit) { - return allocator->alloc(Location(), std::nullopt, AstName{tfit.family->name.c_str()}, std::nullopt, Location()); + return allocator->alloc(Location(), std::nullopt, AstName{tfit.function->name.c_str()}, std::nullopt, Location()); } private: @@ -456,7 +456,7 @@ public: AstTypePack* operator()(const TypeFunctionInstanceTypePack& tfitp) const { - return allocator->alloc(Location(), AstName(tfitp.family->name.c_str())); + return allocator->alloc(Location(), AstName(tfitp.function->name.c_str())); } private: diff --git a/Analysis/src/TypeChecker2.cpp b/Analysis/src/TypeChecker2.cpp index 97cec176..167e87b1 100644 --- a/Analysis/src/TypeChecker2.cpp +++ b/Analysis/src/TypeChecker2.cpp @@ -13,6 +13,7 @@ #include "Luau/Normalize.h" #include "Luau/OverloadResolution.h" #include "Luau/Subtyping.h" +#include "Luau/TimeTrace.h" #include "Luau/ToString.h" #include "Luau/TxnLog.h" #include "Luau/Type.h" @@ -95,7 +96,7 @@ static std::optional getIdentifierOfBaseVar(AstExpr* node) template bool areEquivalent(const T& a, const T& b) { - if (a.family != b.family) + if (a.function != b.function) return false; if (a.typeArguments.size() != b.typeArguments.size() || a.packArguments.size() != b.packArguments.size()) @@ -116,39 +117,39 @@ bool areEquivalent(const T& a, const T& b) return true; } -struct FamilyFinder : TypeOnceVisitor +struct TypeFunctionFinder : TypeOnceVisitor { - DenseHashSet mentionedFamilies{nullptr}; - DenseHashSet mentionedFamilyPacks{nullptr}; + DenseHashSet mentionedFunctions{nullptr}; + DenseHashSet mentionedFunctionPacks{nullptr}; bool visit(TypeId ty, const TypeFunctionInstanceType&) override { - mentionedFamilies.insert(ty); + mentionedFunctions.insert(ty); return true; } bool visit(TypePackId tp, const TypeFunctionInstanceTypePack&) override { - mentionedFamilyPacks.insert(tp); + mentionedFunctionPacks.insert(tp); return true; } }; -struct InternalFamilyFinder : TypeOnceVisitor +struct InternalTypeFunctionFinder : TypeOnceVisitor { - DenseHashSet internalFamilies{nullptr}; - DenseHashSet internalPackFamilies{nullptr}; - DenseHashSet mentionedFamilies{nullptr}; - DenseHashSet mentionedFamilyPacks{nullptr}; + DenseHashSet internalFunctions{nullptr}; + DenseHashSet internalPackFunctions{nullptr}; + DenseHashSet mentionedFunctions{nullptr}; + DenseHashSet mentionedFunctionPacks{nullptr}; - InternalFamilyFinder(std::vector& declStack) + InternalTypeFunctionFinder(std::vector& declStack) { - FamilyFinder f; + TypeFunctionFinder f; for (TypeId fn : declStack) f.traverse(fn); - mentionedFamilies = std::move(f.mentionedFamilies); - mentionedFamilyPacks = std::move(f.mentionedFamilyPacks); + mentionedFunctions = std::move(f.mentionedFunctions); + mentionedFunctionPacks = std::move(f.mentionedFunctionPacks); } bool visit(TypeId ty, const TypeFunctionInstanceType& tfit) override @@ -175,7 +176,7 @@ struct InternalFamilyFinder : TypeOnceVisitor if (hasGeneric) { - for (TypeId mentioned : mentionedFamilies) + for (TypeId mentioned : mentionedFunctions) { const TypeFunctionInstanceType* mentionedTfit = get(mentioned); LUAU_ASSERT(mentionedTfit); @@ -185,7 +186,7 @@ struct InternalFamilyFinder : TypeOnceVisitor } } - internalFamilies.insert(ty); + internalFunctions.insert(ty); } return true; @@ -215,7 +216,7 @@ struct InternalFamilyFinder : TypeOnceVisitor if (hasGeneric) { - for (TypePackId mentioned : mentionedFamilyPacks) + for (TypePackId mentioned : mentionedFunctionPacks) { const TypeFunctionInstanceTypePack* mentionedTfitp = get(mentioned); LUAU_ASSERT(mentionedTfitp); @@ -225,7 +226,7 @@ struct InternalFamilyFinder : TypeOnceVisitor } } - internalPackFamilies.insert(tp); + internalPackFunctions.insert(tp); } return true; @@ -423,19 +424,19 @@ struct TypeChecker2 return std::nullopt; } - void checkForInternalFamily(TypeId ty, Location location) + void checkForInternalTypeFunction(TypeId ty, Location location) { - InternalFamilyFinder finder(functionDeclStack); + InternalTypeFunctionFinder finder(functionDeclStack); finder.traverse(ty); - for (TypeId internal : finder.internalFamilies) + for (TypeId internal : finder.internalFunctions) reportError(WhereClauseNeeded{internal}, location); - for (TypePackId internal : finder.internalPackFamilies) + for (TypePackId internal : finder.internalPackFunctions) reportError(PackWhereClauseNeeded{internal}, location); } - TypeId checkForFamilyInhabitance(TypeId instance, Location location) + TypeId checkForTypeFunctionInhabitance(TypeId instance, Location location) { if (seenTypeFunctionInstances.find(instance)) return instance; @@ -468,11 +469,11 @@ struct TypeChecker2 // allows us not to think about this very much in the actual typechecking logic. TypeId* ty = module->astTypes.find(expr); if (ty) - return checkForFamilyInhabitance(follow(*ty), expr->location); + return checkForTypeFunctionInhabitance(follow(*ty), expr->location); TypePackId* tp = module->astTypePacks.find(expr); if (tp) - return checkForFamilyInhabitance(flattenPack(*tp), expr->location); + return checkForTypeFunctionInhabitance(flattenPack(*tp), expr->location); return builtinTypes->anyType; } @@ -495,7 +496,7 @@ struct TypeChecker2 TypeId* ty = module->astResolvedTypes.find(annotation); LUAU_ASSERT(ty); - return checkForFamilyInhabitance(follow(*ty), annotation->location); + return checkForTypeFunctionInhabitance(follow(*ty), annotation->location); } std::optional lookupPackAnnotation(AstTypePack* annotation) @@ -1725,7 +1726,7 @@ struct TypeChecker2 visit(*fn->returnAnnotation); - // If the function type has a family annotation, we need to see if we can suggest an annotation + // If the function type has a function annotation, we need to see if we can suggest an annotation if (normalizedFnTy) { const FunctionType* inferredFtv = get(normalizedFnTy->functions.parts.front()); @@ -1855,7 +1856,7 @@ struct TypeChecker2 if (get(expectedResult)) { - checkForInternalFamily(expectedResult, expr->location); + checkForInternalTypeFunction(expectedResult, expr->location); return expectedResult; } @@ -2254,7 +2255,7 @@ struct TypeChecker2 { TypeId* resolvedTy = module->astResolvedTypes.find(ty); if (resolvedTy) - checkForFamilyInhabitance(follow(*resolvedTy), ty->location); + checkForTypeFunctionInhabitance(follow(*resolvedTy), ty->location); if (auto t = ty->as()) return visit(t); @@ -3057,6 +3058,8 @@ struct TypeChecker2 void check(NotNull builtinTypes, NotNull unifierState, NotNull limits, DcrLogger* logger, const SourceModule& sourceModule, Module* module) { + LUAU_TIMETRACE_SCOPE("check", "Typechecking"); + TypeChecker2 typeChecker{builtinTypes, unifierState, limits, logger, &sourceModule, module}; typeChecker.visit(sourceModule.root); diff --git a/Analysis/src/TypeFunction.cpp b/Analysis/src/TypeFunction.cpp index 136eac69..28b18289 100644 --- a/Analysis/src/TypeFunction.cpp +++ b/Analysis/src/TypeFunction.cpp @@ -104,7 +104,7 @@ struct TypeFunctionReducer VecDeque queuedTys; VecDeque queuedTps; TypeOrTypePackIdSet shouldGuess; - std::vector cyclicTypeFamilies; + std::vector cyclicTypeFunctions; TypeOrTypePackIdSet irreducible{nullptr}; FunctionGraphReductionResult result; bool force = false; @@ -118,7 +118,7 @@ struct TypeFunctionReducer , queuedTys(std::move(queuedTys)) , queuedTps(std::move(queuedTps)) , shouldGuess(std::move(shouldGuess)) - , cyclicTypeFamilies(std::move(cyclicTypes)) + , cyclicTypeFunctions(std::move(cyclicTypes)) , force(force) , location(location) { @@ -138,7 +138,7 @@ struct TypeFunctionReducer if (is(ty)) { - for (auto t : cyclicTypeFamilies) + for (auto t : cyclicTypeFunctions) { if (ty == t) return SkipTestResult::CyclicTypeFunction; @@ -339,7 +339,7 @@ struct TypeFunctionReducer if (!testParameters(subject, tfit) && testCyclic != SkipTestResult::CyclicTypeFunction) { if (FFlag::DebugLuauLogTypeFamilies) - printf("Irreducible due to irreducible/pending and a non-cyclic family\n"); + printf("Irreducible due to irreducible/pending and a non-cyclic function\n"); return; } @@ -347,7 +347,7 @@ struct TypeFunctionReducer if (tryGuessing(subject)) return; - TypeFunctionReductionResult result = tfit->family->reducer(subject, tfit->typeArguments, tfit->packArguments, NotNull{&ctx}); + TypeFunctionReductionResult result = tfit->function->reducer(subject, tfit->typeArguments, tfit->packArguments, NotNull{&ctx}); handleTypeFunctionReduction(subject, result); } } @@ -371,7 +371,7 @@ struct TypeFunctionReducer if (tryGuessing(subject)) return; - TypeFunctionReductionResult result = tfit->family->reducer(subject, tfit->typeArguments, tfit->packArguments, NotNull{&ctx}); + TypeFunctionReductionResult result = tfit->function->reducer(subject, tfit->typeArguments, tfit->packArguments, NotNull{&ctx}); handleTypeFunctionReduction(subject, result); } } @@ -385,7 +385,7 @@ struct TypeFunctionReducer } }; -static FunctionGraphReductionResult reduceFamiliesInternal(VecDeque queuedTys, VecDeque queuedTps, TypeOrTypePackIdSet shouldGuess, +static FunctionGraphReductionResult reduceFunctionsInternal(VecDeque queuedTys, VecDeque queuedTps, TypeOrTypePackIdSet shouldGuess, std::vector cyclics, Location location, TypeFunctionContext ctx, bool force) { TypeFunctionReducer reducer{std::move(queuedTys), std::move(queuedTps), std::move(shouldGuess), std::move(cyclics), location, ctx, force}; @@ -422,7 +422,7 @@ FunctionGraphReductionResult reduceTypeFunctions(TypeId entrypoint, Location loc if (collector.tys.empty() && collector.tps.empty()) return {}; - return reduceFamiliesInternal(std::move(collector.tys), std::move(collector.tps), std::move(collector.shouldGuess), + return reduceFunctionsInternal(std::move(collector.tys), std::move(collector.tps), std::move(collector.shouldGuess), std::move(collector.cyclicInstance), location, ctx, force); } @@ -442,7 +442,7 @@ FunctionGraphReductionResult reduceTypeFunctions(TypePackId entrypoint, Location if (collector.tys.empty() && collector.tps.empty()) return {}; - return reduceFamiliesInternal(std::move(collector.tys), std::move(collector.tps), std::move(collector.shouldGuess), + return reduceFunctionsInternal(std::move(collector.tys), std::move(collector.tps), std::move(collector.shouldGuess), std::move(collector.cyclicInstance), location, ctx, force); } @@ -528,7 +528,7 @@ static std::optional> tryDistributeTypeFunct return std::nullopt; } -TypeFunctionReductionResult notFamilyFn( +TypeFunctionReductionResult notTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 1 || !packParams.empty()) @@ -545,14 +545,14 @@ TypeFunctionReductionResult notFamilyFn( if (isPending(ty, ctx->solver)) return {std::nullopt, false, {ty}, {}}; - if (auto result = tryDistributeTypeFunctionApp(notFamilyFn, instance, typeParams, packParams, ctx)) + if (auto result = tryDistributeTypeFunctionApp(notTypeFunction, instance, typeParams, packParams, ctx)) return *result; // `not` operates on anything and returns a `boolean` always. return {ctx->builtins->booleanType, false, {}, {}}; } -TypeFunctionReductionResult lenFamilyFn( +TypeFunctionReductionResult lenTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 1 || !packParams.empty()) @@ -604,7 +604,7 @@ TypeFunctionReductionResult lenFamilyFn( if (normTy->hasTopTable() || get(normalizedOperand)) return {ctx->builtins->numberType, false, {}, {}}; - if (auto result = tryDistributeTypeFunctionApp(notFamilyFn, instance, typeParams, packParams, ctx)) + if (auto result = tryDistributeTypeFunctionApp(notTypeFunction, instance, typeParams, packParams, ctx)) return *result; // findMetatableEntry demands the ability to emit errors, so we must give it @@ -644,7 +644,7 @@ TypeFunctionReductionResult lenFamilyFn( return {ctx->builtins->numberType, false, {}, {}}; } -TypeFunctionReductionResult unmFamilyFn( +TypeFunctionReductionResult unmTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 1 || !packParams.empty()) @@ -689,7 +689,7 @@ TypeFunctionReductionResult unmFamilyFn( if (normTy->isExactlyNumber()) return {ctx->builtins->numberType, false, {}, {}}; - if (auto result = tryDistributeTypeFunctionApp(notFamilyFn, instance, typeParams, packParams, ctx)) + if (auto result = tryDistributeTypeFunctionApp(notTypeFunction, instance, typeParams, packParams, ctx)) return *result; // findMetatableEntry demands the ability to emit errors, so we must give it @@ -744,7 +744,7 @@ NotNull TypeFunctionContext::pushConstraint(ConstraintV&& c) return newConstraint; } -TypeFunctionReductionResult numericBinopFamilyFn(TypeId instance, const std::vector& typeParams, +TypeFunctionReductionResult numericBinopTypeFunction(TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx, const std::string metamethod) { if (typeParams.size() != 2 || !packParams.empty()) @@ -787,7 +787,7 @@ TypeFunctionReductionResult numericBinopFamilyFn(TypeId instance, const rhsTy = *rhsMaybeGeneralized; } - // TODO: Normalization needs to remove cyclic type families from a `NormalizedType`. + // TODO: Normalization needs to remove cyclic type functions from a `NormalizedType`. std::shared_ptr normLhsTy = ctx->normalizer->normalize(lhsTy); std::shared_ptr normRhsTy = ctx->normalizer->normalize(rhsTy); @@ -803,7 +803,7 @@ TypeFunctionReductionResult numericBinopFamilyFn(TypeId instance, const if (normLhsTy->isExactlyNumber() && normRhsTy->isExactlyNumber()) return {ctx->builtins->numberType, false, {}, {}}; - if (auto result = tryDistributeTypeFunctionApp(numericBinopFamilyFn, instance, typeParams, packParams, ctx, metamethod)) + if (auto result = tryDistributeTypeFunctionApp(numericBinopTypeFunction, instance, typeParams, packParams, ctx, metamethod)) return *result; // findMetatableEntry demands the ability to emit errors, so we must give it @@ -847,7 +847,7 @@ TypeFunctionReductionResult numericBinopFamilyFn(TypeId instance, const return {extracted.head.front(), false, {}, {}}; } -TypeFunctionReductionResult addFamilyFn( +TypeFunctionReductionResult addTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -856,10 +856,10 @@ TypeFunctionReductionResult addFamilyFn( LUAU_ASSERT(false); } - return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__add"); + return numericBinopTypeFunction(instance, typeParams, packParams, ctx, "__add"); } -TypeFunctionReductionResult subFamilyFn( +TypeFunctionReductionResult subTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -868,10 +868,10 @@ TypeFunctionReductionResult subFamilyFn( LUAU_ASSERT(false); } - return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__sub"); + return numericBinopTypeFunction(instance, typeParams, packParams, ctx, "__sub"); } -TypeFunctionReductionResult mulFamilyFn( +TypeFunctionReductionResult mulTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -880,10 +880,10 @@ TypeFunctionReductionResult mulFamilyFn( LUAU_ASSERT(false); } - return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__mul"); + return numericBinopTypeFunction(instance, typeParams, packParams, ctx, "__mul"); } -TypeFunctionReductionResult divFamilyFn( +TypeFunctionReductionResult divTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -892,10 +892,10 @@ TypeFunctionReductionResult divFamilyFn( LUAU_ASSERT(false); } - return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__div"); + return numericBinopTypeFunction(instance, typeParams, packParams, ctx, "__div"); } -TypeFunctionReductionResult idivFamilyFn( +TypeFunctionReductionResult idivTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -904,10 +904,10 @@ TypeFunctionReductionResult idivFamilyFn( LUAU_ASSERT(false); } - return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__idiv"); + return numericBinopTypeFunction(instance, typeParams, packParams, ctx, "__idiv"); } -TypeFunctionReductionResult powFamilyFn( +TypeFunctionReductionResult powTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -916,10 +916,10 @@ TypeFunctionReductionResult powFamilyFn( LUAU_ASSERT(false); } - return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__pow"); + return numericBinopTypeFunction(instance, typeParams, packParams, ctx, "__pow"); } -TypeFunctionReductionResult modFamilyFn( +TypeFunctionReductionResult modTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -928,10 +928,10 @@ TypeFunctionReductionResult modFamilyFn( LUAU_ASSERT(false); } - return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__mod"); + return numericBinopTypeFunction(instance, typeParams, packParams, ctx, "__mod"); } -TypeFunctionReductionResult concatFamilyFn( +TypeFunctionReductionResult concatTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -987,7 +987,7 @@ TypeFunctionReductionResult concatFamilyFn( if ((normLhsTy->isSubtypeOfString() || normLhsTy->isExactlyNumber()) && (normRhsTy->isSubtypeOfString() || normRhsTy->isExactlyNumber())) return {ctx->builtins->stringType, false, {}, {}}; - if (auto result = tryDistributeTypeFunctionApp(concatFamilyFn, instance, typeParams, packParams, ctx)) + if (auto result = tryDistributeTypeFunctionApp(concatTypeFunction, instance, typeParams, packParams, ctx)) return *result; // findMetatableEntry demands the ability to emit errors, so we must give it @@ -1039,7 +1039,7 @@ TypeFunctionReductionResult concatFamilyFn( return {ctx->builtins->stringType, false, {}, {}}; } -TypeFunctionReductionResult andFamilyFn( +TypeFunctionReductionResult andTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -1090,7 +1090,7 @@ TypeFunctionReductionResult andFamilyFn( return {overallResult.result, false, std::move(blockedTypes), {}}; } -TypeFunctionReductionResult orFamilyFn( +TypeFunctionReductionResult orTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -1141,7 +1141,7 @@ TypeFunctionReductionResult orFamilyFn( return {overallResult.result, false, std::move(blockedTypes), {}}; } -static TypeFunctionReductionResult comparisonFamilyFn(TypeId instance, const std::vector& typeParams, +static TypeFunctionReductionResult comparisonTypeFunction(TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx, const std::string metamethod) { @@ -1162,7 +1162,7 @@ static TypeFunctionReductionResult comparisonFamilyFn(TypeId instance, c else if (isPending(rhsTy, ctx->solver)) return {std::nullopt, false, {rhsTy}, {}}; - // Algebra Reduction Rules for comparison family functions + // Algebra Reduction Rules for comparison type functions // Note that comparing to never tells you nothing about the other operand // lt< 'a , never> -> continue // lt< never, 'a> -> continue @@ -1173,7 +1173,7 @@ static TypeFunctionReductionResult comparisonFamilyFn(TypeId instance, c bool rhsFree = get(rhsTy) != nullptr; if (canSubmitConstraint) { - // Implement injective type families for comparison type families + // Implement injective type functions for comparison type functions // lt implies t is number // lt implies t is number if (lhsFree && isNumber(rhsTy)) @@ -1238,7 +1238,7 @@ static TypeFunctionReductionResult comparisonFamilyFn(TypeId instance, c if (normLhsTy->isExactlyNumber() && normRhsTy->isExactlyNumber()) return {ctx->builtins->booleanType, false, {}, {}}; - if (auto result = tryDistributeTypeFunctionApp(comparisonFamilyFn, instance, typeParams, packParams, ctx, metamethod)) + if (auto result = tryDistributeTypeFunctionApp(comparisonTypeFunction, instance, typeParams, packParams, ctx, metamethod)) return *result; // findMetatableEntry demands the ability to emit errors, so we must give it @@ -1280,7 +1280,7 @@ static TypeFunctionReductionResult comparisonFamilyFn(TypeId instance, c return {ctx->builtins->booleanType, false, {}, {}}; } -TypeFunctionReductionResult ltFamilyFn( +TypeFunctionReductionResult ltTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -1289,10 +1289,10 @@ TypeFunctionReductionResult ltFamilyFn( LUAU_ASSERT(false); } - return comparisonFamilyFn(instance, typeParams, packParams, ctx, "__lt"); + return comparisonTypeFunction(instance, typeParams, packParams, ctx, "__lt"); } -TypeFunctionReductionResult leFamilyFn( +TypeFunctionReductionResult leTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -1301,10 +1301,10 @@ TypeFunctionReductionResult leFamilyFn( LUAU_ASSERT(false); } - return comparisonFamilyFn(instance, typeParams, packParams, ctx, "__le"); + return comparisonTypeFunction(instance, typeParams, packParams, ctx, "__le"); } -TypeFunctionReductionResult eqFamilyFn( +TypeFunctionReductionResult eqTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -1381,7 +1381,7 @@ TypeFunctionReductionResult eqFamilyFn( return {ctx->builtins->falseType, false, {}, {}}; } - return {std::nullopt, true, {}, {}}; // if it's not, then this family is irreducible! + return {std::nullopt, true, {}, {}}; // if it's not, then this type function is irreducible! } mmType = follow(*mmType); @@ -1435,7 +1435,7 @@ struct FindRefinementBlockers : TypeOnceVisitor }; -TypeFunctionReductionResult refineFamilyFn( +TypeFunctionReductionResult refineTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -1520,7 +1520,7 @@ TypeFunctionReductionResult refineFamilyFn( return {resultTy, false, {}, {}}; } -TypeFunctionReductionResult singletonFamilyFn( +TypeFunctionReductionResult singletonTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 1 || !packParams.empty()) @@ -1557,7 +1557,7 @@ TypeFunctionReductionResult singletonFamilyFn( return {ctx->builtins->unknownType, false, {}, {}}; } -TypeFunctionReductionResult unionFamilyFn( +TypeFunctionReductionResult unionTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (!packParams.empty()) @@ -1618,7 +1618,7 @@ TypeFunctionReductionResult unionFamilyFn( } -TypeFunctionReductionResult intersectFamilyFn( +TypeFunctionReductionResult intersectTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (!packParams.empty()) @@ -1725,7 +1725,7 @@ bool computeKeysOf(TypeId ty, Set& result, DenseHashSet& se return false; } -TypeFunctionReductionResult keyofFamilyImpl( +TypeFunctionReductionResult keyofFunctionImpl( const std::vector& typeParams, const std::vector& packParams, NotNull ctx, bool isRaw) { if (typeParams.size() != 1 || !packParams.empty()) @@ -1842,7 +1842,7 @@ TypeFunctionReductionResult keyofFamilyImpl( return {ctx->arena->addType(UnionType{singletons}), false, {}, {}}; } -TypeFunctionReductionResult keyofFamilyFn( +TypeFunctionReductionResult keyofTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 1 || !packParams.empty()) @@ -1851,10 +1851,10 @@ TypeFunctionReductionResult keyofFamilyFn( LUAU_ASSERT(false); } - return keyofFamilyImpl(typeParams, packParams, ctx, /* isRaw */ false); + return keyofFunctionImpl(typeParams, packParams, ctx, /* isRaw */ false); } -TypeFunctionReductionResult rawkeyofFamilyFn( +TypeFunctionReductionResult rawkeyofTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 1 || !packParams.empty()) @@ -1863,7 +1863,7 @@ TypeFunctionReductionResult rawkeyofFamilyFn( LUAU_ASSERT(false); } - return keyofFamilyImpl(typeParams, packParams, ctx, /* isRaw */ true); + return keyofFunctionImpl(typeParams, packParams, ctx, /* isRaw */ true); } /* Searches through table's or class's props/indexer to find the property of `ty` @@ -1960,7 +1960,7 @@ bool tblIndexInto(TypeId indexer, TypeId indexee, DenseHashSet& result, /* Vocabulary note: indexee refers to the type that contains the properties, indexer refers to the type that is used to access indexee Example: index => `Person` is the indexee and `"name"` is the indexer */ -TypeFunctionReductionResult indexFamilyImpl( +TypeFunctionReductionResult indexFunctionImpl( const std::vector& typeParams, const std::vector& packParams, NotNull ctx, bool isRaw) { TypeId indexeeTy = follow(typeParams.at(0)); @@ -2064,7 +2064,7 @@ TypeFunctionReductionResult indexFamilyImpl( return {ctx->arena->addType(UnionType{std::vector(properties.begin(), properties.end())}), false, {}, {}}; } -TypeFunctionReductionResult indexFamilyFn( +TypeFunctionReductionResult indexTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -2073,10 +2073,10 @@ TypeFunctionReductionResult indexFamilyFn( LUAU_ASSERT(false); } - return indexFamilyImpl(typeParams, packParams, ctx, /* isRaw */ false); + return indexFunctionImpl(typeParams, packParams, ctx, /* isRaw */ false); } -TypeFunctionReductionResult rawgetFamilyFn( +TypeFunctionReductionResult rawgetTypeFunction( TypeId instance, const std::vector& typeParams, const std::vector& packParams, NotNull ctx) { if (typeParams.size() != 2 || !packParams.empty()) @@ -2085,34 +2085,34 @@ TypeFunctionReductionResult rawgetFamilyFn( LUAU_ASSERT(false); } - return indexFamilyImpl(typeParams, packParams, ctx, /* isRaw */ true); + return indexFunctionImpl(typeParams, packParams, ctx, /* isRaw */ true); } BuiltinTypeFunctions::BuiltinTypeFunctions() - : notFunc{"not", notFamilyFn} - , lenFunc{"len", lenFamilyFn} - , unmFunc{"unm", unmFamilyFn} - , addFunc{"add", addFamilyFn} - , subFunc{"sub", subFamilyFn} - , mulFunc{"mul", mulFamilyFn} - , divFunc{"div", divFamilyFn} - , idivFunc{"idiv", idivFamilyFn} - , powFunc{"pow", powFamilyFn} - , modFunc{"mod", modFamilyFn} - , concatFunc{"concat", concatFamilyFn} - , andFunc{"and", andFamilyFn} - , orFunc{"or", orFamilyFn} - , ltFunc{"lt", ltFamilyFn} - , leFunc{"le", leFamilyFn} - , eqFunc{"eq", eqFamilyFn} - , refineFunc{"refine", refineFamilyFn} - , singletonFunc{"singleton", singletonFamilyFn} - , unionFunc{"union", unionFamilyFn} - , intersectFunc{"intersect", intersectFamilyFn} - , keyofFunc{"keyof", keyofFamilyFn} - , rawkeyofFunc{"rawkeyof", rawkeyofFamilyFn} - , indexFunc{"index", indexFamilyFn} - , rawgetFunc{"rawget", rawgetFamilyFn} + : notFunc{"not", notTypeFunction} + , lenFunc{"len", lenTypeFunction} + , unmFunc{"unm", unmTypeFunction} + , addFunc{"add", addTypeFunction} + , subFunc{"sub", subTypeFunction} + , mulFunc{"mul", mulTypeFunction} + , divFunc{"div", divTypeFunction} + , idivFunc{"idiv", idivTypeFunction} + , powFunc{"pow", powTypeFunction} + , modFunc{"mod", modTypeFunction} + , concatFunc{"concat", concatTypeFunction} + , andFunc{"and", andTypeFunction} + , orFunc{"or", orTypeFunction} + , ltFunc{"lt", ltTypeFunction} + , leFunc{"le", leTypeFunction} + , eqFunc{"eq", eqTypeFunction} + , refineFunc{"refine", refineTypeFunction} + , singletonFunc{"singleton", singletonTypeFunction} + , unionFunc{"union", unionTypeFunction} + , intersectFunc{"intersect", intersectTypeFunction} + , keyofFunc{"keyof", keyofTypeFunction} + , rawkeyofFunc{"rawkeyof", rawkeyofTypeFunction} + , indexFunc{"index", indexTypeFunction} + , rawgetFunc{"rawget", rawgetTypeFunction} { } diff --git a/Analysis/src/TypeFunctionReductionGuesser.cpp b/Analysis/src/TypeFunctionReductionGuesser.cpp index 9279c1d3..fac8ef16 100644 --- a/Analysis/src/TypeFunctionReductionGuesser.cpp +++ b/Analysis/src/TypeFunctionReductionGuesser.cpp @@ -83,7 +83,7 @@ bool TypeFunctionReductionGuesser::isFunctionGenericsSaturated(const FunctionTyp void TypeFunctionReductionGuesser::dumpGuesses() { - for (auto [tf, t] : familyReducesTo) + for (auto [tf, t] : functionReducesTo) printf("Type family %s ~~> %s\n", toString(tf).c_str(), toString(t).c_str()); for (auto [t, t_] : substitutable) printf("Substitute %s for %s\n", toString(t).c_str(), toString(t_).c_str()); @@ -175,7 +175,7 @@ TypeFunctionReductionGuessResult TypeFunctionReductionGuesser::guessTypeFunction toInfer.clear(); cyclicInstances.clear(); - familyReducesTo.clear(); + functionReducesTo.clear(); substitutable.clear(); return TypeFunctionReductionGuessResult{results, recommendedAnnotation}; @@ -196,44 +196,44 @@ std::optional TypeFunctionReductionGuesser::guessType(TypeId arg) } if (get(t)) { - if (familyReducesTo.contains(t)) - return familyReducesTo[t]; + if (functionReducesTo.contains(t)) + return functionReducesTo[t]; } return {}; } -bool TypeFunctionReductionGuesser::isNumericBinopFamily(const TypeFunctionInstanceType& instance) +bool TypeFunctionReductionGuesser::isNumericBinopFunction(const TypeFunctionInstanceType& instance) { - return instance.family->name == "add" || instance.family->name == "sub" || instance.family->name == "mul" || instance.family->name == "div" || - instance.family->name == "idiv" || instance.family->name == "pow" || instance.family->name == "mod"; + return instance.function->name == "add" || instance.function->name == "sub" || instance.function->name == "mul" || instance.function->name == "div" || + instance.function->name == "idiv" || instance.function->name == "pow" || instance.function->name == "mod"; } -bool TypeFunctionReductionGuesser::isComparisonFamily(const TypeFunctionInstanceType& instance) +bool TypeFunctionReductionGuesser::isComparisonFunction(const TypeFunctionInstanceType& instance) { - return instance.family->name == "lt" || instance.family->name == "le" || instance.family->name == "eq"; + return instance.function->name == "lt" || instance.function->name == "le" || instance.function->name == "eq"; } -bool TypeFunctionReductionGuesser::isOrAndFamily(const TypeFunctionInstanceType& instance) +bool TypeFunctionReductionGuesser::isOrAndFunction(const TypeFunctionInstanceType& instance) { - return instance.family->name == "or" || instance.family->name == "and"; + return instance.function->name == "or" || instance.function->name == "and"; } -bool TypeFunctionReductionGuesser::isNotFamily(const TypeFunctionInstanceType& instance) +bool TypeFunctionReductionGuesser::isNotFunction(const TypeFunctionInstanceType& instance) { - return instance.family->name == "not"; + return instance.function->name == "not"; } -bool TypeFunctionReductionGuesser::isLenFamily(const TypeFunctionInstanceType& instance) +bool TypeFunctionReductionGuesser::isLenFunction(const TypeFunctionInstanceType& instance) { - return instance.family->name == "len"; + return instance.function->name == "len"; } bool TypeFunctionReductionGuesser::isUnaryMinus(const TypeFunctionInstanceType& instance) { - return instance.family->name == "unm"; + return instance.function->name == "unm"; } -// Operand is assignable if it looks like a cyclic family instance, or a generic type +// Operand is assignable if it looks like a cyclic function instance, or a generic type bool TypeFunctionReductionGuesser::operandIsAssignable(TypeId ty) { if (get(ty)) @@ -257,8 +257,8 @@ std::optional TypeFunctionReductionGuesser::tryAssignOperandType(TypeId // We try to check if we guessed a type for it if (auto tfit = get(ty)) { - if (familyReducesTo.contains(ty)) - return {familyReducesTo[ty]}; + if (functionReducesTo.contains(ty)) + return {functionReducesTo[ty]}; } // If ty is a generic, we need to check if we inferred a substitution @@ -298,24 +298,24 @@ void TypeFunctionReductionGuesser::inferTypeFunctionSubstitutions(TypeId ty, con TypeFunctionInferenceResult result; LUAU_ASSERT(instance); // TODO: Make an inexhaustive version of this warn in the compiler? - if (isNumericBinopFamily(*instance)) - result = inferNumericBinopFamily(instance); - else if (isComparisonFamily(*instance)) - result = inferComparisonFamily(instance); - else if (isOrAndFamily(*instance)) - result = inferOrAndFamily(instance); - else if (isNotFamily(*instance)) - result = inferNotFamily(instance); - else if (isLenFamily(*instance)) - result = inferLenFamily(instance); + if (isNumericBinopFunction(*instance)) + result = inferNumericBinopFunction(instance); + else if (isComparisonFunction(*instance)) + result = inferComparisonFunction(instance); + else if (isOrAndFunction(*instance)) + result = inferOrAndFunction(instance); + else if (isNotFunction(*instance)) + result = inferNotFunction(instance); + else if (isLenFunction(*instance)) + result = inferLenFunction(instance); else if (isUnaryMinus(*instance)) - result = inferUnaryMinusFamily(instance); + result = inferUnaryMinusFunction(instance); else result = {{}, builtins->unknownType}; - TypeId resultInference = follow(result.familyResultInference); - if (!familyReducesTo.contains(resultInference)) - familyReducesTo[ty] = resultInference; + TypeId resultInference = follow(result.functionResultInference); + if (!functionReducesTo.contains(resultInference)) + functionReducesTo[ty] = resultInference; for (size_t i = 0; i < instance->typeArguments.size(); i++) { @@ -325,8 +325,8 @@ void TypeFunctionReductionGuesser::inferTypeFunctionSubstitutions(TypeId ty, con TypeId inference = follow(result.operandInference[i]); if (auto tfit = get(arg)) { - if (!familyReducesTo.contains(arg)) - familyReducesTo.try_insert(arg, inference); + if (!functionReducesTo.contains(arg)) + functionReducesTo.try_insert(arg, inference); } else if (auto gt = get(arg)) substitutable[arg] = inference; @@ -334,17 +334,17 @@ void TypeFunctionReductionGuesser::inferTypeFunctionSubstitutions(TypeId ty, con } } -TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferNumericBinopFamily(const TypeFunctionInstanceType* instance) +TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferNumericBinopFunction(const TypeFunctionInstanceType* instance) { LUAU_ASSERT(instance->typeArguments.size() == 2); TypeFunctionInferenceResult defaultNumericBinopInference{{builtins->numberType, builtins->numberType}, builtins->numberType}; return defaultNumericBinopInference; } -TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferComparisonFamily(const TypeFunctionInstanceType* instance) +TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferComparisonFunction(const TypeFunctionInstanceType* instance) { LUAU_ASSERT(instance->typeArguments.size() == 2); - // Comparison families are lt/le/eq. + // Comparison functions are lt/le/eq. // Heuristic: these are type functions from t -> t -> bool TypeId lhsTy = follow(instance->typeArguments[0]); @@ -365,7 +365,7 @@ TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferComparisonFamily( return comparisonInference(builtins->numberType); } -TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferOrAndFamily(const TypeFunctionInstanceType* instance) +TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferOrAndFunction(const TypeFunctionInstanceType* instance) { LUAU_ASSERT(instance->typeArguments.size() == 2); @@ -384,7 +384,7 @@ TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferOrAndFamily(const bool lhsTruthy = lty ? lty->isTruthy() : false; bool rhsTruthy = rty ? rty->isTruthy() : false; // If at the end, we still don't have good substitutions, return the default type - if (instance->family->name == "or") + if (instance->function->name == "or") { if (operandIsAssignable(lhsTy) && operandIsAssignable(rhsTy)) return defaultAndOrInference; @@ -398,7 +398,7 @@ TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferOrAndFamily(const return {{builtins->unknownType, rhsTy}, rhsTy}; } - if (instance->family->name == "and") + if (instance->function->name == "and") { if (operandIsAssignable(lhsTy) && operandIsAssignable(rhsTy)) @@ -416,7 +416,7 @@ TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferOrAndFamily(const return defaultAndOrInference; } -TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferNotFamily(const TypeFunctionInstanceType* instance) +TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferNotFunction(const TypeFunctionInstanceType* instance) { LUAU_ASSERT(instance->typeArguments.size() == 1); TypeId opTy = follow(instance->typeArguments[0]); @@ -425,7 +425,7 @@ TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferNotFamily(const T return {{opTy}, builtins->booleanType}; } -TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferLenFamily(const TypeFunctionInstanceType* instance) +TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferLenFunction(const TypeFunctionInstanceType* instance) { LUAU_ASSERT(instance->typeArguments.size() == 1); TypeId opTy = follow(instance->typeArguments[0]); @@ -434,7 +434,7 @@ TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferLenFamily(const T return {{opTy}, builtins->numberType}; } -TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferUnaryMinusFamily(const TypeFunctionInstanceType* instance) +TypeFunctionInferenceResult TypeFunctionReductionGuesser::inferUnaryMinusFunction(const TypeFunctionInstanceType* instance) { LUAU_ASSERT(instance->typeArguments.size() == 1); TypeId opTy = follow(instance->typeArguments[0]); diff --git a/Analysis/src/Unifier2.cpp b/Analysis/src/Unifier2.cpp index c43edbd1..df448113 100644 --- a/Analysis/src/Unifier2.cpp +++ b/Analysis/src/Unifier2.cpp @@ -92,19 +92,19 @@ Unifier2::Unifier2(NotNull arena, NotNull builtinTypes, , ice(ice) , limits(TypeCheckLimits{}) // TODO: typecheck limits in unifier2 , recursionLimit(FInt::LuauTypeInferRecursionLimit) - , uninhabitedTypeFamilies(nullptr) + , uninhabitedTypeFunctions(nullptr) { } Unifier2::Unifier2(NotNull arena, NotNull builtinTypes, NotNull scope, NotNull ice, - DenseHashSet* uninhabitedTypeFamilies) + DenseHashSet* uninhabitedTypeFunctions) : arena(arena) , builtinTypes(builtinTypes) , scope(scope) , ice(ice) , limits(TypeCheckLimits{}) // TODO: typecheck limits in unifier2 , recursionLimit(FInt::LuauTypeInferRecursionLimit) - , uninhabitedTypeFamilies(uninhabitedTypeFamilies) + , uninhabitedTypeFunctions(uninhabitedTypeFunctions) { } @@ -135,7 +135,7 @@ bool Unifier2::unify(TypeId subTy, TypeId superTy) // - *blocked* <: unknown if ((isIrresolvable(subTy) || isIrresolvable(superTy)) && !get(subTy) && !get(superTy)) { - if (uninhabitedTypeFamilies && (uninhabitedTypeFamilies->contains(subTy) || uninhabitedTypeFamilies->contains(superTy))) + if (uninhabitedTypeFunctions && (uninhabitedTypeFunctions->contains(subTy) || uninhabitedTypeFunctions->contains(superTy))) return true; incompleteSubtypes.push_back(SubtypeConstraint{subTy, superTy}); @@ -539,7 +539,7 @@ bool Unifier2::unify(TypePackId subTp, TypePackId superTp) if (isIrresolvable(subTp) || isIrresolvable(superTp)) { - if (uninhabitedTypeFamilies && (uninhabitedTypeFamilies->contains(subTp) || uninhabitedTypeFamilies->contains(superTp))) + if (uninhabitedTypeFunctions && (uninhabitedTypeFunctions->contains(subTp) || uninhabitedTypeFunctions->contains(superTp))) return true; incompleteSubtypes.push_back(PackSubtypeConstraint{subTp, superTp}); diff --git a/EqSat/src/UnionFind.cpp b/EqSat/src/UnionFind.cpp index 5c01e968..4d7dd4b2 100644 --- a/EqSat/src/UnionFind.cpp +++ b/EqSat/src/UnionFind.cpp @@ -11,7 +11,6 @@ Id UnionFind::makeSet() Id id{parents.size()}; parents.push_back(id); ranks.push_back(0); - return id; } diff --git a/tests/Error.test.cpp b/tests/Error.test.cpp index 00a5a2e7..431b326d 100644 --- a/tests/Error.test.cpp +++ b/tests/Error.test.cpp @@ -36,7 +36,7 @@ local x: Account = 5 CHECK_EQ("Type 'number' could not be converted into 'Account'", toString(result.errors[0])); } -TEST_CASE_FIXTURE(BuiltinsFixture, "binary_op_type_family_errors") +TEST_CASE_FIXTURE(BuiltinsFixture, "binary_op_type_function_errors") { frontend.options.retainFullTypeGraphs = false; @@ -54,7 +54,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "binary_op_type_family_errors") CHECK_EQ("Type 'string' could not be converted into 'number'", toString(result.errors[0])); } -TEST_CASE_FIXTURE(BuiltinsFixture, "unary_op_type_family_errors") +TEST_CASE_FIXTURE(BuiltinsFixture, "unary_op_type_function_errors") { frontend.options.retainFullTypeGraphs = false; diff --git a/tests/Frontend.test.cpp b/tests/Frontend.test.cpp index 9ae1a1de..a6999466 100644 --- a/tests/Frontend.test.cpp +++ b/tests/Frontend.test.cpp @@ -311,7 +311,7 @@ TEST_CASE_FIXTURE(FrontendFixture, "nocheck_cycle_used_by_checked") REQUIRE(bool(cExports)); if (FFlag::DebugLuauDeferredConstraintResolution) - CHECK_EQ("{ a: any, b: any }", toString(*cExports)); + CHECK_EQ("{ a: { hello: any }, b: { hello: any } }", toString(*cExports)); else CHECK_EQ("{| a: any, b: any |}", toString(*cExports)); } diff --git a/tests/Linter.test.cpp b/tests/Linter.test.cpp index b758764d..d74c4855 100644 --- a/tests/Linter.test.cpp +++ b/tests/Linter.test.cpp @@ -28,7 +28,7 @@ end REQUIRE(0 == result.warnings.size()); } -TEST_CASE_FIXTURE(Fixture, "type_family_fully_reduces") +TEST_CASE_FIXTURE(Fixture, "type_function_fully_reduces") { LintResult result = lint(R"( function fib(n) diff --git a/tests/Normalize.test.cpp b/tests/Normalize.test.cpp index e8a10e92..29dcc6d3 100644 --- a/tests/Normalize.test.cpp +++ b/tests/Normalize.test.cpp @@ -404,8 +404,16 @@ TEST_CASE_FIXTURE(IsSubtypeFixture, "error_suppression") CHECK(!isSubtype(any, str)); CHECK(isSubtype(str, any)); - CHECK(!isSubtype(any, unk)); - CHECK(isSubtype(unk, any)); + // We have added this as an exception - the set of inhabitants of any is exactly the set of inhabitants of unknown (since error has no + // inhabitants). any = err | unknown, so under semantic subtyping, {} U unknown = unknown + if (FFlag::DebugLuauDeferredConstraintResolution) + { + CHECK(isSubtype(any, unk)); + } + else + { + CHECK(!isSubtype(any, unk)); + } CHECK(!isSubtype(err, str)); CHECK(!isSubtype(str, err)); diff --git a/tests/Subtyping.test.cpp b/tests/Subtyping.test.cpp index 832049a4..a748de62 100644 --- a/tests/Subtyping.test.cpp +++ b/tests/Subtyping.test.cpp @@ -470,9 +470,11 @@ TEST_CASE_FIXTURE(SubtypeFixture, "variadic_subpath_in_pack") CHECK(!result.isSubtype); } -TEST_CASE_FIXTURE(SubtypeFixture, "any anyType, builtinTypes->unknownType); + // We have added this as an exception - the set of inhabitants of any is exactly the set of inhabitants of unknown (since error has no + // inhabitants). any = err | unknown, so under semantic subtyping, {} U unknown = unknown + CHECK_IS_SUBTYPE(builtinTypes->anyType, builtinTypes->unknownType); } TEST_CASE_FIXTURE(SubtypeFixture, "number? <: unknown") @@ -990,39 +992,51 @@ TEST_CASE_FIXTURE(SubtypeFixture, "semantic_subtyping_disj") TEST_CASE_FIXTURE(SubtypeFixture, "t1 where t1 = {trim: (t1) -> string} <: t2 where t2 = {trim: (t2) -> string}") { - TypeId t1 = cyclicTable([&](TypeId ty, TableType* tt) { - tt->props["trim"] = fn({ty}, {builtinTypes->stringType}); - }); + TypeId t1 = cyclicTable( + [&](TypeId ty, TableType* tt) + { + tt->props["trim"] = fn({ty}, {builtinTypes->stringType}); + }); - TypeId t2 = cyclicTable([&](TypeId ty, TableType* tt) { - tt->props["trim"] = fn({ty}, {builtinTypes->stringType}); - }); + TypeId t2 = cyclicTable( + [&](TypeId ty, TableType* tt) + { + tt->props["trim"] = fn({ty}, {builtinTypes->stringType}); + }); CHECK_IS_SUBTYPE(t1, t2); } TEST_CASE_FIXTURE(SubtypeFixture, "t1 where t1 = {trim: (t1) -> string} t2}") { - TypeId t1 = cyclicTable([&](TypeId ty, TableType* tt) { - tt->props["trim"] = fn({ty}, {builtinTypes->stringType}); - }); + TypeId t1 = cyclicTable( + [&](TypeId ty, TableType* tt) + { + tt->props["trim"] = fn({ty}, {builtinTypes->stringType}); + }); - TypeId t2 = cyclicTable([&](TypeId ty, TableType* tt) { - tt->props["trim"] = fn({ty}, {ty}); - }); + TypeId t2 = cyclicTable( + [&](TypeId ty, TableType* tt) + { + tt->props["trim"] = fn({ty}, {ty}); + }); CHECK_IS_NOT_SUBTYPE(t1, t2); } TEST_CASE_FIXTURE(SubtypeFixture, "t1 where t1 = {trim: (t1) -> t1} string}") { - TypeId t1 = cyclicTable([&](TypeId ty, TableType* tt) { - tt->props["trim"] = fn({ty}, {ty}); - }); + TypeId t1 = cyclicTable( + [&](TypeId ty, TableType* tt) + { + tt->props["trim"] = fn({ty}, {ty}); + }); - TypeId t2 = cyclicTable([&](TypeId ty, TableType* tt) { - tt->props["trim"] = fn({ty}, {builtinTypes->stringType}); - }); + TypeId t2 = cyclicTable( + [&](TypeId ty, TableType* tt) + { + tt->props["trim"] = fn({ty}, {builtinTypes->stringType}); + }); CHECK_IS_NOT_SUBTYPE(t1, t2); } @@ -1286,7 +1300,7 @@ TEST_CASE_FIXTURE(SubtypeFixture, "({ x: T }) -> T <: ({ method: ({ x: T } CHECK_IS_SUBTYPE(tableToPropType, otherType); } -TEST_CASE_FIXTURE(SubtypeFixture, "subtyping_reasonings_to_follow_a_reduced_type_family_instance") +TEST_CASE_FIXTURE(SubtypeFixture, "subtyping_reasonings_to_follow_a_reduced_type_function_instance") { TypeId longTy = arena.addType(UnionType{{builtinTypes->booleanType, builtinTypes->bufferType, builtinTypes->classType, builtinTypes->functionType, builtinTypes->numberType, builtinTypes->stringType, builtinTypes->tableType, builtinTypes->threadType}}); @@ -1323,8 +1337,8 @@ TEST_CASE_FIXTURE(SubtypeFixture, "table_property") CHECK(!result.isSubtype); REQUIRE(result.reasoning.size() == 1); CHECK(*result.reasoning.begin() == SubtypingReasoning{/* subPath */ Path(TypePath::Property::read("X")), - /* superPath */ Path(TypePath::Property::read("X")), - /* variance */ SubtypingVariance::Invariant}); + /* superPath */ Path(TypePath::Property::read("X")), + /* variance */ SubtypingVariance::Invariant}); } TEST_CASE_FIXTURE(SubtypeFixture, "table_indexers") @@ -1397,9 +1411,9 @@ TEST_CASE_FIXTURE(SubtypeFixture, "fn_rets") CHECK(!result.isSubtype); REQUIRE(result.reasoning.size() == 1); CHECK(*result.reasoning.begin() == SubtypingReasoning{ - /* subPath */ TypePath::PathBuilder().rets().index(0).build(), - /* superPath */ TypePath::PathBuilder().rets().index(0).build(), - }); + /* subPath */ TypePath::PathBuilder().rets().index(0).build(), + /* superPath */ TypePath::PathBuilder().rets().index(0).build(), + }); } TEST_CASE_FIXTURE(SubtypeFixture, "fn_rets_tail") @@ -1411,9 +1425,9 @@ TEST_CASE_FIXTURE(SubtypeFixture, "fn_rets_tail") CHECK(!result.isSubtype); REQUIRE(result.reasoning.size() == 1); CHECK(*result.reasoning.begin() == SubtypingReasoning{ - /* subPath */ TypePath::PathBuilder().rets().tail().variadic().build(), - /* superPath */ TypePath::PathBuilder().rets().tail().variadic().build(), - }); + /* subPath */ TypePath::PathBuilder().rets().tail().variadic().build(), + /* superPath */ TypePath::PathBuilder().rets().tail().variadic().build(), + }); } TEST_CASE_FIXTURE(SubtypeFixture, "nested_table_properties") @@ -1425,10 +1439,10 @@ TEST_CASE_FIXTURE(SubtypeFixture, "nested_table_properties") CHECK(!result.isSubtype); REQUIRE(result.reasoning.size() == 1); CHECK(*result.reasoning.begin() == SubtypingReasoning{ - /* subPath */ TypePath::PathBuilder().readProp("X").readProp("Y").readProp("Z").build(), - /* superPath */ TypePath::PathBuilder().readProp("X").readProp("Y").readProp("Z").build(), - /* variance */ SubtypingVariance::Invariant, - }); + /* subPath */ TypePath::PathBuilder().readProp("X").readProp("Y").readProp("Z").build(), + /* superPath */ TypePath::PathBuilder().readProp("X").readProp("Y").readProp("Z").build(), + /* variance */ SubtypingVariance::Invariant, + }); } TEST_CASE_FIXTURE(SubtypeFixture, "string_table_mt") diff --git a/tests/TypeFunction.test.cpp b/tests/TypeFunction.test.cpp index 9638b3ff..0c87a395 100644 --- a/tests/TypeFunction.test.cpp +++ b/tests/TypeFunction.test.cpp @@ -15,14 +15,14 @@ using namespace Luau; LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution) LUAU_DYNAMIC_FASTINT(LuauTypeFamilyApplicationCartesianProductLimit) -struct FamilyFixture : Fixture +struct TypeFunctionFixture : Fixture { - TypeFunction swapFamily; + TypeFunction swapFunction; - FamilyFixture() + TypeFunctionFixture() : Fixture(true, false) { - swapFamily = TypeFunction{/* name */ "Swap", + swapFunction = TypeFunction{/* name */ "Swap", /* reducer */ [](TypeId instance, const std::vector& tys, const std::vector& tps, NotNull ctx) -> TypeFunctionReductionResult { @@ -54,14 +54,14 @@ struct FamilyFixture : Fixture ScopePtr globalScope = frontend.globals.globalScope; globalScope->exportedTypeBindings["Swap"] = - TypeFun{{genericT}, frontend.globals.globalTypes.addType(TypeFunctionInstanceType{NotNull{&swapFamily}, {t}, {}})}; + TypeFun{{genericT}, frontend.globals.globalTypes.addType(TypeFunctionInstanceType{NotNull{&swapFunction}, {t}, {}})}; freeze(frontend.globals.globalTypes); } }; TEST_SUITE_BEGIN("TypeFunctionTests"); -TEST_CASE_FIXTURE(FamilyFixture, "basic_type_family") +TEST_CASE_FIXTURE(TypeFunctionFixture, "basic_type_function") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -83,7 +83,7 @@ TEST_CASE_FIXTURE(FamilyFixture, "basic_type_family") CHECK("Type function instance Swap is uninhabited" == toString(result.errors[0])); }; -TEST_CASE_FIXTURE(FamilyFixture, "family_as_fn_ret") +TEST_CASE_FIXTURE(TypeFunctionFixture, "function_as_fn_ret") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -102,7 +102,7 @@ TEST_CASE_FIXTURE(FamilyFixture, "family_as_fn_ret") CHECK("Type function instance Swap is uninhabited" == toString(result.errors[0])); } -TEST_CASE_FIXTURE(FamilyFixture, "family_as_fn_arg") +TEST_CASE_FIXTURE(TypeFunctionFixture, "function_as_fn_arg") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -121,7 +121,7 @@ TEST_CASE_FIXTURE(FamilyFixture, "family_as_fn_arg") CHECK("Type function instance Swap is uninhabited" == toString(result.errors[1])); } -TEST_CASE_FIXTURE(FamilyFixture, "resolve_deep_families") +TEST_CASE_FIXTURE(TypeFunctionFixture, "resolve_deep_functions") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -134,7 +134,7 @@ TEST_CASE_FIXTURE(FamilyFixture, "resolve_deep_families") CHECK("number" == toString(requireType("x"))); } -TEST_CASE_FIXTURE(FamilyFixture, "unsolvable_family") +TEST_CASE_FIXTURE(TypeFunctionFixture, "unsolvable_function") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -152,7 +152,7 @@ TEST_CASE_FIXTURE(FamilyFixture, "unsolvable_family") } } -TEST_CASE_FIXTURE(FamilyFixture, "table_internal_families") +TEST_CASE_FIXTURE(TypeFunctionFixture, "table_internal_functions") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -172,7 +172,7 @@ TEST_CASE_FIXTURE(FamilyFixture, "table_internal_families") CHECK(toString(result.errors[0]) == "Type function instance Swap is uninhabited"); } -TEST_CASE_FIXTURE(FamilyFixture, "function_internal_families") +TEST_CASE_FIXTURE(TypeFunctionFixture, "function_internal_functions") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -193,7 +193,7 @@ TEST_CASE_FIXTURE(FamilyFixture, "function_internal_families") CHECK(toString(result.errors[0]) == "Type function instance Swap is uninhabited"); } -TEST_CASE_FIXTURE(Fixture, "add_family_at_work") +TEST_CASE_FIXTURE(Fixture, "add_function_at_work") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -216,7 +216,7 @@ TEST_CASE_FIXTURE(Fixture, "add_family_at_work") CHECK(toString(result.errors[1]) == "Type function instance Add is uninhabited"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "cyclic_add_family_at_work") +TEST_CASE_FIXTURE(BuiltinsFixture, "cyclic_add_function_at_work") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -229,7 +229,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "cyclic_add_family_at_work") CHECK(toString(requireTypeAlias("T")) == "number"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "mul_family_with_union_of_multiplicatives") +TEST_CASE_FIXTURE(BuiltinsFixture, "mul_function_with_union_of_multiplicatives") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -252,7 +252,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "mul_family_with_union_of_multiplicatives") CHECK(toString(requireTypeAlias("T")) == "Vec2 | Vec3"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "mul_family_with_union_of_multiplicatives_2") +TEST_CASE_FIXTURE(BuiltinsFixture, "mul_function_with_union_of_multiplicatives_2") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -272,7 +272,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "mul_family_with_union_of_multiplicatives_2") CHECK(toString(requireTypeAlias("T")) == "Vec3"); } -TEST_CASE_FIXTURE(Fixture, "internal_families_raise_errors") +TEST_CASE_FIXTURE(Fixture, "internal_functions_raise_errors") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -288,7 +288,7 @@ TEST_CASE_FIXTURE(Fixture, "internal_families_raise_errors") "signature; this construct cannot be type-checked at this time"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "type_families_can_be_shadowed") +TEST_CASE_FIXTURE(BuiltinsFixture, "type_functions_can_be_shadowed") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -313,7 +313,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "type_families_can_be_shadowed") CHECK(toString(requireType("plus")) == "(a, b) -> add"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "type_families_inhabited_with_normalization") +TEST_CASE_FIXTURE(BuiltinsFixture, "type_functions_inhabited_with_normalization") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -331,7 +331,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "type_families_inhabited_with_normalization") LUAU_REQUIRE_NO_ERRORS(result); } -TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_works") +TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_function_works") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -352,7 +352,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_works") CHECK_EQ("\"x\" | \"y\" | \"z\"", toString(tpm->givenTp)); } -TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_works_with_metatables") +TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_function_works_with_metatables") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -375,7 +375,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_works_with_metatables") CHECK_EQ("\"w\" | \"x\" | \"y\" | \"z\"", toString(tpm->givenTp)); } -TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_errors_if_it_has_nontable_part") +TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_function_errors_if_it_has_nontable_part") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -393,7 +393,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_errors_if_it_has_nontable_ CHECK(toString(result.errors[1]) == "Type 'MyObject | boolean' does not have keys, so 'keyof' is invalid"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_string_indexer") +TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_function_string_indexer") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -421,7 +421,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_string_indexer") CHECK_EQ("\"x\" | \"y\" | \"z\"", toString(tpm->givenTp)); } -TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_common_subset_if_union_of_differing_tables") +TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_function_common_subset_if_union_of_differing_tables") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -442,7 +442,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_common_subset_if_union_of_ CHECK_EQ("\"y\" | \"z\"", toString(tpm->givenTp)); } -TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_never_for_empty_table") +TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_function_never_for_empty_table") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -457,7 +457,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_type_family_never_for_empty_table") CHECK(toString(requireType("foo")) == "never"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_family_works") +TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_function_works") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -478,7 +478,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_family_works") CHECK_EQ("\"x\" | \"y\" | \"z\"", toString(tpm->givenTp)); } -TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_family_ignores_metatables") +TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_function_ignores_metatables") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -501,7 +501,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_family_ignores_metatables") CHECK_EQ("\"x\" | \"y\" | \"z\"", toString(tpm->givenTp)); } -TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_family_errors_if_it_has_nontable_part") +TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_function_errors_if_it_has_nontable_part") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -519,7 +519,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_family_errors_if_it_has_nontab CHECK(toString(result.errors[1]) == "Type 'MyObject | boolean' does not have keys, so 'rawkeyof' is invalid"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_family_common_subset_if_union_of_differing_tables") +TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_function_common_subset_if_union_of_differing_tables") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -540,7 +540,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_family_common_subset_if_union_ CHECK_EQ("\"y\" | \"z\"", toString(tpm->givenTp)); } -TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_family_never_for_empty_table") +TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_function_never_for_empty_table") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -555,7 +555,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "rawkeyof_type_family_never_for_empty_table") CHECK(toString(requireType("foo")) == "never"); } -TEST_CASE_FIXTURE(ClassFixture, "keyof_type_family_works_on_classes") +TEST_CASE_FIXTURE(ClassFixture, "keyof_type_function_works_on_classes") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -575,7 +575,7 @@ TEST_CASE_FIXTURE(ClassFixture, "keyof_type_family_works_on_classes") CHECK_EQ("\"BaseField\" | \"BaseMethod\" | \"Touched\"", toString(tpm->givenTp)); } -TEST_CASE_FIXTURE(ClassFixture, "keyof_type_family_errors_if_it_has_nonclass_part") +TEST_CASE_FIXTURE(ClassFixture, "keyof_type_function_errors_if_it_has_nonclass_part") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -592,7 +592,7 @@ TEST_CASE_FIXTURE(ClassFixture, "keyof_type_family_errors_if_it_has_nonclass_par CHECK(toString(result.errors[1]) == "Type 'BaseClass | boolean' does not have keys, so 'keyof' is invalid"); } -TEST_CASE_FIXTURE(ClassFixture, "keyof_type_family_common_subset_if_union_of_differing_classes") +TEST_CASE_FIXTURE(ClassFixture, "keyof_type_function_common_subset_if_union_of_differing_classes") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -606,7 +606,7 @@ TEST_CASE_FIXTURE(ClassFixture, "keyof_type_family_common_subset_if_union_of_dif LUAU_REQUIRE_NO_ERRORS(result); } -TEST_CASE_FIXTURE(ClassFixture, "binary_type_family_works_with_default_argument") +TEST_CASE_FIXTURE(ClassFixture, "binary_type_function_works_with_default_argument") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -699,7 +699,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "keyof_oss_crash_gh1161") CHECK(get(result.errors[0])); } -TEST_CASE_FIXTURE(FamilyFixture, "fuzzer_numeric_binop_doesnt_assert_on_generalizeFreeType") +TEST_CASE_FIXTURE(TypeFunctionFixture, "fuzzer_numeric_binop_doesnt_assert_on_generalizeFreeType") { CheckResult result = check(R"( Module 'l0': @@ -714,7 +714,7 @@ _(setmetatable(_,{[...]=_,})) )"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "cyclic_concat_family_at_work") +TEST_CASE_FIXTURE(BuiltinsFixture, "cyclic_concat_function_at_work") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -827,7 +827,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "ensure_equivalence_with_distributivity") CHECK(toString(requireTypeAlias("U")) == "A | A | B | B"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "we_shouldnt_warn_that_a_reducible_type_family_is_uninhabited") +TEST_CASE_FIXTURE(BuiltinsFixture, "we_shouldnt_warn_that_a_reducible_type_function_is_uninhabited") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -857,7 +857,7 @@ end LUAU_REQUIRE_NO_ERRORS(result); } -TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works") +TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_function_works") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -880,7 +880,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works") CHECK_EQ("string", toString(tpm->givenTp)); } -TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works_w_array") +TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_function_works_w_array") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -895,7 +895,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works_w_array") LUAU_REQUIRE_NO_ERRORS(result); } -TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works_w_generic_types") +TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_function_works_w_generic_types") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -917,7 +917,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works_w_generic_types") LUAU_REQUIRE_NO_ERRORS(result); } -TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_errors_w_bad_indexer") +TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_function_errors_w_bad_indexer") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -933,7 +933,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_errors_w_bad_indexer") CHECK(toString(result.errors[1]) == "Property 'boolean' does not exist on type 'MyObject'"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_errors_w_var_indexer") +TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_function_errors_w_var_indexer") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -950,7 +950,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_errors_w_var_indexer") CHECK(toString(result.errors[1]) == "Unknown type 'key'"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works_w_union_type_indexer") +TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_function_works_w_union_type_indexer") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -968,7 +968,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works_w_union_type_indexer CHECK(toString(result.errors[0]) == "Property '\"a\" | \"d\"' does not exist on type 'MyObject'"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works_w_union_type_indexee") +TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_function_works_w_union_type_indexee") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -987,7 +987,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works_w_union_type_indexee CHECK(toString(result.errors[0]) == "Property '\"b\"' does not exist on type 'MyObject | MyObject2'"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_rfc_alternative_section") +TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_function_rfc_alternative_section") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -1005,7 +1005,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_rfc_alternative_section") CHECK(toString(result.errors[0]) == "Property '\"b\"' does not exist on type 'MyObject'"); } -TEST_CASE_FIXTURE(ClassFixture, "index_type_family_works_on_classes") +TEST_CASE_FIXTURE(ClassFixture, "index_type_function_works_on_classes") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -1019,7 +1019,7 @@ TEST_CASE_FIXTURE(ClassFixture, "index_type_family_works_on_classes") LUAU_REQUIRE_NO_ERRORS(result); } -TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works_w_index_metatables") +TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_function_works_w_index_metatables") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -1045,7 +1045,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_family_works_w_index_metatables") CHECK(toString(result.errors[0]) == "Property '\"Car\"' does not exist on type 'exampleClass2'"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_works") +TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_function_works") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -1067,7 +1067,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_works") CHECK_EQ("string", toString(tpm->givenTp)); } -TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_works_w_array") +TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_function_works_w_array") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -1081,7 +1081,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_works_w_array") LUAU_REQUIRE_NO_ERRORS(result); } -TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_errors_w_var_indexer") +TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_function_errors_w_var_indexer") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -1097,7 +1097,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_errors_w_var_indexer") CHECK(toString(result.errors[1]) == "Unknown type 'key'"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_works_w_union_type_indexer") +TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_function_works_w_union_type_indexer") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -1113,7 +1113,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_works_w_union_type_indexe CHECK(toString(result.errors[0]) == "Property '\"a\" | \"d\"' does not exist on type 'MyObject'"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_works_w_union_type_indexee") +TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_function_works_w_union_type_indexee") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -1130,7 +1130,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_works_w_union_type_indexe CHECK(toString(result.errors[0]) == "Property '\"b\"' does not exist on type 'MyObject | MyObject2'"); } -TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_works_w_index_metatables") +TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_function_works_w_index_metatables") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -1150,7 +1150,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "rawget_type_family_works_w_index_metatables" CHECK(toString(result.errors[1]) == "Property '\"Bar\" | \"Foo\"' does not exist on type 'exampleClass3'"); } -TEST_CASE_FIXTURE(ClassFixture, "rawget_type_family_errors_w_classes") +TEST_CASE_FIXTURE(ClassFixture, "rawget_type_function_errors_w_classes") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; diff --git a/tests/TypeInfer.anyerror.test.cpp b/tests/TypeInfer.anyerror.test.cpp index d1cbd048..dc1c6199 100644 --- a/tests/TypeInfer.anyerror.test.cpp +++ b/tests/TypeInfer.anyerror.test.cpp @@ -32,7 +32,10 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_returns_any") LUAU_REQUIRE_NO_ERRORS(result); - CHECK(builtinTypes->anyType == requireType("a")); + if (FFlag::DebugLuauDeferredConstraintResolution) + CHECK("any?" == toString(requireType("a"))); + else + CHECK(builtinTypes->anyType == requireType("a")); } TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_returns_any2") @@ -50,7 +53,10 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_returns_any2") LUAU_REQUIRE_NO_ERRORS(result); - CHECK("any" == toString(requireType("a"))); + if (FFlag::DebugLuauDeferredConstraintResolution) + CHECK("any?" == toString(requireType("a"))); + else + CHECK("any" == toString(requireType("a"))); } TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_is_any") @@ -66,7 +72,10 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_is_any") LUAU_REQUIRE_NO_ERRORS(result); - CHECK("any" == toString(requireType("a"))); + if (FFlag::DebugLuauDeferredConstraintResolution) + CHECK("any?" == toString(requireType("a"))); + else + CHECK("any" == toString(requireType("a"))); } TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_is_any2") @@ -80,7 +89,10 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_is_any2") end )"); - CHECK("any" == toString(requireType("a"))); + if (FFlag::DebugLuauDeferredConstraintResolution) + CHECK("any?" == toString(requireType("a"))); + else + CHECK("any" == toString(requireType("a"))); } TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_is_any_pack") @@ -96,7 +108,10 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_is_any_pack") LUAU_REQUIRE_NO_ERRORS(result); - CHECK("any" == toString(requireType("a"))); + if (FFlag::DebugLuauDeferredConstraintResolution) + CHECK("any?" == toString(requireType("a"))); + else + CHECK("any" == toString(requireType("a"))); } TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_is_error") @@ -291,7 +306,11 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "replace_every_free_type_when_unifying_a_comp )"); LUAU_REQUIRE_NO_ERRORS(result); - CHECK_EQ("any", toString(requireType("b"))); + + if (FFlag::DebugLuauDeferredConstraintResolution) + CHECK_EQ("any?", toString(requireType("b"))); + else + CHECK_EQ("any", toString(requireType("b"))); } TEST_CASE_FIXTURE(Fixture, "call_to_any_yields_any") diff --git a/tests/TypeInfer.generics.test.cpp b/tests/TypeInfer.generics.test.cpp index 93fbc945..b98d5a87 100644 --- a/tests/TypeInfer.generics.test.cpp +++ b/tests/TypeInfer.generics.test.cpp @@ -1424,7 +1424,7 @@ TEST_CASE_FIXTURE(Fixture, "missing_generic_type_parameter") REQUIRE(get(result.errors[1])); } -TEST_CASE_FIXTURE(BuiltinsFixture, "generic_type_families_work_in_subtyping") +TEST_CASE_FIXTURE(BuiltinsFixture, "generic_type_functions_work_in_subtyping") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; diff --git a/tests/TypeInfer.operators.test.cpp b/tests/TypeInfer.operators.test.cpp index 929f8159..0d1ccbbe 100644 --- a/tests/TypeInfer.operators.test.cpp +++ b/tests/TypeInfer.operators.test.cpp @@ -745,7 +745,7 @@ TEST_CASE_FIXTURE(Fixture, "strict_binary_op_where_lhs_unknown") if (FFlag::DebugLuauDeferredConstraintResolution) { LUAU_REQUIRE_ERROR_COUNT(ops.size(), result); - CHECK_EQ("Type family instance Add depends on generic function parameters but does not appear in the function signature; this " + CHECK_EQ("Type function instance Add depends on generic function parameters but does not appear in the function signature; this " "construct cannot be type-checked at this time", toString(result.errors[0])); CHECK_EQ("Unknown type used in - operation; consider adding a type annotation to 'a'", toString(result.errors[1])); @@ -1456,7 +1456,7 @@ return startsWith LUAU_REQUIRE_NO_ERRORS(result); } -TEST_CASE_FIXTURE(Fixture, "add_type_family_works") +TEST_CASE_FIXTURE(Fixture, "add_type_function_works") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -1473,7 +1473,7 @@ TEST_CASE_FIXTURE(Fixture, "add_type_family_works") LUAU_REQUIRE_ERROR_COUNT(1, result); CHECK(toString(requireType("a")) == "number"); CHECK(toString(requireType("b")) == "Add"); - CHECK(toString(result.errors[0]) == "Type family instance Add is uninhabited"); + CHECK(toString(result.errors[0]) == "Type function instance Add is uninhabited"); } TEST_CASE_FIXTURE(BuiltinsFixture, "normalize_strings_comparison") diff --git a/tests/TypeInfer.tables.test.cpp b/tests/TypeInfer.tables.test.cpp index 8ddfc190..4788545c 100644 --- a/tests/TypeInfer.tables.test.cpp +++ b/tests/TypeInfer.tables.test.cpp @@ -25,7 +25,7 @@ LUAU_DYNAMIC_FASTFLAG(LuauImproveNonFunctionCallError) TEST_SUITE_BEGIN("TableTests"); -TEST_CASE_FIXTURE(BuiltinsFixture, "generalization_shouldnt_seal_table_in_len_family_fn") +TEST_CASE_FIXTURE(BuiltinsFixture, "generalization_shouldnt_seal_table_in_len_function_fn") { if (!FFlag::DebugLuauDeferredConstraintResolution) return; @@ -4579,4 +4579,27 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "metatable_table_assertion_crash") )"); } +TEST_CASE_FIXTURE(BuiltinsFixture, "table::insert_should_not_report_errors_when_correct_overload_is_picked") +{ + CheckResult result = check(R"( +type cs = { GetTagged : (cs, string) -> any} +local destroyQueue: {any} = {} -- pair of (time, coin) +local tick : () -> any +local CS : cs +local DESTROY_DELAY +local function SpawnCoin() + local spawns = CS:GetTagged('CoinSpawner') + local n : any + local StartPos = spawns[n].CFrame + local Coin = script.Coin:Clone() + Coin.CFrame = StartPos + Coin.Parent = workspace.Coins + + table.insert(destroyQueue, {tick() + DESTROY_DELAY, Coin}) +end +)"); + + LUAU_REQUIRE_NO_ERRORS(result); +} + TEST_SUITE_END(); diff --git a/tools/faillist.txt b/tools/faillist.txt index 51f086ff..8a31b430 100644 --- a/tools/faillist.txt +++ b/tools/faillist.txt @@ -39,7 +39,6 @@ Differ.negation FrontendTest.environments FrontendTest.imported_table_modification_2 FrontendTest.it_should_be_safe_to_stringify_errors_when_full_type_graph_is_discarded -FrontendTest.nocheck_cycle_used_by_checked FrontendTest.trace_requires_in_nonstrict_mode GenericsTests.apply_type_function_nested_generics1 GenericsTests.better_mismatch_error_messages @@ -54,7 +53,7 @@ GenericsTests.generic_argument_count_too_few GenericsTests.generic_argument_count_too_many GenericsTests.generic_factories GenericsTests.generic_functions_in_types -GenericsTests.generic_type_families_work_in_subtyping +GenericsTests.generic_type_functions_work_in_subtyping GenericsTests.generic_type_pack_parentheses GenericsTests.generic_type_pack_unification1 GenericsTests.generic_type_pack_unification2 @@ -246,18 +245,18 @@ TypeAliases.report_shadowed_aliases TypeAliases.type_alias_local_mutation TypeAliases.type_alias_local_rename TypeAliases.type_alias_of_an_imported_recursive_generic_type -TypeFunctionTests.add_family_at_work -TypeFunctionTests.cyclic_add_family_at_work -TypeFunctionTests.cyclic_concat_family_at_work +TypeFunctionTests.add_function_at_work +TypeFunctionTests.cyclic_add_function_at_work +TypeFunctionTests.cyclic_concat_function_at_work TypeFunctionTests.didnt_quite_exceed_distributivity_limits TypeFunctionTests.ensure_equivalence_with_distributivity -TypeFunctionTests.family_as_fn_arg -TypeFunctionTests.index_type_family_works_w_generic_types -TypeFunctionTests.internal_families_raise_errors +TypeFunctionTests.function_as_fn_arg +TypeFunctionTests.index_type_function_works_w_generic_types +TypeFunctionTests.internal_functions_raise_errors TypeFunctionTests.keyof_oss_crash_gh1161 -TypeFunctionTests.mul_family_with_union_of_multiplicatives -TypeFunctionTests.mul_family_with_union_of_multiplicatives_2 -TypeFunctionTests.unsolvable_family +TypeFunctionTests.mul_function_with_union_of_multiplicatives +TypeFunctionTests.mul_function_with_union_of_multiplicatives_2 +TypeFunctionTests.unsolvable_function TypeInfer.be_sure_to_use_active_txnlog_when_evaluating_a_variadic_overload TypeInfer.check_type_infer_recursion_count TypeInfer.checking_should_not_ice @@ -277,12 +276,6 @@ 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 -TypeInferAnyError.for_in_loop_iterator_is_any -TypeInferAnyError.for_in_loop_iterator_is_any2 -TypeInferAnyError.for_in_loop_iterator_is_any_pack -TypeInferAnyError.for_in_loop_iterator_returns_any -TypeInferAnyError.for_in_loop_iterator_returns_any2 -TypeInferAnyError.replace_every_free_type_when_unifying_a_complex_function_with_any TypeInferClasses.callable_classes TypeInferClasses.cannot_unify_class_instance_with_primitive TypeInferClasses.class_type_mismatch_with_name_conflict @@ -370,7 +363,7 @@ 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.promise_type_error_too_complex -TypeInferOperators.add_type_family_works +TypeInferOperators.add_type_function_works TypeInferOperators.cli_38355_recursive_union TypeInferOperators.compound_assign_result_must_be_compatible_with_var TypeInferOperators.concat_op_on_free_lhs_and_string_rhs