mirror of
https://github.com/luau-lang/luau.git
synced 2025-08-26 11:27:08 +01:00
Sync to upstream/release/682 (#1912)
# What's changed? Another somewhat quiet week! Don't let the large PR fool you, this is mostly ... ## New Solver * The code for type functions has been re-organized: instead of _everything_ living in `TypeFunction.h` and `TypeFunction.cpp`, we now have separate files for the type function inference machinery (`TypeFunction.h`), definitions of built-in type functions (`BuiltinTypeFunctions.h`), and the implementation of user defined type functions (`UserDefinedTypeFunction.h`). * Refinements against `*no-refine*`, a sentinel type indicating that no refinements should occur, are now _always_ resolved, even if the target of the refinement would be otherwise pending, such as another type function. ## Autocomplete * Fixed autocomplete to prefer table property completion to string singleton completion. In the below example, the types associated with each member of `foo` will be displayed in autocomplete popups. ``` local foo = { ["Item/Foo"] = 42, ["Item/Bar"] = "it's true", ["Item/Baz"] = true, } foo["|"] -- cursor at `|` ``` ## Native Codegen * Fixed native compilation lowering of the new global lookup instruction, which caused code generation to fail with an error or to evaluate incorrect results. Issue affected 678-681 releases when all flags were enabled. --- Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Ariel Weiss <aaronweiss@roblox.com> Co-authored-by: Hunter Goldstein <hgoldstein@roblox.com> Co-authored-by: Sora Kanosue <skanosue@roblox.com> Co-authored-by: Talha Pathan <tpathan@roblox.com> Co-authored-by: Vighnesh Vijay <vvijay@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com>
This commit is contained in:
parent
60cd88af32
commit
6ff0650a8d
54 changed files with 3794 additions and 3941 deletions
56
Analysis/include/Luau/BuiltinTypeFunctions.h
Normal file
56
Analysis/include/Luau/BuiltinTypeFunctions.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||
#pragma once
|
||||
|
||||
#include "Luau/TypeFunction.h"
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
||||
struct BuiltinTypeFunctions
|
||||
{
|
||||
BuiltinTypeFunctions();
|
||||
|
||||
TypeFunction userFunc;
|
||||
|
||||
TypeFunction notFunc;
|
||||
TypeFunction lenFunc;
|
||||
TypeFunction unmFunc;
|
||||
|
||||
TypeFunction addFunc;
|
||||
TypeFunction subFunc;
|
||||
TypeFunction mulFunc;
|
||||
TypeFunction divFunc;
|
||||
TypeFunction idivFunc;
|
||||
TypeFunction powFunc;
|
||||
TypeFunction modFunc;
|
||||
|
||||
TypeFunction concatFunc;
|
||||
|
||||
TypeFunction andFunc;
|
||||
TypeFunction orFunc;
|
||||
|
||||
TypeFunction ltFunc;
|
||||
TypeFunction leFunc;
|
||||
TypeFunction eqFunc;
|
||||
|
||||
TypeFunction refineFunc;
|
||||
TypeFunction singletonFunc;
|
||||
TypeFunction unionFunc;
|
||||
TypeFunction intersectFunc;
|
||||
|
||||
TypeFunction keyofFunc;
|
||||
TypeFunction rawkeyofFunc;
|
||||
TypeFunction indexFunc;
|
||||
TypeFunction rawgetFunc;
|
||||
|
||||
TypeFunction setmetatableFunc;
|
||||
TypeFunction getmetatableFunc;
|
||||
|
||||
TypeFunction weakoptionalFunc;
|
||||
|
||||
void addToScope(NotNull<TypeArena> arena, NotNull<Scope> scope) const;
|
||||
};
|
||||
|
||||
const BuiltinTypeFunctions& builtinTypeFunctions();
|
||||
|
||||
}
|
|
@ -25,43 +25,7 @@ struct TypeFunctionRuntimeBuilderState;
|
|||
struct TypeFunctionContext;
|
||||
class Normalizer;
|
||||
|
||||
using StateRef = std::unique_ptr<lua_State, void (*)(lua_State*)>;
|
||||
|
||||
struct TypeFunctionRuntime
|
||||
{
|
||||
TypeFunctionRuntime(NotNull<InternalErrorReporter> ice, NotNull<TypeCheckLimits> limits);
|
||||
~TypeFunctionRuntime();
|
||||
|
||||
// Return value is an error message if registration failed
|
||||
std::optional<std::string> registerFunction(AstStatTypeFunction* function);
|
||||
|
||||
// For user-defined type functions, we store all generated types and packs for the duration of the typecheck
|
||||
TypedAllocator<TypeFunctionType> typeArena;
|
||||
TypedAllocator<TypeFunctionTypePackVar> typePackArena;
|
||||
|
||||
NotNull<InternalErrorReporter> ice;
|
||||
NotNull<TypeCheckLimits> limits;
|
||||
|
||||
StateRef state;
|
||||
|
||||
// Set of functions which have their environment table initialized
|
||||
DenseHashSet<AstStatTypeFunction*> initialized{nullptr};
|
||||
|
||||
// Evaluation of type functions should only be performed in the absence of parse errors in the source module
|
||||
bool allowEvaluation = true;
|
||||
|
||||
// Root scope in which the type function operates in, set up by ConstraintGenerator
|
||||
ScopePtr rootScope;
|
||||
|
||||
// Output created by 'print' function
|
||||
std::vector<std::string> messages;
|
||||
|
||||
// Type builder, valid for the duration of a single evaluation
|
||||
TypeFunctionRuntimeBuilderState* runtimeBuilder = nullptr;
|
||||
|
||||
private:
|
||||
void prepareState();
|
||||
};
|
||||
struct TypeFunctionRuntime;
|
||||
|
||||
struct TypeFunctionContext
|
||||
{
|
||||
|
@ -203,7 +167,7 @@ struct FunctionGraphReductionResult
|
|||
* @param normalizer the normalizer to use when normalizing types
|
||||
* @param ice the internal error reporter to use for ICEs
|
||||
*/
|
||||
FunctionGraphReductionResult reduceTypeFunctions(TypeId entrypoint, Location location, TypeFunctionContext, bool force = false);
|
||||
FunctionGraphReductionResult reduceTypeFunctions(TypeId entrypoint, Location location, NotNull<TypeFunctionContext> ctx, bool force = false);
|
||||
|
||||
/**
|
||||
* Attempt to reduce all instances of any type or type pack functions in the type
|
||||
|
@ -217,53 +181,13 @@ FunctionGraphReductionResult reduceTypeFunctions(TypeId entrypoint, Location loc
|
|||
* @param normalizer the normalizer to use when normalizing types
|
||||
* @param ice the internal error reporter to use for ICEs
|
||||
*/
|
||||
FunctionGraphReductionResult reduceTypeFunctions(TypePackId entrypoint, Location location, TypeFunctionContext, bool force = false);
|
||||
FunctionGraphReductionResult reduceTypeFunctions(TypePackId entrypoint, Location location, NotNull<TypeFunctionContext> ctx, bool force = false);
|
||||
|
||||
struct BuiltinTypeFunctions
|
||||
{
|
||||
BuiltinTypeFunctions();
|
||||
|
||||
TypeFunction userFunc;
|
||||
|
||||
TypeFunction notFunc;
|
||||
TypeFunction lenFunc;
|
||||
TypeFunction unmFunc;
|
||||
|
||||
TypeFunction addFunc;
|
||||
TypeFunction subFunc;
|
||||
TypeFunction mulFunc;
|
||||
TypeFunction divFunc;
|
||||
TypeFunction idivFunc;
|
||||
TypeFunction powFunc;
|
||||
TypeFunction modFunc;
|
||||
|
||||
TypeFunction concatFunc;
|
||||
|
||||
TypeFunction andFunc;
|
||||
TypeFunction orFunc;
|
||||
|
||||
TypeFunction ltFunc;
|
||||
TypeFunction leFunc;
|
||||
TypeFunction eqFunc;
|
||||
|
||||
TypeFunction refineFunc;
|
||||
TypeFunction singletonFunc;
|
||||
TypeFunction unionFunc;
|
||||
TypeFunction intersectFunc;
|
||||
|
||||
TypeFunction keyofFunc;
|
||||
TypeFunction rawkeyofFunc;
|
||||
TypeFunction indexFunc;
|
||||
TypeFunction rawgetFunc;
|
||||
|
||||
TypeFunction setmetatableFunc;
|
||||
TypeFunction getmetatableFunc;
|
||||
|
||||
TypeFunction weakoptionalFunc;
|
||||
|
||||
void addToScope(NotNull<TypeArena> arena, NotNull<Scope> scope) const;
|
||||
};
|
||||
|
||||
const BuiltinTypeFunctions& builtinTypeFunctions();
|
||||
/* Returns true if the type provided should block a type function from reducing.
|
||||
*
|
||||
* Most type functions cannot dispatch if one of their operands is a
|
||||
* BlockedType, a PendingExpansionType, or an unsolved TypeFunctionInstanceType.
|
||||
*/
|
||||
bool isPending(TypeId ty, ConstraintSolver* solver);
|
||||
|
||||
} // namespace Luau
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "Luau/Common.h"
|
||||
#include "Luau/Scope.h"
|
||||
#include "Luau/TypeFunctionRuntimeBuilder.h"
|
||||
#include "Luau/Type.h"
|
||||
#include "Luau/Variant.h"
|
||||
#include "Luau/TypeFwd.h"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
@ -15,17 +17,22 @@ using lua_State = struct lua_State;
|
|||
namespace Luau
|
||||
{
|
||||
|
||||
struct TypeFunctionRuntime;
|
||||
struct InternalErrorReporter;
|
||||
struct TypeCheckLimits;
|
||||
struct TypeFunctionRuntimeBuilderState;
|
||||
|
||||
struct LuauTempThreadPopper
|
||||
{
|
||||
explicit LuauTempThreadPopper(lua_State* L);
|
||||
~LuauTempThreadPopper();
|
||||
|
||||
lua_State* L = nullptr;
|
||||
};
|
||||
|
||||
using StateRef = std::unique_ptr<lua_State, void (*)(lua_State*)>;
|
||||
|
||||
void* typeFunctionAlloc(void* ud, void* ptr, size_t osize, size_t nsize);
|
||||
|
||||
// Replica of types from Type.h
|
||||
struct TypeFunctionType;
|
||||
using TypeFunctionTypeId = const TypeFunctionType*;
|
||||
|
||||
struct TypeFunctionTypePackVar;
|
||||
using TypeFunctionTypePackId = const TypeFunctionTypePackVar*;
|
||||
|
||||
struct TypeFunctionPrimitiveType
|
||||
{
|
||||
enum Type
|
||||
|
@ -274,6 +281,42 @@ T* getMutable(TypeFunctionTypeId tv)
|
|||
return tv ? Luau::get_if<T>(&const_cast<TypeFunctionType*>(tv)->type) : nullptr;
|
||||
}
|
||||
|
||||
struct TypeFunctionRuntime
|
||||
{
|
||||
TypeFunctionRuntime(NotNull<InternalErrorReporter> ice, NotNull<TypeCheckLimits> limits);
|
||||
~TypeFunctionRuntime();
|
||||
|
||||
// Return value is an error message if registration failed
|
||||
std::optional<std::string> registerFunction(AstStatTypeFunction* function);
|
||||
|
||||
// For user-defined type functions, we store all generated types and packs for the duration of the typecheck
|
||||
TypedAllocator<TypeFunctionType> typeArena;
|
||||
TypedAllocator<TypeFunctionTypePackVar> typePackArena;
|
||||
|
||||
NotNull<InternalErrorReporter> ice;
|
||||
NotNull<TypeCheckLimits> limits;
|
||||
|
||||
StateRef state;
|
||||
|
||||
// Set of functions which have their environment table initialized
|
||||
DenseHashSet<AstStatTypeFunction*> initialized{nullptr};
|
||||
|
||||
// Evaluation of type functions should only be performed in the absence of parse errors in the source module
|
||||
bool allowEvaluation = true;
|
||||
|
||||
// Root scope in which the type function operates in, set up by ConstraintGenerator
|
||||
ScopePtr rootScope;
|
||||
|
||||
// Output created by 'print' function
|
||||
std::vector<std::string> messages;
|
||||
|
||||
// Type builder, valid for the duration of a single evaluation
|
||||
TypeFunctionRuntimeBuilderState* runtimeBuilder = nullptr;
|
||||
|
||||
private:
|
||||
void prepareState();
|
||||
};
|
||||
|
||||
std::optional<std::string> checkResultForError(lua_State* L, const char* typeFunctionName, int luaResult);
|
||||
|
||||
TypeFunctionRuntime* getTypeFunctionRuntime(lua_State* L);
|
||||
|
|
|
@ -1,20 +1,12 @@
|
|||
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||
#pragma once
|
||||
|
||||
#include "Luau/Type.h"
|
||||
#include "Luau/TypeFunction.h"
|
||||
#include "Luau/TypeFunctionRuntime.h"
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
||||
using Kind = Variant<TypeId, TypePackId>;
|
||||
|
||||
template<typename T>
|
||||
const T* get(const Kind& kind)
|
||||
{
|
||||
return get_if<T>(&kind);
|
||||
}
|
||||
struct TypeFunctionContext;
|
||||
|
||||
using TypeFunctionKind = Variant<TypeFunctionTypeId, TypeFunctionTypePackId>;
|
||||
|
||||
|
|
|
@ -56,4 +56,10 @@ struct BuiltinTypes;
|
|||
|
||||
using TypeOrPack = Variant<TypeId, TypePackId>;
|
||||
|
||||
struct TypeFunctionType;
|
||||
using TypeFunctionTypeId = const TypeFunctionType*;
|
||||
|
||||
struct TypeFunctionTypePackVar;
|
||||
using TypeFunctionTypePackId = const TypeFunctionTypePackVar*;
|
||||
|
||||
} // namespace Luau
|
||||
|
|
17
Analysis/include/Luau/UserDefinedTypeFunction.h
Normal file
17
Analysis/include/Luau/UserDefinedTypeFunction.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||
#pragma once
|
||||
|
||||
#include "Luau/TypeFunction.h"
|
||||
#include "Luau/TypeFwd.h"
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
||||
TypeFunctionReductionResult<TypeId> userDefinedTypeFunction(
|
||||
TypeId instance,
|
||||
const std::vector<TypeId>& typeParams,
|
||||
const std::vector<TypePackId>& packParams,
|
||||
NotNull<TypeFunctionContext> ctx
|
||||
);
|
||||
|
||||
}
|
|
@ -26,7 +26,7 @@ LUAU_FASTINT(LuauTypeInferIterationLimit)
|
|||
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
||||
LUAU_FASTFLAGVARIABLE(DebugLuauMagicVariableNames)
|
||||
LUAU_FASTFLAGVARIABLE(LuauAutocompleteMissingFollows)
|
||||
LUAU_FASTFLAG(LuauImplicitTableIndexerKeys2)
|
||||
LUAU_FASTFLAG(LuauImplicitTableIndexerKeys3)
|
||||
|
||||
static const std::unordered_set<std::string> kStatementStartingKeywords =
|
||||
{"while", "if", "local", "repeat", "function", "do", "for", "return", "break", "continue", "type", "export"};
|
||||
|
@ -578,6 +578,29 @@ static void autocompleteStringSingleton(TypeId ty, bool addQuotes, AstNode* node
|
|||
|
||||
ty = follow(ty);
|
||||
|
||||
if (FFlag::LuauImplicitTableIndexerKeys3)
|
||||
{
|
||||
if (auto ss = get<StringSingleton>(get<SingletonType>(ty)))
|
||||
{
|
||||
// This is purposefully `try_emplace` as we don't want to override any existing entries.
|
||||
result.try_emplace(formatKey(ss->value), AutocompleteEntry{AutocompleteEntryKind::String, ty, false, false, TypeCorrectKind::Correct});
|
||||
}
|
||||
else if (auto uty = get<UnionType>(ty))
|
||||
{
|
||||
for (auto el : uty)
|
||||
{
|
||||
if (auto ss = get<StringSingleton>(get<SingletonType>(el)))
|
||||
{
|
||||
// This is purposefully `try_emplace` as we don't want to override any existing entries.
|
||||
result.try_emplace(
|
||||
formatKey(ss->value), AutocompleteEntry{AutocompleteEntryKind::String, ty, false, false, TypeCorrectKind::Correct}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (auto ss = get<StringSingleton>(get<SingletonType>(ty)))
|
||||
{
|
||||
result[formatKey(ss->value)] = AutocompleteEntry{AutocompleteEntryKind::String, ty, false, false, TypeCorrectKind::Correct};
|
||||
|
@ -590,6 +613,7 @@ static void autocompleteStringSingleton(TypeId ty, bool addQuotes, AstNode* node
|
|||
result[formatKey(ss->value)] = AutocompleteEntry{AutocompleteEntryKind::String, ty, false, false, TypeCorrectKind::Correct};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static bool canSuggestInferredType(ScopePtr scope, TypeId ty)
|
||||
|
@ -2030,7 +2054,7 @@ AutocompleteResult autocomplete_(
|
|||
{
|
||||
AutocompleteEntryMap result;
|
||||
|
||||
if (!FFlag::LuauImplicitTableIndexerKeys2)
|
||||
if (!FFlag::LuauImplicitTableIndexerKeys3)
|
||||
{
|
||||
if (auto it = module->astExpectedTypes.find(node->asExpr()))
|
||||
autocompleteStringSingleton(*it, false, node, position, result);
|
||||
|
@ -2053,7 +2077,7 @@ AutocompleteResult autocomplete_(
|
|||
}
|
||||
}
|
||||
|
||||
if (FFlag::LuauImplicitTableIndexerKeys2)
|
||||
if (FFlag::LuauImplicitTableIndexerKeys3)
|
||||
{
|
||||
if (auto it = module->astExpectedTypes.find(node->asExpr()))
|
||||
autocompleteStringSingleton(*it, false, node, position, result);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "Luau/BuiltinDefinitions.h"
|
||||
|
||||
#include "Luau/Ast.h"
|
||||
#include "Luau/BuiltinTypeFunctions.h"
|
||||
#include "Luau/Clone.h"
|
||||
#include "Luau/Common.h"
|
||||
#include "Luau/ConstraintGenerator.h"
|
||||
|
@ -35,7 +36,6 @@ LUAU_FASTFLAG(LuauEagerGeneralization4)
|
|||
LUAU_FASTFLAG(LuauRemoveTypeCallsForReadWriteProps)
|
||||
LUAU_FASTFLAGVARIABLE(LuauTableCloneClonesType3)
|
||||
LUAU_FASTFLAGVARIABLE(LuauStringFormatImprovements)
|
||||
LUAU_FASTFLAGVARIABLE(LuauMagicFreezeCheckBlocked2)
|
||||
LUAU_FASTFLAGVARIABLE(LuauUpdateSetMetatableTypeSignature)
|
||||
LUAU_FASTFLAGVARIABLE(LuauUpdateGetMetatableTypeSignature)
|
||||
LUAU_FASTFLAG(LuauUseWorkspacePropToChooseSolver)
|
||||
|
@ -1781,8 +1781,6 @@ bool MagicFreeze::infer(const MagicFunctionCallContext& context)
|
|||
std::optional<DefId> resultDef = dfg->getDefOptional(targetExpr);
|
||||
std::optional<TypeId> resultTy = resultDef ? scope->lookup(*resultDef) : std::nullopt;
|
||||
|
||||
if (FFlag::LuauMagicFreezeCheckBlocked2)
|
||||
{
|
||||
if (resultTy && !get<BlockedType>(follow(resultTy)))
|
||||
{
|
||||
// If there's an existing result type, but it's _not_ blocked, then
|
||||
|
@ -1790,7 +1788,6 @@ bool MagicFreeze::infer(const MagicFunctionCallContext& context)
|
|||
// regular inference.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<TypeId> frozenType = freezeTable(inputType, context);
|
||||
|
||||
|
|
2828
Analysis/src/BuiltinTypeFunctions.cpp
Normal file
2828
Analysis/src/BuiltinTypeFunctions.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,7 @@
|
|||
#include "Luau/Common.h"
|
||||
#include "Luau/NotNull.h"
|
||||
#include "Luau/Type.h"
|
||||
#include "Luau/TypeOrPack.h"
|
||||
#include "Luau/TypePack.h"
|
||||
#include "Luau/Unifiable.h"
|
||||
#include "Luau/VisitType.h"
|
||||
|
@ -20,14 +21,6 @@ namespace Luau
|
|||
namespace
|
||||
{
|
||||
|
||||
using Kind = Variant<TypeId, TypePackId>;
|
||||
|
||||
template<typename T>
|
||||
const T* get(const Kind& kind)
|
||||
{
|
||||
return get_if<T>(&kind);
|
||||
}
|
||||
|
||||
class TypeCloner
|
||||
{
|
||||
|
||||
|
@ -38,7 +31,7 @@ protected:
|
|||
// A queue of kinds where we cloned it, but whose interior types hasn't
|
||||
// been updated to point to new clones. Once all of its interior types
|
||||
// has been updated, it gets removed from the queue.
|
||||
std::vector<Kind> queue;
|
||||
std::vector<TypeOrPack> queue;
|
||||
|
||||
NotNull<SeenTypes> types;
|
||||
NotNull<SeenTypePacks> packs;
|
||||
|
@ -116,7 +109,7 @@ private:
|
|||
if (hasExceededIterationLimit())
|
||||
break;
|
||||
|
||||
Kind kind = queue.back();
|
||||
TypeOrPack kind = queue.back();
|
||||
queue.pop_back();
|
||||
|
||||
if (find(kind))
|
||||
|
@ -147,7 +140,7 @@ protected:
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<Kind> find(Kind kind) const
|
||||
std::optional<TypeOrPack> find(TypeOrPack kind) const
|
||||
{
|
||||
if (auto ty = get<TypeId>(kind))
|
||||
return find(*ty);
|
||||
|
@ -265,7 +258,7 @@ private:
|
|||
);
|
||||
}
|
||||
|
||||
void cloneChildren(Kind kind)
|
||||
void cloneChildren(TypeOrPack kind)
|
||||
{
|
||||
if (auto ty = get<TypeId>(kind))
|
||||
return cloneChildren(*ty);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "Luau/Ast.h"
|
||||
#include "Luau/BuiltinDefinitions.h"
|
||||
#include "Luau/BuiltinTypeFunctions.h"
|
||||
#include "Luau/Common.h"
|
||||
#include "Luau/Constraint.h"
|
||||
#include "Luau/ControlFlow.h"
|
||||
|
@ -38,8 +39,6 @@ LUAU_FASTFLAG(LuauEagerGeneralization4)
|
|||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
LUAU_FASTFLAG(LuauGlobalVariableModuleIsolation)
|
||||
LUAU_FASTFLAGVARIABLE(LuauEnableWriteOnlyProperties)
|
||||
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
||||
LUAU_FASTFLAG(LuauDoNotAddUpvalueTypesToLocalType)
|
||||
LUAU_FASTFLAGVARIABLE(LuauAvoidDoubleNegation)
|
||||
LUAU_FASTFLAGVARIABLE(LuauSimplifyOutOfLine2)
|
||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck2)
|
||||
|
@ -1330,8 +1329,6 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatForIn* forI
|
|||
loopScope, getLocation(forIn->values), IterableConstraint{iterator, variableTypes, forIn->values.data[0], &module->astForInNextTypes}
|
||||
);
|
||||
|
||||
if (FFlag::LuauAddCallConstraintForIterableFunctions)
|
||||
{
|
||||
// Add an intersection ReduceConstraint for the key variable to denote that it can't be nil
|
||||
AstLocal* keyVar = *forIn->vars.begin();
|
||||
const DefId keyDef = dfg->getDef(keyVar);
|
||||
|
@ -1345,7 +1342,6 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatForIn* forI
|
|||
|
||||
auto c = addConstraint(loopScope, keyVar->location, ReduceConstraint{intersectionTy});
|
||||
c->dependencies.push_back(iterable);
|
||||
}
|
||||
|
||||
for (TypeId var : variableTypes)
|
||||
{
|
||||
|
@ -3302,7 +3298,7 @@ void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprLocal* local
|
|||
if (ty)
|
||||
{
|
||||
TypeIds* localDomain = localTypes.find(*ty);
|
||||
if (localDomain && !(FFlag::LuauDoNotAddUpvalueTypesToLocalType && local->upvalue))
|
||||
if (localDomain && !local->upvalue)
|
||||
localDomain->insert(rhsType);
|
||||
}
|
||||
else
|
||||
|
@ -3333,10 +3329,6 @@ void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprLocal* local
|
|||
if (annotatedTy)
|
||||
addConstraint(scope, local->location, SubtypeConstraint{rhsType, *annotatedTy});
|
||||
|
||||
// This is vestigial.
|
||||
if (!FFlag::LuauDoNotAddUpvalueTypesToLocalType)
|
||||
if (TypeIds* localDomain = localTypes.find(*ty))
|
||||
localDomain->insert(rhsType);
|
||||
}
|
||||
|
||||
void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprGlobal* global, TypeId rhsType)
|
||||
|
|
|
@ -34,7 +34,6 @@ LUAU_FASTINTVARIABLE(LuauSolverRecursionLimit, 500)
|
|||
LUAU_FASTFLAGVARIABLE(DebugLuauEqSatSimplification)
|
||||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
LUAU_FASTFLAG(LuauStuckTypeFunctionsStillDispatch)
|
||||
LUAU_FASTFLAGVARIABLE(LuauAddCallConstraintForIterableFunctions)
|
||||
LUAU_FASTFLAGVARIABLE(LuauGuardAgainstMalformedTypeAliasExpansion2)
|
||||
LUAU_FASTFLAGVARIABLE(LuauInsertErrorTypesIntoIndexerResult)
|
||||
LUAU_FASTFLAGVARIABLE(LuauAvoidGenericsLeakingDuringFunctionCallCheck)
|
||||
|
@ -633,8 +632,9 @@ void ConstraintSolver::finalizeTypeFunctions()
|
|||
TypeId ty = follow(t);
|
||||
if (get<TypeFunctionInstanceType>(ty))
|
||||
{
|
||||
TypeFunctionContext context{NotNull{this}, constraint->scope, NotNull{constraint}};
|
||||
FunctionGraphReductionResult result =
|
||||
reduceTypeFunctions(t, constraint->location, TypeFunctionContext{NotNull{this}, constraint->scope, NotNull{constraint}}, true);
|
||||
reduceTypeFunctions(t, constraint->location, NotNull{&context}, true);
|
||||
|
||||
for (TypeId r : result.reducedTypes)
|
||||
unblock(r, constraint->location);
|
||||
|
@ -2772,8 +2772,9 @@ bool ConstraintSolver::tryDispatch(const UnpackConstraint& c, NotNull<const Cons
|
|||
bool ConstraintSolver::tryDispatch(const ReduceConstraint& c, NotNull<const Constraint> constraint, bool force)
|
||||
{
|
||||
TypeId ty = follow(c.ty);
|
||||
FunctionGraphReductionResult result =
|
||||
reduceTypeFunctions(ty, constraint->location, TypeFunctionContext{NotNull{this}, constraint->scope, constraint}, force);
|
||||
|
||||
TypeFunctionContext context{NotNull{this}, constraint->scope, constraint};
|
||||
FunctionGraphReductionResult result = reduceTypeFunctions(ty, constraint->location, NotNull{&context}, force);
|
||||
|
||||
for (TypeId r : result.reducedTypes)
|
||||
unblock(r, constraint->location);
|
||||
|
@ -2824,8 +2825,9 @@ bool ConstraintSolver::tryDispatch(const ReduceConstraint& c, NotNull<const Cons
|
|||
bool ConstraintSolver::tryDispatch(const ReducePackConstraint& c, NotNull<const Constraint> constraint, bool force)
|
||||
{
|
||||
TypePackId tp = follow(c.tp);
|
||||
FunctionGraphReductionResult result =
|
||||
reduceTypeFunctions(tp, constraint->location, TypeFunctionContext{NotNull{this}, constraint->scope, constraint}, force);
|
||||
|
||||
TypeFunctionContext context{NotNull{this}, constraint->scope, constraint};
|
||||
FunctionGraphReductionResult result = reduceTypeFunctions(tp, constraint->location, NotNull{&context}, force);
|
||||
|
||||
for (TypeId r : result.reducedTypes)
|
||||
unblock(r, constraint->location);
|
||||
|
@ -3204,8 +3206,6 @@ bool ConstraintSolver::tryDispatchIterableFunction(TypeId nextTy, TypeId tableTy
|
|||
// the type of the `nextAstFragment` is the `nextTy`.
|
||||
(*c.astForInNextTypes)[c.nextAstFragment] = nextTy;
|
||||
|
||||
if (FFlag::LuauAddCallConstraintForIterableFunctions)
|
||||
{
|
||||
// Construct a FunctionCallConstraint, to help us learn about the type of the loop variables being assigned to in this iterable
|
||||
TypePackId tableTyPack = arena->addTypePack({tableTy});
|
||||
|
||||
|
@ -3220,34 +3220,6 @@ bool ConstraintSolver::tryDispatchIterableFunction(TypeId nextTy, TypeId tableTy
|
|||
inheritBlocks(constraint, callConstraint);
|
||||
|
||||
inheritBlocks(unpackConstraint, callConstraint);
|
||||
}
|
||||
else
|
||||
{
|
||||
const TypePackId nextRetPack = nextFn->retTypes;
|
||||
TypePackIterator it = begin(nextRetPack);
|
||||
std::vector<TypeId> modifiedNextRetHead;
|
||||
|
||||
// The first value is never nil in the context of the loop, even if it's nil
|
||||
// in the next function's return type, because the loop will not advance if
|
||||
// it's nil.
|
||||
if (it != end(nextRetPack))
|
||||
{
|
||||
TypeId firstRet = *it;
|
||||
TypeId modifiedFirstRet = stripNil(builtinTypes, *arena, firstRet);
|
||||
modifiedNextRetHead.push_back(modifiedFirstRet);
|
||||
++it;
|
||||
}
|
||||
|
||||
for (; it != end(nextRetPack); ++it)
|
||||
modifiedNextRetHead.push_back(*it);
|
||||
|
||||
TypePackId modifiedNextRetPack = arena->addTypePack(std::move(modifiedNextRetHead), it.tail());
|
||||
|
||||
auto unpackConstraint = unpackAndAssign(c.variables, modifiedNextRetPack, constraint);
|
||||
|
||||
inheritBlocks(constraint, unpackConstraint);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
LUAU_FASTFLAG(DebugLuauFreezeArena)
|
||||
LUAU_FASTFLAG(LuauSolverV2)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDfgScopeStackNotNull)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDoNotAddUpvalueTypesToLocalType)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDfgIfBlocksShouldRespectControlFlow)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDfgAllowUpdatesInLoops)
|
||||
LUAU_FASTFLAG(LuauFragmentAutocompleteTracksRValueRefinements)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDfgForwardNilFromAndOr)
|
||||
|
@ -510,8 +508,6 @@ ControlFlow DataFlowGraphBuilder::visit(AstStatIf* i)
|
|||
}
|
||||
|
||||
DfgScope* scope = FFlag::LuauDfgScopeStackNotNull ? currentScope() : currentScope_DEPRECATED();
|
||||
if (FFlag::LuauDfgIfBlocksShouldRespectControlFlow)
|
||||
{
|
||||
// If the control flow from the `if` or `else` block is non-linear,
|
||||
// then we should assume that the _other_ branch is the one taken.
|
||||
if (thencf != ControlFlow::None && elsecf == ControlFlow::None)
|
||||
|
@ -520,16 +516,6 @@ ControlFlow DataFlowGraphBuilder::visit(AstStatIf* i)
|
|||
scope->inherit(thenScope);
|
||||
else if ((thencf | elsecf) == ControlFlow::None)
|
||||
join(scope, thenScope, elseScope);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thencf != ControlFlow::None && elsecf == ControlFlow::None)
|
||||
join(scope, scope, elseScope);
|
||||
else if (thencf == ControlFlow::None && elsecf != ControlFlow::None)
|
||||
join(scope, thenScope, scope);
|
||||
else if ((thencf | elsecf) == ControlFlow::None)
|
||||
join(scope, thenScope, elseScope);
|
||||
}
|
||||
|
||||
if (thencf == elsecf)
|
||||
return thencf;
|
||||
|
@ -1311,7 +1297,7 @@ DefId DataFlowGraphBuilder::visitLValue(AstExprLocal* l, DefId incomingDef)
|
|||
DfgScope* scope = FFlag::LuauDfgScopeStackNotNull ? currentScope() : currentScope_DEPRECATED();
|
||||
|
||||
// In order to avoid alias tracking, we need to clip the reference to the parent def.
|
||||
if (scope->canUpdateDefinition(l->local) && !(FFlag::LuauDoNotAddUpvalueTypesToLocalType && l->upvalue))
|
||||
if (scope->canUpdateDefinition(l->local) && !l->upvalue)
|
||||
{
|
||||
DefId updated = defArena->freshCell(l->local, l->location, containsSubscriptedDefinition(incomingDef));
|
||||
scope->bindings[l->local] = updated;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "Luau/TypeUtils.h"
|
||||
#include "Luau/VisitType.h"
|
||||
|
||||
LUAU_FASTFLAGVARIABLE(LuauImplicitTableIndexerKeys2)
|
||||
LUAU_FASTFLAGVARIABLE(LuauImplicitTableIndexerKeys3)
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
@ -147,7 +147,7 @@ struct IndexCollector : public TypeOnceVisitor
|
|||
|
||||
bool ExpectedTypeVisitor::visit(AstExprIndexExpr* expr)
|
||||
{
|
||||
if (!FFlag::LuauImplicitTableIndexerKeys2)
|
||||
if (!FFlag::LuauImplicitTableIndexerKeys3)
|
||||
return true;
|
||||
|
||||
if (auto ty = astTypes->find(expr->expr))
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
LUAU_FASTFLAG(DebugLuauMagicTypes)
|
||||
|
||||
LUAU_FASTFLAGVARIABLE(LuauNewNonStrictVisitTypes2)
|
||||
LUAU_FASTFLAGVARIABLE(LuauNewNonStrictFixGenericTypePacks)
|
||||
LUAU_FASTFLAGVARIABLE(LuauNewNonStrictMoreUnknownSymbols)
|
||||
LUAU_FASTFLAGVARIABLE(LuauNewNonStrictNoErrorsPassingNever)
|
||||
|
@ -240,14 +239,8 @@ struct NonStrictTypeChecker
|
|||
if (noTypeFunctionErrors.find(instance))
|
||||
return instance;
|
||||
|
||||
ErrorVec errors =
|
||||
reduceTypeFunctions(
|
||||
instance,
|
||||
location,
|
||||
TypeFunctionContext{arena, builtinTypes, stack.back(), simplifier, NotNull{&normalizer}, typeFunctionRuntime, ice, limits},
|
||||
true
|
||||
)
|
||||
.errors;
|
||||
TypeFunctionContext context{arena, builtinTypes, stack.back(), simplifier, NotNull{&normalizer}, typeFunctionRuntime, ice, limits};
|
||||
ErrorVec errors = reduceTypeFunctions(instance, location, NotNull{&context}, true).errors;
|
||||
|
||||
if (errors.empty())
|
||||
noTypeFunctionErrors.insert(instance);
|
||||
|
@ -340,7 +333,6 @@ struct NonStrictTypeChecker
|
|||
{
|
||||
ctx.remove(dfg->getDef(local));
|
||||
|
||||
if (FFlag::LuauNewNonStrictVisitTypes2)
|
||||
visit(local->annotation);
|
||||
}
|
||||
}
|
||||
|
@ -426,7 +418,6 @@ struct NonStrictTypeChecker
|
|||
|
||||
NonStrictContext visit(AstStatFor* forStatement)
|
||||
{
|
||||
if (FFlag::LuauNewNonStrictVisitTypes2)
|
||||
visit(forStatement->var->annotation);
|
||||
|
||||
// TODO: throwing out context based on same principle as existing code?
|
||||
|
@ -440,12 +431,9 @@ struct NonStrictTypeChecker
|
|||
}
|
||||
|
||||
NonStrictContext visit(AstStatForIn* forInStatement)
|
||||
{
|
||||
if (FFlag::LuauNewNonStrictVisitTypes2)
|
||||
{
|
||||
for (auto var : forInStatement->vars)
|
||||
visit(var->annotation);
|
||||
}
|
||||
|
||||
for (AstExpr* rhs : forInStatement->values)
|
||||
visit(rhs, ValueContext::RValue);
|
||||
|
@ -481,12 +469,9 @@ struct NonStrictTypeChecker
|
|||
}
|
||||
|
||||
NonStrictContext visit(AstStatTypeAlias* typeAlias)
|
||||
{
|
||||
if (FFlag::LuauNewNonStrictVisitTypes2)
|
||||
{
|
||||
visitGenerics(typeAlias->generics, typeAlias->genericPacks);
|
||||
visit(typeAlias->type);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -497,28 +482,22 @@ struct NonStrictTypeChecker
|
|||
}
|
||||
|
||||
NonStrictContext visit(AstStatDeclareFunction* declFn)
|
||||
{
|
||||
if (FFlag::LuauNewNonStrictVisitTypes2)
|
||||
{
|
||||
visitGenerics(declFn->generics, declFn->genericPacks);
|
||||
visit(declFn->params);
|
||||
visit(declFn->retTypes);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
NonStrictContext visit(AstStatDeclareGlobal* declGlobal)
|
||||
{
|
||||
if (FFlag::LuauNewNonStrictVisitTypes2)
|
||||
visit(declGlobal->type);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
NonStrictContext visit(AstStatDeclareExternType* declClass)
|
||||
{
|
||||
if (FFlag::LuauNewNonStrictVisitTypes2)
|
||||
{
|
||||
if (declClass->indexer)
|
||||
{
|
||||
|
@ -528,7 +507,6 @@ struct NonStrictTypeChecker
|
|||
|
||||
for (auto prop : declClass->props)
|
||||
visit(prop.ty);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -793,19 +771,15 @@ struct NonStrictTypeChecker
|
|||
}
|
||||
remainder.remove(dfg->getDef(local));
|
||||
|
||||
if (FFlag::LuauNewNonStrictVisitTypes2)
|
||||
visit(local->annotation);
|
||||
}
|
||||
|
||||
if (FFlag::LuauNewNonStrictVisitTypes2)
|
||||
{
|
||||
visitGenerics(exprFn->generics, exprFn->genericPacks);
|
||||
|
||||
visit(exprFn->returnAnnotation);
|
||||
|
||||
if (exprFn->varargAnnotation)
|
||||
visit(exprFn->varargAnnotation);
|
||||
}
|
||||
|
||||
return remainder;
|
||||
}
|
||||
|
@ -836,7 +810,6 @@ struct NonStrictTypeChecker
|
|||
|
||||
NonStrictContext visit(AstExprTypeAssertion* typeAssertion)
|
||||
{
|
||||
if (FFlag::LuauNewNonStrictVisitTypes2)
|
||||
visit(typeAssertion->annotation);
|
||||
|
||||
return visit(typeAssertion->expr, ValueContext::RValue);
|
||||
|
@ -868,8 +841,6 @@ struct NonStrictTypeChecker
|
|||
|
||||
void visit(AstType* ty)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauNewNonStrictVisitTypes2);
|
||||
|
||||
// If this node is `nullptr`, early exit.
|
||||
if (!ty)
|
||||
return;
|
||||
|
@ -1081,8 +1052,6 @@ struct NonStrictTypeChecker
|
|||
|
||||
void visit(AstTypePack* pack)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauNewNonStrictVisitTypes2);
|
||||
|
||||
// If there is no pack node, early exit.
|
||||
if (!pack)
|
||||
return;
|
||||
|
|
|
@ -246,8 +246,9 @@ std::pair<OverloadResolver::Analysis, ErrorVec> OverloadResolver::checkOverload_
|
|||
const std::vector<AstExpr*>* argExprs
|
||||
)
|
||||
{
|
||||
TypeFunctionContext context{arena, builtinTypes, scope, simplifier, normalizer, typeFunctionRuntime, ice, limits};
|
||||
FunctionGraphReductionResult result = reduceTypeFunctions(
|
||||
fnTy, callLoc, TypeFunctionContext{arena, builtinTypes, scope, simplifier, normalizer, typeFunctionRuntime, ice, limits}, /*force=*/true
|
||||
fnTy, callLoc, NotNull{&context}, /*force=*/true
|
||||
);
|
||||
if (!result.errors.empty())
|
||||
return {OverloadIsNonviable, result.errors};
|
||||
|
|
|
@ -2151,7 +2151,7 @@ std::pair<TypeId, ErrorVec> Subtyping::handleTypeFunctionReductionResult(const T
|
|||
{
|
||||
TypeFunctionContext context{arena, builtinTypes, scope, simplifier, normalizer, typeFunctionRuntime, iceReporter, NotNull{&limits}};
|
||||
TypeId function = arena->addType(*functionInstance);
|
||||
FunctionGraphReductionResult result = reduceTypeFunctions(function, {}, context, true);
|
||||
FunctionGraphReductionResult result = reduceTypeFunctions(function, {}, NotNull{&context}, true);
|
||||
ErrorVec errors;
|
||||
if (result.blockedTypes.size() != 0 || result.blockedPacks.size() != 0)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "Luau/TypeOrPack.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
LUAU_FASTFLAGVARIABLE(LuauEnableDenseTableAlias)
|
||||
|
|
|
@ -30,10 +30,8 @@
|
|||
|
||||
LUAU_FASTFLAG(DebugLuauMagicTypes)
|
||||
|
||||
LUAU_FASTFLAGVARIABLE(LuauTypeCheckerStricterIndexCheck)
|
||||
LUAU_FASTFLAG(LuauEnableWriteOnlyProperties)
|
||||
LUAU_FASTFLAG(LuauNewNonStrictFixGenericTypePacks)
|
||||
LUAU_FASTFLAGVARIABLE(LuauReportSubtypingErrors)
|
||||
LUAU_FASTFLAGVARIABLE(LuauSkipMalformedTypeAliases)
|
||||
LUAU_FASTFLAGVARIABLE(LuauTableLiteralSubtypeSpecificCheck2)
|
||||
LUAU_FASTFLAG(LuauStuckTypeFunctionsStillDispatch)
|
||||
|
@ -499,16 +497,11 @@ TypeId TypeChecker2::checkForTypeFunctionInhabitance(TypeId instance, Location l
|
|||
return instance;
|
||||
seenTypeFunctionInstances.insert(instance);
|
||||
|
||||
ErrorVec errors =
|
||||
reduceTypeFunctions(
|
||||
instance,
|
||||
location,
|
||||
TypeFunctionContext{
|
||||
TypeFunctionContext context{
|
||||
NotNull{&module->internalTypes}, builtinTypes, stack.back(), simplifier, NotNull{&normalizer}, typeFunctionRuntime, ice, limits
|
||||
},
|
||||
true
|
||||
)
|
||||
.errors;
|
||||
};
|
||||
|
||||
ErrorVec errors = reduceTypeFunctions(instance, location, NotNull{&context}, true).errors;
|
||||
if (!isErrorSuppressing(location, instance))
|
||||
reportErrors(std::move(errors));
|
||||
return instance;
|
||||
|
@ -1417,8 +1410,6 @@ void TypeChecker2::visit(AstExprConstantBool* expr)
|
|||
NotNull<Scope> scope{findInnermostScope(expr->location)};
|
||||
|
||||
SubtypingResult r = subtyping->isSubtype(bestType, inferredType, scope);
|
||||
if (FFlag::LuauReportSubtypingErrors)
|
||||
{
|
||||
if (!isErrorSuppressing(expr->location, inferredType))
|
||||
{
|
||||
if (!r.isSubtype)
|
||||
|
@ -1431,12 +1422,6 @@ void TypeChecker2::visit(AstExprConstantBool* expr)
|
|||
reportErrors(r.errors);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!r.isSubtype && !isErrorSuppressing(expr->location, inferredType))
|
||||
reportError(TypeMismatch{inferredType, bestType}, expr->location);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeChecker2::visit(AstExprConstantNumber* expr)
|
||||
{
|
||||
|
@ -1459,8 +1444,6 @@ void TypeChecker2::visit(AstExprConstantString* expr)
|
|||
NotNull<Scope> scope{findInnermostScope(expr->location)};
|
||||
|
||||
SubtypingResult r = subtyping->isSubtype(bestType, inferredType, scope);
|
||||
if (FFlag::LuauReportSubtypingErrors)
|
||||
{
|
||||
if (!isErrorSuppressing(expr->location, inferredType))
|
||||
{
|
||||
if (!r.isSubtype)
|
||||
|
@ -1473,12 +1456,6 @@ void TypeChecker2::visit(AstExprConstantString* expr)
|
|||
reportErrors(r.errors);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!r.isSubtype && !isErrorSuppressing(expr->location, inferredType))
|
||||
reportError(TypeMismatch{inferredType, bestType}, expr->location);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeChecker2::visit(AstExprLocal* expr)
|
||||
{
|
||||
|
@ -1545,8 +1522,6 @@ void TypeChecker2::visitCall(AstExprCall* call)
|
|||
if (result.isSubtype)
|
||||
fnTy = follow(*selectedOverloadTy);
|
||||
|
||||
if (FFlag::LuauReportSubtypingErrors)
|
||||
{
|
||||
if (!isErrorSuppressing(call->location, *selectedOverloadTy))
|
||||
if (FFlag::LuauSubtypingCheckFunctionGenericCounts)
|
||||
{
|
||||
|
@ -1554,8 +1529,6 @@ void TypeChecker2::visitCall(AstExprCall* call)
|
|||
e.location = call->location;
|
||||
}
|
||||
reportErrors(std::move(result.errors));
|
||||
}
|
||||
|
||||
if (result.normalizationTooComplex)
|
||||
{
|
||||
reportError(NormalizationTooComplex{}, call->func->location);
|
||||
|
@ -3220,8 +3193,6 @@ bool TypeChecker2::testIsSubtype(TypeId subTy, TypeId superTy, Location location
|
|||
NotNull<Scope> scope{findInnermostScope(location)};
|
||||
SubtypingResult r = subtyping->isSubtype(subTy, superTy, scope);
|
||||
|
||||
if (FFlag::LuauReportSubtypingErrors)
|
||||
{
|
||||
if (!isErrorSuppressing(location, subTy))
|
||||
if (FFlag::LuauSubtypingCheckFunctionGenericCounts)
|
||||
{
|
||||
|
@ -3229,8 +3200,6 @@ bool TypeChecker2::testIsSubtype(TypeId subTy, TypeId superTy, Location location
|
|||
e.location = location;
|
||||
}
|
||||
reportErrors(std::move(r.errors));
|
||||
}
|
||||
|
||||
if (r.normalizationTooComplex)
|
||||
reportError(NormalizationTooComplex{}, location);
|
||||
|
||||
|
@ -3245,8 +3214,6 @@ bool TypeChecker2::testIsSubtype(TypePackId subTy, TypePackId superTy, Location
|
|||
NotNull<Scope> scope{findInnermostScope(location)};
|
||||
SubtypingResult r = subtyping->isSubtype(subTy, superTy, scope);
|
||||
|
||||
if (FFlag::LuauReportSubtypingErrors)
|
||||
{
|
||||
if (!isErrorSuppressing(location, subTy))
|
||||
if (FFlag::LuauSubtypingCheckFunctionGenericCounts)
|
||||
{
|
||||
|
@ -3254,8 +3221,6 @@ bool TypeChecker2::testIsSubtype(TypePackId subTy, TypePackId superTy, Location
|
|||
e.location = location;
|
||||
}
|
||||
reportErrors(std::move(r.errors));
|
||||
}
|
||||
|
||||
if (r.normalizationTooComplex)
|
||||
reportError(NormalizationTooComplex{}, location);
|
||||
|
||||
|
@ -3501,18 +3466,8 @@ PropertyType TypeChecker2::hasIndexTypeFromType(
|
|||
return {NormalizationResult::True, {tt->indexer->indexResultType}};
|
||||
}
|
||||
|
||||
if (FFlag::LuauTypeCheckerStricterIndexCheck)
|
||||
{
|
||||
return {NormalizationResult::False, {builtinTypes->unknownType}};
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we are in a conditional context, we treat the property as present and `unknown` because
|
||||
// we may be _refining_ `tableTy` to include that property. we will want to revisit this a bit
|
||||
// in the future once luau has support for exact tables since this only applies when inexact.
|
||||
return {inConditional(typeContext) ? NormalizationResult::True : NormalizationResult::False, {builtinTypes->unknownType}};
|
||||
}
|
||||
}
|
||||
else if (const ExternType* cls = get<ExternType>(ty))
|
||||
{
|
||||
// If the property doesn't exist on the class, we consult the indexer
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,9 +2,16 @@
|
|||
|
||||
#include "Luau/TypeFunctionRuntime.h"
|
||||
|
||||
#include "Luau/Allocator.h"
|
||||
#include "Luau/Lexer.h"
|
||||
#include "Luau/BuiltinTypeFunctions.h"
|
||||
#include "Luau/BytecodeBuilder.h"
|
||||
#include "Luau/ParseResult.h"
|
||||
#include "Luau/Compiler.h"
|
||||
#include "Luau/DenseHash.h"
|
||||
#include "Luau/StringUtils.h"
|
||||
#include "Luau/TypeFunction.h"
|
||||
#include "Luau/TypeFunctionRuntimeBuilder.h"
|
||||
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
|
@ -19,6 +26,133 @@ LUAU_FASTFLAGVARIABLE(LuauTypeFunOptional)
|
|||
namespace Luau
|
||||
{
|
||||
|
||||
LuauTempThreadPopper::LuauTempThreadPopper(lua_State* L)
|
||||
: L(L)
|
||||
{
|
||||
}
|
||||
|
||||
LuauTempThreadPopper::~LuauTempThreadPopper()
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
static void dummyStateClose(lua_State*) {}
|
||||
|
||||
TypeFunctionRuntime::TypeFunctionRuntime(NotNull<InternalErrorReporter> ice, NotNull<TypeCheckLimits> limits)
|
||||
: ice(ice)
|
||||
, limits(limits)
|
||||
, state(nullptr, dummyStateClose)
|
||||
{
|
||||
}
|
||||
|
||||
TypeFunctionRuntime::~TypeFunctionRuntime() {}
|
||||
|
||||
std::optional<std::string> TypeFunctionRuntime::registerFunction(AstStatTypeFunction* function)
|
||||
{
|
||||
// If evaluation is disabled, we do not generate additional error messages
|
||||
if (!allowEvaluation)
|
||||
return std::nullopt;
|
||||
|
||||
// Do not evaluate type functions with parse errors inside
|
||||
if (function->hasErrors)
|
||||
return std::nullopt;
|
||||
|
||||
prepareState();
|
||||
|
||||
lua_State* global = state.get();
|
||||
|
||||
// Fetch to check if function is already registered
|
||||
lua_pushlightuserdata(global, function);
|
||||
lua_gettable(global, LUA_REGISTRYINDEX);
|
||||
|
||||
if (!lua_isnil(global, -1))
|
||||
{
|
||||
lua_pop(global, 1);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
lua_pop(global, 1);
|
||||
|
||||
AstName name = function->name;
|
||||
|
||||
// Construct ParseResult containing the type function
|
||||
Allocator allocator;
|
||||
AstNameTable names(allocator);
|
||||
|
||||
AstExpr* exprFunction = function->body;
|
||||
AstArray<AstExpr*> exprReturns{&exprFunction, 1};
|
||||
AstStatReturn stmtReturn{Location{}, exprReturns};
|
||||
AstStat* stmtArray[] = {&stmtReturn};
|
||||
AstArray<AstStat*> stmts{stmtArray, 1};
|
||||
AstStatBlock exec{Location{}, stmts};
|
||||
ParseResult parseResult{&exec, 1, {}, {}, {}, CstNodeMap{nullptr}};
|
||||
|
||||
BytecodeBuilder builder;
|
||||
try
|
||||
{
|
||||
compileOrThrow(builder, parseResult, names);
|
||||
}
|
||||
catch (CompileError& e)
|
||||
{
|
||||
return format("'%s' type function failed to compile with error message: %s", name.value, e.what());
|
||||
}
|
||||
|
||||
std::string bytecode = builder.getBytecode();
|
||||
|
||||
// Separate sandboxed thread for individual execution and private globals
|
||||
lua_State* L = lua_newthread(global);
|
||||
LuauTempThreadPopper popper(global);
|
||||
|
||||
// Create individual environment for the type function
|
||||
luaL_sandboxthread(L);
|
||||
|
||||
// Do not allow global writes to that environment
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
lua_setreadonly(L, -1, true);
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Load bytecode into Luau state
|
||||
if (auto error = checkResultForError(L, name.value, luau_load(L, name.value, bytecode.data(), bytecode.size(), 0)))
|
||||
return error;
|
||||
|
||||
// Execute the global function which should return our user-defined type function
|
||||
if (auto error = checkResultForError(L, name.value, lua_resume(L, nullptr, 0)))
|
||||
return error;
|
||||
|
||||
if (!lua_isfunction(L, -1))
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
return format("Could not find '%s' type function in the global scope", name.value);
|
||||
}
|
||||
|
||||
// Store resulting function in the registry
|
||||
lua_pushlightuserdata(global, function);
|
||||
lua_xmove(L, global, 1);
|
||||
lua_settable(global, LUA_REGISTRYINDEX);
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void TypeFunctionRuntime::prepareState()
|
||||
{
|
||||
if (state)
|
||||
return;
|
||||
|
||||
state = StateRef(lua_newstate(typeFunctionAlloc, nullptr), lua_close);
|
||||
lua_State* L = state.get();
|
||||
|
||||
lua_setthreaddata(L, this);
|
||||
|
||||
setTypeFunctionEnvironment(L);
|
||||
|
||||
registerTypeUserData(L);
|
||||
|
||||
registerTypesLibrary(L);
|
||||
|
||||
luaL_sandbox(L);
|
||||
luaL_sandboxthread(L);
|
||||
}
|
||||
|
||||
constexpr int kTypeUserdataTag = 42;
|
||||
|
||||
void* typeFunctionAlloc(void* ud, void* ptr, size_t osize, size_t nsize)
|
||||
|
@ -2108,13 +2242,6 @@ bool TypeFunctionProperty::isWriteOnly() const
|
|||
* Below is a helper class for type.copy()
|
||||
* Forked version of Clone.cpp
|
||||
*/
|
||||
using TypeFunctionKind = Variant<TypeFunctionTypeId, TypeFunctionTypePackId>;
|
||||
|
||||
template<typename T>
|
||||
const T* get(const TypeFunctionKind& kind)
|
||||
{
|
||||
return get_if<T>(&kind);
|
||||
}
|
||||
|
||||
class TypeFunctionCloner
|
||||
{
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "Luau/TypeFunctionRuntimeBuilder.h"
|
||||
|
||||
#include "Luau/Ast.h"
|
||||
#include "Luau/BuiltinDefinitions.h"
|
||||
#include "Luau/Common.h"
|
||||
#include "Luau/DenseHash.h"
|
||||
|
@ -12,6 +11,7 @@
|
|||
#include "Luau/TypeFwd.h"
|
||||
#include "Luau/TypeFunctionRuntime.h"
|
||||
#include "Luau/TypePack.h"
|
||||
#include "Luau/TypeOrPack.h"
|
||||
#include "Luau/ToString.h"
|
||||
|
||||
#include <optional>
|
||||
|
@ -41,7 +41,7 @@ class TypeFunctionSerializer
|
|||
// queue.back() should always return two of same type in their respective sides
|
||||
// For example `auto [first, second] = queue.back()`: if first is PrimitiveType,
|
||||
// second must be TypeFunctionPrimitiveType; else there should be an error
|
||||
std::vector<std::tuple<Kind, TypeFunctionKind>> queue;
|
||||
std::vector<std::tuple<TypeOrPack, TypeFunctionKind>> queue;
|
||||
|
||||
SeenTypes types; // Mapping of TypeIds that have been shallow serialized to TypeFunctionTypeIds
|
||||
SeenTypePacks packs; // Mapping of TypePackIds that have been shallow serialized to TypeFunctionTypePackIds
|
||||
|
@ -121,7 +121,7 @@ private:
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<TypeFunctionKind> find(Kind kind) const
|
||||
std::optional<TypeFunctionKind> find(TypeOrPack kind) const
|
||||
{
|
||||
if (auto ty = get<TypeId>(kind))
|
||||
return find(*ty);
|
||||
|
@ -316,7 +316,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void serializeChildren(Kind kind, TypeFunctionKind tfkind)
|
||||
void serializeChildren(TypeOrPack kind, TypeFunctionKind tfkind)
|
||||
{
|
||||
if (auto [ty, tfty] = std::tuple{get<TypeId>(kind), get<TypeFunctionTypeId>(tfkind)}; ty && tfty)
|
||||
serializeChildren(*ty, *tfty);
|
||||
|
@ -496,7 +496,7 @@ class TypeFunctionDeserializer
|
|||
// queue.back() should always return two of same type in their respective sides
|
||||
// For example `auto [first, second] = queue.back()`: if first is TypeFunctionPrimitiveType,
|
||||
// second must be PrimitiveType; else there should be an error
|
||||
std::vector<std::tuple<TypeFunctionKind, Kind>> queue;
|
||||
std::vector<std::tuple<TypeFunctionKind, TypeOrPack>> queue;
|
||||
|
||||
// Generic types and packs currently in scope
|
||||
// Generics are resolved by name even if runtime generic type pointers are different
|
||||
|
@ -600,7 +600,7 @@ private:
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<Kind> find(TypeFunctionKind kind) const
|
||||
std::optional<TypeOrPack> find(TypeFunctionKind kind) const
|
||||
{
|
||||
if (auto ty = get<TypeFunctionTypeId>(kind))
|
||||
return find(*ty);
|
||||
|
@ -824,7 +824,7 @@ private:
|
|||
state->ctx->ice->ice("Deserializing user defined type function arguments: mysterious type is being deserialized");
|
||||
}
|
||||
|
||||
void deserializeChildren(TypeFunctionKind tfkind, Kind kind)
|
||||
void deserializeChildren(TypeFunctionKind tfkind, TypeOrPack kind)
|
||||
{
|
||||
if (auto [ty, tfty] = std::tuple{get<TypeId>(kind), get<TypeFunctionTypeId>(tfkind)}; ty && tfty)
|
||||
deserializeChildren(*tfty, *ty);
|
||||
|
|
|
@ -737,8 +737,6 @@ std::string toString(const TypePath::Path& path, bool prefixDot)
|
|||
|
||||
std::string toStringHuman(const TypePath::Path& path)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauSolverV2);
|
||||
|
||||
enum class State
|
||||
{
|
||||
Initial,
|
||||
|
|
391
Analysis/src/UserDefinedTypeFunction.cpp
Normal file
391
Analysis/src/UserDefinedTypeFunction.cpp
Normal file
|
@ -0,0 +1,391 @@
|
|||
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||
|
||||
#include "Luau/ApplyTypeFunction.h"
|
||||
#include "Luau/BuiltinTypeFunctions.h"
|
||||
#include "Luau/ConstraintSolver.h"
|
||||
#include "Luau/Normalize.h"
|
||||
#include "Luau/StringUtils.h"
|
||||
#include "Luau/TimeTrace.h"
|
||||
#include "Luau/UserDefinedTypeFunction.h"
|
||||
#include "Luau/VisitType.h"
|
||||
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
|
||||
LUAU_FASTFLAG(LuauUserTypeFunctionAliases)
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class ScopedAssign
|
||||
{
|
||||
public:
|
||||
ScopedAssign(T& target, const T& value)
|
||||
: target(&target)
|
||||
, oldValue(target)
|
||||
{
|
||||
target = value;
|
||||
}
|
||||
|
||||
~ScopedAssign()
|
||||
{
|
||||
*target = oldValue;
|
||||
}
|
||||
|
||||
private:
|
||||
T* target = nullptr;
|
||||
T oldValue;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
struct FindUserTypeFunctionBlockers : TypeOnceVisitor
|
||||
{
|
||||
NotNull<TypeFunctionContext> ctx;
|
||||
DenseHashSet<TypeId> blockingTypeMap{nullptr};
|
||||
std::vector<TypeId> blockingTypes;
|
||||
|
||||
explicit FindUserTypeFunctionBlockers(NotNull<TypeFunctionContext> ctx)
|
||||
: TypeOnceVisitor(/* skipBoundTypes */ true)
|
||||
, ctx(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
bool visit(TypeId ty) override
|
||||
{
|
||||
if (isPending(ty, ctx->solver))
|
||||
{
|
||||
if (!blockingTypeMap.contains(ty))
|
||||
{
|
||||
blockingTypeMap.insert(ty);
|
||||
blockingTypes.push_back(ty);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit(TypePackId tp) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit(TypeId ty, const ExternType&) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static int evaluateTypeAliasCall(lua_State* L)
|
||||
{
|
||||
TypeFun* tf = static_cast<TypeFun*>(lua_tolightuserdata(L, lua_upvalueindex(1)));
|
||||
|
||||
TypeFunctionRuntime* runtime = getTypeFunctionRuntime(L);
|
||||
TypeFunctionRuntimeBuilderState* runtimeBuilder = runtime->runtimeBuilder;
|
||||
|
||||
ApplyTypeFunction applyTypeFunction{runtimeBuilder->ctx->arena};
|
||||
|
||||
int argumentCount = lua_gettop(L);
|
||||
std::vector<TypeId> rawTypeArguments;
|
||||
|
||||
for (int i = 0; i < argumentCount; i++)
|
||||
{
|
||||
TypeFunctionTypeId tfty = getTypeUserData(L, i + 1);
|
||||
TypeId ty = deserialize(tfty, runtimeBuilder);
|
||||
|
||||
if (!runtimeBuilder->errors.empty())
|
||||
luaL_error(L, "failed to deserialize type at argument %d", i + 1);
|
||||
|
||||
rawTypeArguments.push_back(ty);
|
||||
}
|
||||
|
||||
// Check if we have enough arguments, by typical typechecking rules
|
||||
size_t typesRequired = tf->typeParams.size();
|
||||
size_t packsRequired = tf->typePackParams.size();
|
||||
|
||||
size_t typesProvided = rawTypeArguments.size() > typesRequired ? typesRequired : rawTypeArguments.size();
|
||||
size_t extraTypes = rawTypeArguments.size() > typesRequired ? rawTypeArguments.size() - typesRequired : 0;
|
||||
size_t packsProvided = 0;
|
||||
|
||||
if (extraTypes != 0 && packsProvided == 0)
|
||||
{
|
||||
// Extra types are only collected into a pack if a pack is expected
|
||||
if (packsRequired != 0)
|
||||
packsProvided += 1;
|
||||
else
|
||||
typesProvided += extraTypes;
|
||||
}
|
||||
|
||||
for (size_t i = typesProvided; i < typesRequired; ++i)
|
||||
{
|
||||
if (tf->typeParams[i].defaultValue)
|
||||
typesProvided += 1;
|
||||
}
|
||||
|
||||
for (size_t i = packsProvided; i < packsRequired; ++i)
|
||||
{
|
||||
if (tf->typePackParams[i].defaultValue)
|
||||
packsProvided += 1;
|
||||
}
|
||||
|
||||
if (extraTypes == 0 && packsProvided + 1 == packsRequired)
|
||||
packsProvided += 1;
|
||||
|
||||
if (typesProvided != typesRequired || packsProvided != packsRequired)
|
||||
luaL_error(L, "not enough arguments to call");
|
||||
|
||||
// Prepare final types and packs
|
||||
auto [types, packs] = saturateArguments(runtimeBuilder->ctx->arena, runtimeBuilder->ctx->builtins, *tf, rawTypeArguments, {});
|
||||
|
||||
for (size_t i = 0; i < types.size(); ++i)
|
||||
applyTypeFunction.typeArguments[tf->typeParams[i].ty] = types[i];
|
||||
|
||||
for (size_t i = 0; i < packs.size(); ++i)
|
||||
applyTypeFunction.typePackArguments[tf->typePackParams[i].tp] = packs[i];
|
||||
|
||||
std::optional<TypeId> maybeInstantiated = applyTypeFunction.substitute(tf->type);
|
||||
|
||||
if (!maybeInstantiated.has_value())
|
||||
{
|
||||
luaL_error(L, "failed to instantiate type alias");
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeId target = follow(*maybeInstantiated);
|
||||
|
||||
FunctionGraphReductionResult result = reduceTypeFunctions(target, Location{}, runtimeBuilder->ctx);
|
||||
|
||||
if (!result.errors.empty())
|
||||
luaL_error(L, "failed to reduce type function with: %s", toString(result.errors.front()).c_str());
|
||||
|
||||
TypeFunctionTypeId serializedTy = serialize(follow(target), runtimeBuilder);
|
||||
|
||||
if (!runtimeBuilder->errors.empty())
|
||||
luaL_error(L, "%s", runtimeBuilder->errors.front().c_str());
|
||||
|
||||
allocTypeUserData(L, serializedTy->type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeFunctionReductionResult<TypeId> userDefinedTypeFunction(
|
||||
TypeId instance,
|
||||
const std::vector<TypeId>& typeParams,
|
||||
const std::vector<TypePackId>& packParams,
|
||||
NotNull<TypeFunctionContext> ctx
|
||||
)
|
||||
{
|
||||
auto typeFunction = getMutable<TypeFunctionInstanceType>(instance);
|
||||
|
||||
if (typeFunction->userFuncData.owner.expired())
|
||||
{
|
||||
ctx->ice->ice("user-defined type function module has expired");
|
||||
return {std::nullopt, Reduction::Erroneous, {}, {}};
|
||||
}
|
||||
|
||||
if (!typeFunction->userFuncName || !typeFunction->userFuncData.definition)
|
||||
{
|
||||
ctx->ice->ice("all user-defined type functions must have an associated function definition");
|
||||
return {std::nullopt, Reduction::Erroneous, {}, {}};
|
||||
}
|
||||
|
||||
// If type functions cannot be evaluated because of errors in the code, we do not generate any additional ones
|
||||
if (!ctx->typeFunctionRuntime->allowEvaluation || typeFunction->userFuncData.definition->hasErrors)
|
||||
return {ctx->builtins->errorType, Reduction::MaybeOk, {}, {}};
|
||||
|
||||
FindUserTypeFunctionBlockers check{ctx};
|
||||
|
||||
for (auto typeParam : typeParams)
|
||||
check.traverse(follow(typeParam));
|
||||
|
||||
if (FFlag::LuauUserTypeFunctionAliases)
|
||||
{
|
||||
// Check that our environment doesn't depend on any type aliases that are blocked
|
||||
for (auto& [name, definition] : typeFunction->userFuncData.environmentAlias)
|
||||
{
|
||||
if (definition.first->typeParams.empty() && definition.first->typePackParams.empty())
|
||||
check.traverse(follow(definition.first->type));
|
||||
}
|
||||
}
|
||||
|
||||
if (!check.blockingTypes.empty())
|
||||
return {std::nullopt, Reduction::MaybeOk, check.blockingTypes, {}};
|
||||
|
||||
// Ensure that whole type function environment is registered
|
||||
for (auto& [name, definition] : typeFunction->userFuncData.environmentFunction)
|
||||
{
|
||||
// Cannot evaluate if a potential dependency couldn't be parsed
|
||||
if (definition.first->hasErrors)
|
||||
return {ctx->builtins->errorType, Reduction::MaybeOk, {}, {}};
|
||||
|
||||
if (std::optional<std::string> error = ctx->typeFunctionRuntime->registerFunction(definition.first))
|
||||
{
|
||||
// Failure to register at this point means that original definition had to error out and should not have been present in the
|
||||
// environment
|
||||
ctx->ice->ice("user-defined type function reference cannot be registered");
|
||||
return {std::nullopt, Reduction::Erroneous, {}, {}};
|
||||
}
|
||||
}
|
||||
|
||||
AstName name = typeFunction->userFuncData.definition->name;
|
||||
|
||||
lua_State* global = ctx->typeFunctionRuntime->state.get();
|
||||
|
||||
if (global == nullptr)
|
||||
return {std::nullopt, Reduction::Erroneous, {}, {}, format("'%s' type function: cannot be evaluated in this context", name.value)};
|
||||
|
||||
// Separate sandboxed thread for individual execution and private globals
|
||||
lua_State* L = lua_newthread(global);
|
||||
LuauTempThreadPopper popper(global);
|
||||
|
||||
std::unique_ptr<TypeFunctionRuntimeBuilderState> runtimeBuilder = std::make_unique<TypeFunctionRuntimeBuilderState>(ctx);
|
||||
|
||||
ScopedAssign setRuntimeBuilder(ctx->typeFunctionRuntime->runtimeBuilder, runtimeBuilder.get());
|
||||
ScopedAssign enableReduction(ctx->normalizer->sharedState->reentrantTypeReduction, false);
|
||||
|
||||
// Build up the environment table of each function we have visible
|
||||
for (auto& [_, curr] : typeFunction->userFuncData.environmentFunction)
|
||||
{
|
||||
// Environment table has to be filled only once in the current execution context
|
||||
if (ctx->typeFunctionRuntime->initialized.find(curr.first))
|
||||
continue;
|
||||
ctx->typeFunctionRuntime->initialized.insert(curr.first);
|
||||
|
||||
lua_pushlightuserdata(L, curr.first);
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
if (!lua_isfunction(L, -1))
|
||||
{
|
||||
ctx->ice->ice("user-defined type function reference cannot be found in the registry");
|
||||
return {std::nullopt, Reduction::Erroneous, {}, {}};
|
||||
}
|
||||
|
||||
// Build up the environment of the current function, where some might not be visible
|
||||
lua_getfenv(L, -1);
|
||||
lua_setreadonly(L, -1, false);
|
||||
|
||||
for (auto& [name, definition] : typeFunction->userFuncData.environmentFunction)
|
||||
{
|
||||
// Filter visibility based on original scope depth
|
||||
if (definition.second >= curr.second)
|
||||
{
|
||||
lua_pushlightuserdata(L, definition.first);
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
if (!lua_isfunction(L, -1))
|
||||
break; // Don't have to report an error here, we will visit each function in outer loop
|
||||
|
||||
lua_setfield(L, -2, name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (FFlag::LuauUserTypeFunctionAliases)
|
||||
{
|
||||
for (auto& [name, definition] : typeFunction->userFuncData.environmentAlias)
|
||||
{
|
||||
// Filter visibility based on original scope depth
|
||||
if (definition.second >= curr.second)
|
||||
{
|
||||
if (definition.first->typeParams.empty() && definition.first->typePackParams.empty())
|
||||
{
|
||||
TypeId ty = follow(definition.first->type);
|
||||
|
||||
// This is checked at the top of the function, and should still be true.
|
||||
LUAU_ASSERT(!isPending(ty, ctx->solver));
|
||||
|
||||
TypeFunctionTypeId serializedTy = serialize(ty, runtimeBuilder.get());
|
||||
|
||||
// Only register aliases that are representable in type environment
|
||||
if (runtimeBuilder->errors.empty())
|
||||
{
|
||||
allocTypeUserData(L, serializedTy->type);
|
||||
lua_setfield(L, -2, name.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushlightuserdata(L, definition.first);
|
||||
lua_pushcclosure(L, evaluateTypeAliasCall, name.c_str(), 1);
|
||||
lua_setfield(L, -2, name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lua_setreadonly(L, -1, true);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
// Fetch the function we want to evaluate
|
||||
lua_pushlightuserdata(L, typeFunction->userFuncData.definition);
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
if (!lua_isfunction(L, -1))
|
||||
{
|
||||
ctx->ice->ice("user-defined type function reference cannot be found in the registry");
|
||||
return {std::nullopt, Reduction::Erroneous, {}, {}};
|
||||
}
|
||||
|
||||
resetTypeFunctionState(L);
|
||||
|
||||
// Push serialized arguments onto the stack
|
||||
for (auto typeParam : typeParams)
|
||||
{
|
||||
TypeId ty = follow(typeParam);
|
||||
// This is checked at the top of the function, and should still be true.
|
||||
LUAU_ASSERT(!isPending(ty, ctx->solver));
|
||||
|
||||
TypeFunctionTypeId serializedTy = serialize(ty, runtimeBuilder.get());
|
||||
// Check if there were any errors while serializing
|
||||
if (runtimeBuilder->errors.size() != 0)
|
||||
return {std::nullopt, Reduction::Erroneous, {}, {}, runtimeBuilder->errors.front()};
|
||||
|
||||
allocTypeUserData(L, serializedTy->type);
|
||||
}
|
||||
|
||||
// Set up an interrupt handler for type functions to respect type checking limits and LSP cancellation requests.
|
||||
lua_callbacks(L)->interrupt = [](lua_State* L, int gc)
|
||||
{
|
||||
auto ctx = static_cast<const TypeFunctionRuntime*>(lua_getthreaddata(lua_mainthread(L)));
|
||||
if (ctx->limits->finishTime && TimeTrace::getClock() > *ctx->limits->finishTime)
|
||||
throw TimeLimitError(ctx->ice->moduleName);
|
||||
|
||||
if (ctx->limits->cancellationToken && ctx->limits->cancellationToken->requested())
|
||||
throw UserCancelError(ctx->ice->moduleName);
|
||||
};
|
||||
|
||||
ctx->typeFunctionRuntime->messages.clear();
|
||||
|
||||
if (auto error = checkResultForError(L, name.value, lua_pcall(L, int(typeParams.size()), 1, 0)))
|
||||
return {std::nullopt, Reduction::Erroneous, {}, {}, std::move(error), ctx->typeFunctionRuntime->messages};
|
||||
|
||||
// If the return value is not a type userdata, return with error message
|
||||
if (!isTypeUserData(L, 1))
|
||||
{
|
||||
return {
|
||||
std::nullopt,
|
||||
Reduction::Erroneous,
|
||||
{},
|
||||
{},
|
||||
format("'%s' type function: returned a non-type value", name.value),
|
||||
ctx->typeFunctionRuntime->messages
|
||||
};
|
||||
}
|
||||
|
||||
TypeFunctionTypeId retTypeFunctionTypeId = getTypeUserData(L, 1);
|
||||
|
||||
// No errors should be present here since we should've returned already if any were raised during serialization.
|
||||
LUAU_ASSERT(runtimeBuilder->errors.size() == 0);
|
||||
|
||||
TypeId retTypeId = deserialize(retTypeFunctionTypeId, runtimeBuilder.get());
|
||||
|
||||
// At least 1 error occurred while deserializing
|
||||
if (runtimeBuilder->errors.size() > 0)
|
||||
return {std::nullopt, Reduction::Erroneous, {}, {}, runtimeBuilder->errors.front(), ctx->typeFunctionRuntime->messages};
|
||||
|
||||
return {retTypeId, Reduction::MaybeOk, {}, {}, std::nullopt, ctx->typeFunctionRuntime->messages};
|
||||
}
|
||||
|
||||
}
|
|
@ -20,7 +20,6 @@ LUAU_FASTINTVARIABLE(LuauParseErrorLimit, 100)
|
|||
LUAU_FASTFLAGVARIABLE(LuauSolverV2)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDeclareExternType)
|
||||
LUAU_FASTFLAGVARIABLE(LuauParseStringIndexer)
|
||||
LUAU_FASTFLAGVARIABLE(LuauCSTForReturnTypeFunctionTail)
|
||||
LUAU_FASTFLAGVARIABLE(LuauParseAttributeFixUninit)
|
||||
LUAU_DYNAMIC_FASTFLAGVARIABLE(DebugLuauReportReturnTypeVariadicWithTypeSuffix, false)
|
||||
|
||||
|
@ -1903,10 +1902,8 @@ AstTypePack* Parser::parseReturnType()
|
|||
// possibly () -> ReturnType
|
||||
if (lexer.current().type != ')')
|
||||
{
|
||||
if (FFlag::LuauCSTForReturnTypeFunctionTail && options.storeCstData)
|
||||
if (options.storeCstData)
|
||||
varargAnnotation = parseTypeList(result, resultNames, &commaPositions, &nameColonPositions);
|
||||
else if (options.storeCstData)
|
||||
varargAnnotation = parseTypeList(result, resultNames, &commaPositions);
|
||||
else
|
||||
varargAnnotation = parseTypeList(result, resultNames);
|
||||
}
|
||||
|
@ -1950,7 +1947,7 @@ AstTypePack* Parser::parseReturnType()
|
|||
Position returnArrowPosition = lexer.current().location.begin;
|
||||
AstType* tail = parseFunctionTypeTail(begin, {nullptr, 0}, {}, {}, copy(result), copy(resultNames), varargAnnotation);
|
||||
|
||||
if (FFlag::LuauCSTForReturnTypeFunctionTail && options.storeCstData && tail->is<AstTypeFunction>())
|
||||
if (options.storeCstData && tail->is<AstTypeFunction>())
|
||||
{
|
||||
cstNodeMap[tail] = allocator.alloc<CstTypeFunction>(
|
||||
Position{0, 0},
|
||||
|
|
|
@ -392,7 +392,7 @@ enum class IrCmd : uint8_t
|
|||
// C: Rn or unsigned int (key)
|
||||
SET_TABLE,
|
||||
|
||||
// TODO: remove with FFlagLuauCodeGenSimplifyImport
|
||||
// TODO: remove with FFlagLuauCodeGenSimplifyImport2
|
||||
// Lookup a value in the environment
|
||||
// A: Rn (where to store the result)
|
||||
// B: unsigned int (import path)
|
||||
|
|
|
@ -1384,7 +1384,10 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
|
|||
break;
|
||||
case IrCmd::GET_CACHED_IMPORT:
|
||||
{
|
||||
regs.spill(build, index);
|
||||
|
||||
Label skip, exit;
|
||||
|
||||
RegisterA64 tempTag = regs.allocTemp(KindA64::w);
|
||||
|
||||
AddressA64 addrConstTag = tempAddr(inst.b, offsetof(TValue, tt));
|
||||
|
@ -1395,8 +1398,6 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
|
|||
build.cbnz(tempTag, skip);
|
||||
|
||||
{
|
||||
size_t spills = regs.spill(build, index);
|
||||
|
||||
build.mov(x0, rState);
|
||||
build.add(x1, rBase, uint16_t(vmRegOp(inst.a) * sizeof(TValue)));
|
||||
build.mov(w2, importOp(inst.c));
|
||||
|
@ -1404,16 +1405,14 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
|
|||
build.ldr(x4, mem(rNativeContext, offsetof(NativeContext, getImport)));
|
||||
build.blr(x4);
|
||||
|
||||
regs.restore(build, spills); // Need to restore before skip so that registers are in a consistent state
|
||||
|
||||
emitUpdateBase(build);
|
||||
build.b(exit);
|
||||
}
|
||||
|
||||
RegisterA64 tempTv = regs.allocTemp(KindA64::q);
|
||||
|
||||
build.setLabel(skip);
|
||||
|
||||
RegisterA64 tempTv = regs.allocTemp(KindA64::q);
|
||||
|
||||
AddressA64 addrConst = tempAddr(inst.b, 0);
|
||||
build.ldr(tempTv, addrConst);
|
||||
|
||||
|
|
|
@ -1221,6 +1221,9 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
|
|||
}
|
||||
case IrCmd::GET_CACHED_IMPORT:
|
||||
{
|
||||
regs.assertAllFree();
|
||||
regs.assertNoSpills();
|
||||
|
||||
Label skip, exit;
|
||||
|
||||
// If the constant for the import is set, we will use it directly, otherwise we have to call an import path lookup function
|
||||
|
@ -1241,9 +1244,10 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
|
|||
emitUpdateBase(build);
|
||||
build.jmp(exit);
|
||||
|
||||
build.setLabel(skip);
|
||||
|
||||
ScopedRegX64 tmp1{regs, SizeX64::xmmword};
|
||||
|
||||
build.setLabel(skip);
|
||||
build.vmovups(tmp1.reg, luauConstant(vmConstOp(inst.b)));
|
||||
build.vmovups(luauReg(vmRegOp(inst.a)), tmp1.reg);
|
||||
build.setLabel(exit);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "lstate.h"
|
||||
#include "ltm.h"
|
||||
|
||||
LUAU_FASTFLAGVARIABLE(LuauCodeGenSimplifyImport)
|
||||
LUAU_FASTFLAGVARIABLE(LuauCodeGenSimplifyImport2)
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
@ -1217,7 +1217,7 @@ void translateInstGetImport(IrBuilder& build, const Instruction* pc, int pcpos)
|
|||
int k = LUAU_INSN_D(*pc);
|
||||
uint32_t aux = pc[1];
|
||||
|
||||
if (FFlag::LuauCodeGenSimplifyImport)
|
||||
if (FFlag::LuauCodeGenSimplifyImport2)
|
||||
{
|
||||
build.inst(IrCmd::CHECK_SAFE_ENV, build.vmExit(pcpos));
|
||||
build.inst(IrCmd::GET_CACHED_IMPORT, build.vmReg(ra), build.vmConst(k), build.constImport(aux), build.constUint(pcpos + 1));
|
||||
|
|
|
@ -1545,6 +1545,8 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction&
|
|||
// Outside of safe environment, environment traversal for an import can execute custom code
|
||||
if (!state.inSafeEnv)
|
||||
state.invalidateUserCall();
|
||||
|
||||
state.invalidateValuePropagation();
|
||||
break;
|
||||
case IrCmd::CONCAT:
|
||||
state.invalidateRegisterRange(vmRegOp(inst.a), function.uintOp(inst.b));
|
||||
|
|
|
@ -4300,8 +4300,6 @@ void compileOrThrow(BytecodeBuilder& bytecode, const ParseResult& parseResult, c
|
|||
}
|
||||
|
||||
// computes type information for all functions based on type annotations
|
||||
if (FFlag::LuauSeparateCompilerTypeInfo)
|
||||
{
|
||||
if (options.typeInfoLevel >= 1 || options.optimizationLevel >= 2)
|
||||
buildTypeMap(
|
||||
compiler.functionTypes,
|
||||
|
@ -4316,24 +4314,6 @@ void compileOrThrow(BytecodeBuilder& bytecode, const ParseResult& parseResult, c
|
|||
options.libraryMemberTypeCb,
|
||||
bytecode
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (options.typeInfoLevel >= 1)
|
||||
buildTypeMap(
|
||||
compiler.functionTypes,
|
||||
compiler.localTypes,
|
||||
compiler.exprTypes,
|
||||
root,
|
||||
options.vectorType,
|
||||
compiler.userdataTypes,
|
||||
compiler.builtinTypes,
|
||||
compiler.builtins,
|
||||
compiler.globals,
|
||||
options.libraryMemberTypeCb,
|
||||
bytecode
|
||||
);
|
||||
}
|
||||
|
||||
for (AstExprFunction* expr : functions)
|
||||
{
|
||||
|
|
|
@ -175,6 +175,7 @@ target_sources(Luau.Analysis PRIVATE
|
|||
Analysis/include/Luau/Autocomplete.h
|
||||
Analysis/include/Luau/AutocompleteTypes.h
|
||||
Analysis/include/Luau/BuiltinDefinitions.h
|
||||
Analysis/include/Luau/BuiltinTypeFunctions.h
|
||||
Analysis/include/Luau/Cancellation.h
|
||||
Analysis/include/Luau/Clone.h
|
||||
Analysis/include/Luau/Constraint.h
|
||||
|
@ -248,6 +249,7 @@ target_sources(Luau.Analysis PRIVATE
|
|||
Analysis/include/Luau/Unifier.h
|
||||
Analysis/include/Luau/Unifier2.h
|
||||
Analysis/include/Luau/UnifierSharedState.h
|
||||
Analysis/include/Luau/UserDefinedTypeFunction.h
|
||||
Analysis/include/Luau/VisitType.h
|
||||
|
||||
Analysis/src/Anyification.cpp
|
||||
|
@ -257,6 +259,7 @@ target_sources(Luau.Analysis PRIVATE
|
|||
Analysis/src/Autocomplete.cpp
|
||||
Analysis/src/AutocompleteCore.cpp
|
||||
Analysis/src/BuiltinDefinitions.cpp
|
||||
Analysis/src/BuiltinTypeFunctions.cpp
|
||||
Analysis/src/Clone.cpp
|
||||
Analysis/src/Constraint.cpp
|
||||
Analysis/src/ConstraintGenerator.cpp
|
||||
|
@ -316,6 +319,7 @@ target_sources(Luau.Analysis PRIVATE
|
|||
Analysis/src/Unifiable.cpp
|
||||
Analysis/src/Unifier.cpp
|
||||
Analysis/src/Unifier2.cpp
|
||||
Analysis/src/UserDefinedTypeFunction.cpp
|
||||
)
|
||||
|
||||
# Luau.EqSat Sources
|
||||
|
|
|
@ -21,7 +21,7 @@ LUAU_FASTFLAG(LuauSetMetatableDoesNotTimeTravel)
|
|||
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
||||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
LUAU_FASTFLAG(LuauExpectedTypeVisitor)
|
||||
LUAU_FASTFLAG(LuauImplicitTableIndexerKeys2)
|
||||
LUAU_FASTFLAG(LuauImplicitTableIndexerKeys3)
|
||||
LUAU_FASTFLAG(LuauPushFunctionTypesInFunctionStatement)
|
||||
|
||||
using namespace Luau;
|
||||
|
@ -4622,7 +4622,7 @@ TEST_CASE_FIXTURE(ACFixture, "autocomplete_implicit_named_index_index_expr")
|
|||
// Somewhat surprisingly, the old solver didn't cover this case.
|
||||
{FFlag::LuauSolverV2, true},
|
||||
{FFlag::LuauExpectedTypeVisitor, true},
|
||||
{FFlag::LuauImplicitTableIndexerKeys2, true},
|
||||
{FFlag::LuauImplicitTableIndexerKeys3, true},
|
||||
};
|
||||
|
||||
check(R"(
|
||||
|
@ -4649,7 +4649,7 @@ TEST_CASE_FIXTURE(ACFixture, "autocomplete_implicit_named_index_index_expr_witho
|
|||
ScopedFastFlag sffs[] = {
|
||||
{FFlag::LuauSolverV2, true},
|
||||
{FFlag::LuauExpectedTypeVisitor, true},
|
||||
{FFlag::LuauImplicitTableIndexerKeys2, false},
|
||||
{FFlag::LuauImplicitTableIndexerKeys3, true},
|
||||
};
|
||||
|
||||
check(R"(
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
using namespace Luau;
|
||||
|
||||
LUAU_FASTFLAG(LuauSolverV2);
|
||||
LUAU_FASTFLAG(LuauDoNotAddUpvalueTypesToLocalType)
|
||||
LUAU_FASTFLAG(LuauDfgAllowUpdatesInLoops)
|
||||
|
||||
struct DataFlowGraphFixture
|
||||
|
@ -447,8 +446,6 @@ TEST_CASE_FIXTURE(DataFlowGraphFixture, "property_lookup_on_a_phi_node_3")
|
|||
|
||||
TEST_CASE_FIXTURE(DataFlowGraphFixture, "function_captures_are_phi_nodes_of_all_versions")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDoNotAddUpvalueTypesToLocalType, true};
|
||||
|
||||
dfg(R"(
|
||||
local x = 5
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||
#pragma once
|
||||
|
||||
#include "Luau/BuiltinTypeFunctions.h"
|
||||
#include "Luau/Config.h"
|
||||
#include "Luau/EqSatSimplification.h"
|
||||
#include "Luau/Error.h"
|
||||
|
|
|
@ -16,7 +16,6 @@ using namespace Luau;
|
|||
LUAU_FASTFLAG(LuauSolverV2);
|
||||
LUAU_FASTFLAG(DebugLuauFreezeArena)
|
||||
LUAU_FASTFLAG(DebugLuauMagicTypes)
|
||||
LUAU_FASTFLAG(LuauNewNonStrictVisitTypes2)
|
||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck2)
|
||||
|
||||
namespace
|
||||
|
@ -977,9 +976,6 @@ TEST_CASE_FIXTURE(FrontendFixture, "environments")
|
|||
LUAU_REQUIRE_NO_ERRORS(resultA);
|
||||
|
||||
CheckResult resultB = getFrontend().check("B");
|
||||
if (FFlag::LuauSolverV2 && !FFlag::LuauNewNonStrictVisitTypes2)
|
||||
LUAU_REQUIRE_NO_ERRORS(resultB);
|
||||
else
|
||||
LUAU_REQUIRE_ERROR_COUNT(1, resultB);
|
||||
|
||||
CheckResult resultC = getFrontend().check("C");
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
LUAU_FASTFLAG(LuauCodeGenSimplifyImport)
|
||||
LUAU_FASTFLAG(LuauCodeGenSimplifyImport2)
|
||||
|
||||
static void luauLibraryConstantLookup(const char* library, const char* member, Luau::CompileConstant* constant)
|
||||
{
|
||||
|
@ -500,7 +500,7 @@ bb_bytecode_1:
|
|||
|
||||
TEST_CASE("DseInitialStackState")
|
||||
{
|
||||
ScopedFastFlag luauCodeGenSimplifyImport{FFlag::LuauCodeGenSimplifyImport, true};
|
||||
ScopedFastFlag luauCodeGenSimplifyImport{FFlag::LuauCodeGenSimplifyImport2, true};
|
||||
|
||||
CHECK_EQ(
|
||||
"\n" + getCodegenAssembly(R"(
|
||||
|
@ -1567,7 +1567,7 @@ end
|
|||
|
||||
TEST_CASE("ForInManualAnnotation")
|
||||
{
|
||||
ScopedFastFlag luauCodeGenSimplifyImport{FFlag::LuauCodeGenSimplifyImport, true};
|
||||
ScopedFastFlag luauCodeGenSimplifyImport{FFlag::LuauCodeGenSimplifyImport2, true};
|
||||
|
||||
CHECK_EQ(
|
||||
"\n" + getCodegenAssembly(
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "doctest.h"
|
||||
#include <iostream>
|
||||
|
||||
LUAU_FASTFLAG(LuauNewNonStrictVisitTypes2)
|
||||
LUAU_FASTFLAG(LuauNewNonStrictFixGenericTypePacks)
|
||||
LUAU_FASTFLAG(LuauNewNonStrictMoreUnknownSymbols)
|
||||
LUAU_FASTFLAG(LuauNewNonStrictNoErrorsPassingNever)
|
||||
|
@ -737,8 +736,6 @@ TEST_CASE_FIXTURE(Fixture, "unknown_globals_in_non_strict_1")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "unknown_types_in_non_strict")
|
||||
{
|
||||
ScopedFastFlag sff{FFlag::LuauNewNonStrictVisitTypes2, true};
|
||||
|
||||
CheckResult result = check(Mode::Nonstrict, R"(
|
||||
--!nonstrict
|
||||
local foo: Foo = 1
|
||||
|
@ -752,8 +749,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "unknown_types_in_non_strict")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "unknown_types_in_non_strict_2")
|
||||
{
|
||||
ScopedFastFlag sff{FFlag::LuauNewNonStrictVisitTypes2, true};
|
||||
|
||||
CheckResult result = check(Mode::Nonstrict, R"(
|
||||
--!nonstrict
|
||||
local foo = 1 :: Foo
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
|
||||
using namespace Luau;
|
||||
|
||||
LUAU_FASTFLAG(LuauCSTForReturnTypeFunctionTail)
|
||||
|
||||
TEST_SUITE_BEGIN("TranspilerTests");
|
||||
|
||||
TEST_CASE("test_1")
|
||||
|
@ -2055,9 +2053,6 @@ TEST_CASE("transpile_type_function_return_types")
|
|||
|
||||
TEST_CASE("transpile_chained_function_types")
|
||||
{
|
||||
ScopedFastFlag fflags[] = {
|
||||
{FFlag::LuauCSTForReturnTypeFunctionTail, true},
|
||||
};
|
||||
std::string code = R"( type Foo = () -> () -> () )";
|
||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||
|
||||
|
|
|
@ -1813,7 +1813,7 @@ struct TFFixture
|
|||
|
||||
BuiltinTypeFunctions builtinTypeFunctions;
|
||||
|
||||
TypeFunctionContext tfc{
|
||||
TypeFunctionContext tfc_{
|
||||
arena,
|
||||
getBuiltins(),
|
||||
NotNull{globalScope.get()},
|
||||
|
@ -1823,6 +1823,8 @@ struct TFFixture
|
|||
NotNull{&ice},
|
||||
NotNull{&limits}
|
||||
};
|
||||
|
||||
NotNull<TypeFunctionContext> tfc{&tfc_};
|
||||
};
|
||||
|
||||
TEST_CASE_FIXTURE(TFFixture, "refine<G, ~(false?)>")
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
using namespace Luau;
|
||||
|
||||
LUAU_FASTFLAG(LuauSolverV2)
|
||||
LUAU_FASTFLAG(LuauNewNonStrictVisitTypes2)
|
||||
LUAU_FASTFLAG(LuauGuardAgainstMalformedTypeAliasExpansion2)
|
||||
LUAU_FASTFLAG(LuauSkipMalformedTypeAliases)
|
||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck2)
|
||||
|
@ -1180,10 +1179,7 @@ TEST_CASE_FIXTURE(Fixture, "bound_type_in_alias_segfault")
|
|||
export type FieldConfigMap<TSource, TContext> = Map<string, FieldConfig<TSource, TContext>>
|
||||
)");
|
||||
|
||||
if (FFlag::LuauNewNonStrictVisitTypes2)
|
||||
LUAU_CHECK_ERROR_COUNT(2, result);
|
||||
else
|
||||
LUAU_CHECK_NO_ERRORS(result);
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "gh1632_no_infinite_recursion_in_normalization")
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
using namespace Luau;
|
||||
|
||||
LUAU_FASTFLAG(LuauSolverV2)
|
||||
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
||||
LUAU_FASTFLAG(LuauDfgAllowUpdatesInLoops)
|
||||
LUAU_FASTFLAG(LuauRemoveTypeCallsForReadWriteProps)
|
||||
|
||||
|
@ -36,16 +35,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_returns_any")
|
|||
LUAU_REQUIRE_NO_ERRORS(result);
|
||||
|
||||
if (FFlag::LuauSolverV2)
|
||||
{
|
||||
if (FFlag::LuauAddCallConstraintForIterableFunctions)
|
||||
{
|
||||
CHECK("(*error-type* | ~nil)?" == toString(requireType("a")));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK("any?" == toString(requireType("a")));
|
||||
}
|
||||
}
|
||||
else
|
||||
CHECK(getBuiltins()->anyType == requireType("a"));
|
||||
}
|
||||
|
@ -66,16 +56,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_returns_any2")
|
|||
LUAU_REQUIRE_NO_ERRORS(result);
|
||||
|
||||
if (FFlag::LuauSolverV2)
|
||||
{
|
||||
if (FFlag::LuauAddCallConstraintForIterableFunctions)
|
||||
{
|
||||
CHECK("(*error-type* | ~nil)?" == toString(requireType("a")));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK("any?" == toString(requireType("a")));
|
||||
}
|
||||
}
|
||||
else
|
||||
CHECK("any" == toString(requireType("a")));
|
||||
}
|
||||
|
@ -94,16 +75,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_is_any")
|
|||
LUAU_REQUIRE_NO_ERRORS(result);
|
||||
|
||||
if (FFlag::LuauSolverV2)
|
||||
{
|
||||
if (FFlag::LuauAddCallConstraintForIterableFunctions)
|
||||
{
|
||||
CHECK("(*error-type* | ~nil)?" == toString(requireType("a")));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK("any?" == toString(requireType("a")));
|
||||
}
|
||||
}
|
||||
else
|
||||
CHECK("any" == toString(requireType("a")));
|
||||
}
|
||||
|
@ -120,16 +92,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_is_any2")
|
|||
)");
|
||||
|
||||
if (FFlag::LuauSolverV2)
|
||||
{
|
||||
if (FFlag::LuauAddCallConstraintForIterableFunctions)
|
||||
{
|
||||
CHECK("(*error-type* | ~nil)?" == toString(requireType("a")));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK("any?" == toString(requireType("a")));
|
||||
}
|
||||
}
|
||||
else
|
||||
CHECK("any" == toString(requireType("a")));
|
||||
}
|
||||
|
@ -148,16 +111,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_iterator_is_any_pack")
|
|||
LUAU_REQUIRE_NO_ERRORS(result);
|
||||
|
||||
if (FFlag::LuauSolverV2)
|
||||
{
|
||||
if (FFlag::LuauAddCallConstraintForIterableFunctions)
|
||||
{
|
||||
CHECK("(*error-type* | ~nil)?" == toString(requireType("a")));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK("any?" == toString(requireType("a")));
|
||||
}
|
||||
}
|
||||
else
|
||||
CHECK("any" == toString(requireType("a")));
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ LUAU_FASTFLAG(LuauRemoveTypeCallsForReadWriteProps)
|
|||
LUAU_FASTFLAG(LuauWriteOnlyPropertyMangling)
|
||||
LUAU_FASTFLAG(LuauEnableWriteOnlyProperties)
|
||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeCheckFunctionCalls)
|
||||
LUAU_FASTFLAG(LuauTypeCheckerStricterIndexCheck)
|
||||
LUAU_FASTFLAG(LuauSuppressErrorsForMultipleNonviableOverloads)
|
||||
|
||||
TEST_SUITE_BEGIN("BuiltinTests");
|
||||
|
@ -1767,8 +1766,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "read_refinements_on_persistent_tables_known_
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "read_refinements_on_persistent_tables_unknown_property")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauTypeCheckerStricterIndexCheck, true};
|
||||
|
||||
CheckResult results = check(R"(
|
||||
if bit32.scrambleEggs then
|
||||
end
|
||||
|
|
|
@ -25,7 +25,6 @@ LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
|||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
LUAU_FASTFLAG(LuauArityMismatchOnUndersaturatedUnknownArguments)
|
||||
LUAU_FASTFLAG(LuauFormatUseLastPosition)
|
||||
LUAU_FASTFLAG(LuauDoNotAddUpvalueTypesToLocalType)
|
||||
LUAU_FASTFLAG(LuauSimplifyOutOfLine2)
|
||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck2)
|
||||
LUAU_FASTFLAG(LuauStuckTypeFunctionsStillDispatch)
|
||||
|
@ -3162,7 +3161,7 @@ TEST_CASE_FIXTURE(Fixture, "recursive_function_calls_should_not_use_the_generali
|
|||
|
||||
TEST_CASE_FIXTURE(Fixture, "fuzz_unwind_mutually_recursive_union_type_func")
|
||||
{
|
||||
ScopedFastFlag sffs[] = {{FFlag::LuauSolverV2, true}, {FFlag::LuauDoNotAddUpvalueTypesToLocalType, true}};
|
||||
ScopedFastFlag _{FFlag::LuauSolverV2, true};
|
||||
|
||||
// Previously, this block minted a type like:
|
||||
//
|
||||
|
|
|
@ -9,12 +9,10 @@
|
|||
|
||||
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
||||
LUAU_FASTFLAG(LuauSolverV2)
|
||||
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
||||
LUAU_FASTFLAG(LuauReturnMappedGenericPacksFromSubtyping)
|
||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck2)
|
||||
LUAU_FASTFLAG(LuauIntersectNotNil)
|
||||
LUAU_FASTFLAG(LuauSubtypingCheckFunctionGenericCounts)
|
||||
LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
||||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
LUAU_FASTFLAG(LuauStuckTypeFunctionsStillDispatch)
|
||||
LUAU_FASTFLAG(LuauRemoveTypeCallsForReadWriteProps)
|
||||
|
@ -785,7 +783,7 @@ TEST_CASE_FIXTURE(Fixture, "instantiated_function_argument_names_old_solver")
|
|||
|
||||
TEST_CASE_FIXTURE(Fixture, "error_detailed_function_mismatch_generic_types")
|
||||
{
|
||||
ScopedFastFlag sffs[] = {{FFlag::LuauReportSubtypingErrors, true}, {FFlag::LuauSubtypingCheckFunctionGenericCounts, true}};
|
||||
ScopedFastFlag _{FFlag::LuauSubtypingCheckFunctionGenericCounts, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
type C = () -> ()
|
||||
|
@ -818,7 +816,7 @@ local d: D = c
|
|||
}
|
||||
TEST_CASE_FIXTURE(Fixture, "generic_function_mismatch_with_argument")
|
||||
{
|
||||
ScopedFastFlag sffs[] = {{FFlag::LuauReportSubtypingErrors, true}, {FFlag::LuauSubtypingCheckFunctionGenericCounts, true}};
|
||||
ScopedFastFlag _{FFlag::LuauSubtypingCheckFunctionGenericCounts, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
type C = (number) -> ()
|
||||
|
@ -852,7 +850,7 @@ local d: D = c
|
|||
|
||||
TEST_CASE_FIXTURE(Fixture, "error_detailed_function_mismatch_generic_pack")
|
||||
{
|
||||
ScopedFastFlag sffs[] = {{FFlag::LuauReportSubtypingErrors, true}, {FFlag::LuauSubtypingCheckFunctionGenericCounts, true}};
|
||||
ScopedFastFlag _{FFlag::LuauSubtypingCheckFunctionGenericCounts, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
type C = () -> ()
|
||||
|
@ -1530,7 +1528,6 @@ TEST_CASE_FIXTURE(Fixture, "infer_generic_function_function_argument_overloaded"
|
|||
TEST_CASE_FIXTURE(BuiltinsFixture, "do_not_infer_generic_functions")
|
||||
{
|
||||
ScopedFastFlag _[] = {
|
||||
{FFlag::LuauReportSubtypingErrors, true},
|
||||
{FFlag::LuauSubtypingCheckFunctionGenericCounts, true},
|
||||
{FFlag::LuauEagerGeneralization4, true},
|
||||
};
|
||||
|
|
|
@ -15,9 +15,7 @@
|
|||
using namespace Luau;
|
||||
|
||||
LUAU_FASTFLAG(LuauSolverV2)
|
||||
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
||||
LUAU_FASTFLAG(LuauSimplifyOutOfLine2)
|
||||
LUAU_FASTFLAG(LuauDfgIfBlocksShouldRespectControlFlow)
|
||||
LUAU_FASTFLAG(LuauDfgAllowUpdatesInLoops)
|
||||
|
||||
TEST_SUITE_BEGIN("TypeInferLoops");
|
||||
|
@ -158,7 +156,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_loop")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_loop_with_next")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauAddCallConstraintForIterableFunctions, true};
|
||||
CheckResult result = check(R"(
|
||||
local n
|
||||
local s
|
||||
|
@ -187,7 +184,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_loop_with_next")
|
|||
TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_loop_with_next_and_multiple_elements")
|
||||
{
|
||||
ScopedFastFlag sffs[] = {
|
||||
{FFlag::LuauAddCallConstraintForIterableFunctions, true},
|
||||
{FFlag::LuauSimplifyOutOfLine2, true},
|
||||
{FFlag::LuauDfgAllowUpdatesInLoops, true},
|
||||
};
|
||||
|
@ -289,15 +285,11 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_with_a_custom_iterator_should_type_ch
|
|||
end
|
||||
)");
|
||||
|
||||
if (FFlag::LuauSolverV2 && FFlag::LuauAddCallConstraintForIterableFunctions)
|
||||
{
|
||||
if (FFlag::LuauSolverV2)
|
||||
LUAU_REQUIRE_NO_ERRORS(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(Fixture, "for_in_loop_on_error")
|
||||
{
|
||||
|
@ -1286,7 +1278,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "forin_metatable_iter_mm")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "iteration_preserves_error_suppression")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauAddCallConstraintForIterableFunctions, true};
|
||||
ScopedFastFlag v1{FFlag::LuauSolverV2, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
|
@ -1504,10 +1495,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "repeat_is_linearish")
|
|||
if (!FFlag::LuauSolverV2)
|
||||
return;
|
||||
|
||||
ScopedFastFlag sffs[] = {
|
||||
{FFlag::LuauDfgIfBlocksShouldRespectControlFlow, true},
|
||||
{FFlag::LuauDfgAllowUpdatesInLoops, true},
|
||||
};
|
||||
ScopedFastFlag _{FFlag::LuauDfgAllowUpdatesInLoops, true};
|
||||
|
||||
LUAU_REQUIRE_NO_ERRORS(check(R"(
|
||||
local x = nil
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
||||
LUAU_FASTFLAG(LuauSolverV2)
|
||||
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
||||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
LUAU_FASTFLAG(LuauReturnMappedGenericPacksFromSubtyping)
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
using namespace Luau;
|
||||
|
||||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
@ -50,9 +52,8 @@ TEST_CASE_FIXTURE(NegationFixture, "string_is_not_a_subtype_of_negated_string")
|
|||
|
||||
TEST_CASE_FIXTURE(Fixture, "cofinite_strings_can_be_compared_for_equality")
|
||||
{
|
||||
// CLI-117082 Cofinite strings cannot be compared for equality because normalization produces a large type with cycles
|
||||
if (FFlag::LuauSolverV2)
|
||||
return;
|
||||
ScopedFastFlag sff{FFlag::LuauEagerGeneralization4, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
function f(e)
|
||||
if e == 'strictEqual' then
|
||||
|
|
|
@ -12,15 +12,14 @@ LUAU_FASTFLAG(LuauSolverV2)
|
|||
LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
||||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
LUAU_FASTFLAG(LuauFunctionCallsAreNotNilable)
|
||||
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
||||
LUAU_FASTFLAG(LuauSimplificationTableExternType)
|
||||
LUAU_FASTFLAG(LuauBetterCannotCallFunctionPrimitive)
|
||||
LUAU_FASTFLAG(LuauStuckTypeFunctionsStillDispatch)
|
||||
LUAU_FASTFLAG(LuauTypeCheckerStricterIndexCheck)
|
||||
LUAU_FASTFLAG(LuauNormalizationIntersectTablesPreservesExternTypes)
|
||||
LUAU_FASTFLAG(LuauNormalizationReorderFreeTypeIntersect)
|
||||
LUAU_FASTFLAG(LuauAvoidDoubleNegation)
|
||||
LUAU_FASTFLAG(LuauRefineTablesWithReadType)
|
||||
LUAU_FASTFLAG(LuauRefineNoRefineAlways)
|
||||
|
||||
using namespace Luau;
|
||||
|
||||
|
@ -1944,10 +1943,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "refine_unknown_to_table_then_clone_it")
|
|||
|
||||
TEST_CASE_FIXTURE(RefinementExternTypeFixture, "refine_a_param_that_got_resolved_during_constraint_solving_stage")
|
||||
{
|
||||
// CLI-117134 - Applying a refinement causes an optional value access error.
|
||||
if (FFlag::LuauSolverV2)
|
||||
return;
|
||||
|
||||
CheckResult result = check(R"(
|
||||
type Id<T> = T
|
||||
|
||||
|
@ -2216,15 +2211,8 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "refine_unknown_to_table")
|
|||
|
||||
LUAU_REQUIRE_NO_ERRORS(result);
|
||||
|
||||
if (FFlag::LuauAddCallConstraintForIterableFunctions)
|
||||
{
|
||||
CHECK_EQ("(unknown) -> (~nil, unknown)", toString(requireType("f")));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_EQ("(unknown) -> (unknown, unknown)", toString(requireType("f")));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "conditional_refinement_should_stay_error_suppressing")
|
||||
{
|
||||
|
@ -2713,7 +2701,6 @@ TEST_CASE_FIXTURE(RefinementExternTypeFixture, "cannot_call_a_function_single")
|
|||
ScopedFastFlag sffs[] = {
|
||||
{FFlag::LuauSolverV2, true},
|
||||
{FFlag::LuauBetterCannotCallFunctionPrimitive, true},
|
||||
{FFlag::LuauTypeCheckerStricterIndexCheck, true},
|
||||
{FFlag::LuauRefineTablesWithReadType, true},
|
||||
};
|
||||
|
||||
|
@ -2734,7 +2721,6 @@ TEST_CASE_FIXTURE(RefinementExternTypeFixture, "cannot_call_a_function_union")
|
|||
ScopedFastFlag sffs[] = {
|
||||
{FFlag::LuauSolverV2, true},
|
||||
{FFlag::LuauBetterCannotCallFunctionPrimitive, true},
|
||||
{FFlag::LuauTypeCheckerStricterIndexCheck, true},
|
||||
{FFlag::LuauRefineTablesWithReadType, true},
|
||||
};
|
||||
|
||||
|
@ -2830,4 +2816,34 @@ TEST_CASE_FIXTURE(Fixture, "limit_complexity_of_arithmetic_type_functions" * doc
|
|||
LUAU_REQUIRE_ERRORS(result);
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "refine_by_no_refine_should_always_reduce")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauSolverV2, true};
|
||||
ScopedFastFlag refineNoRefineAlways{FFlag::LuauRefineNoRefineAlways, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
function foo(t): boolean return true end
|
||||
|
||||
function select<K, V>(t: { [K]: V }, columns: { K }): { [K]: V }
|
||||
local result = {}
|
||||
if foo(t) then
|
||||
for k, v in t do
|
||||
if table.find(columns, k) then
|
||||
result[k] = v -- was TypeError: Type function instance refine<intersect<K, ~nil>, *no-refine*> is uninhabited
|
||||
end
|
||||
end
|
||||
else
|
||||
for k, v in pairs(t) do
|
||||
if table.find(columns, k) then
|
||||
result[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
)");
|
||||
|
||||
LUAU_REQUIRE_NO_ERRORS(result);
|
||||
}
|
||||
|
||||
TEST_SUITE_END();
|
||||
|
|
|
@ -23,8 +23,6 @@ LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
|||
LUAU_FASTFLAG(LuauFixIndexerSubtypingOrdering)
|
||||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
LUAU_FASTFLAG(DebugLuauAssertOnForcedConstraint)
|
||||
LUAU_FASTFLAG(LuauTypeCheckerStricterIndexCheck)
|
||||
LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
||||
LUAU_FASTFLAG(LuauSimplifyOutOfLine2)
|
||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck2)
|
||||
LUAU_FASTFLAG(LuauEnableWriteOnlyProperties)
|
||||
|
@ -3818,10 +3816,7 @@ TEST_CASE_FIXTURE(Fixture, "scalar_is_a_subtype_of_a_compatible_polymorphic_shap
|
|||
|
||||
TEST_CASE_FIXTURE(Fixture, "scalar_is_not_a_subtype_of_a_compatible_polymorphic_shape_type")
|
||||
{
|
||||
ScopedFastFlag sff[] = {
|
||||
{FFlag::LuauReportSubtypingErrors, true},
|
||||
{FFlag::LuauEagerGeneralization4, true},
|
||||
};
|
||||
ScopedFastFlag _{FFlag::LuauEagerGeneralization4, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
local function f(s)
|
||||
|
@ -5696,7 +5691,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "function_call_in_indexer_with_compound_assig
|
|||
TEST_CASE_FIXTURE(Fixture, "stop_refining_new_table_indices_for_non_primitive_tables")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauSolverV2, true};
|
||||
ScopedFastFlag stricterIndexCheck{FFlag::LuauTypeCheckerStricterIndexCheck, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
local foo:{val:number} = {val = 1}
|
||||
|
|
|
@ -24,9 +24,7 @@ LUAU_FASTINT(LuauNormalizeCacheLimit)
|
|||
LUAU_FASTINT(LuauRecursionLimit)
|
||||
LUAU_FASTINT(LuauTypeInferTypePackLoopLimit)
|
||||
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
||||
LUAU_FASTFLAG(LuauMagicFreezeCheckBlocked2)
|
||||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
||||
LUAU_FASTFLAG(LuauAvoidDoubleNegation)
|
||||
LUAU_FASTFLAG(LuauInsertErrorTypesIntoIndexerResult)
|
||||
LUAU_FASTFLAG(LuauSimplifyOutOfLine2)
|
||||
|
@ -1213,8 +1211,6 @@ TEST_CASE_FIXTURE(Fixture, "type_infer_recursion_limit_normalizer")
|
|||
REQUIRE_MESSAGE(!result.errors.empty(), getErrors(result));
|
||||
|
||||
if (FFlag::LuauSolverV2)
|
||||
{
|
||||
if (FFlag::LuauReportSubtypingErrors)
|
||||
{
|
||||
CHECK(4 == result.errors.size());
|
||||
CHECK(Location{{2, 22}, {2, 42}} == result.errors[0].location);
|
||||
|
@ -1226,17 +1222,6 @@ TEST_CASE_FIXTURE(Fixture, "type_infer_recursion_limit_normalizer")
|
|||
CHECK_EQ("Code is too complex to typecheck! Consider simplifying the code around this area", toString(e));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK(3 == result.errors.size());
|
||||
CHECK(Location{{2, 22}, {2, 42}} == result.errors[0].location);
|
||||
CHECK(Location{{3, 22}, {3, 42}} == result.errors[1].location);
|
||||
CHECK(Location{{3, 22}, {3, 41}} == result.errors[2].location);
|
||||
CHECK_EQ("Code is too complex to typecheck! Consider simplifying the code around this area", toString(result.errors[0]));
|
||||
CHECK_EQ("Code is too complex to typecheck! Consider simplifying the code around this area", toString(result.errors[1]));
|
||||
CHECK_EQ("Code is too complex to typecheck! Consider simplifying the code around this area", toString(result.errors[2]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK(1 == result.errors.size());
|
||||
|
||||
|
@ -1986,7 +1971,7 @@ TEST_CASE_FIXTURE(Fixture, "assert_allows_singleton_union_or_intersection")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "assert_table_freeze_constraint_solving")
|
||||
{
|
||||
ScopedFastFlag sffs[] = {{FFlag::LuauSolverV2, true}, {FFlag::LuauMagicFreezeCheckBlocked2, true}};
|
||||
ScopedFastFlag _{FFlag::LuauSolverV2, true};
|
||||
LUAU_REQUIRE_NO_ERRORS(check(R"(
|
||||
local f = table.freeze
|
||||
f(table)
|
||||
|
@ -1995,7 +1980,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "assert_table_freeze_constraint_solving")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzz_assert_table_freeze_constraint_solving")
|
||||
{
|
||||
ScopedFastFlag sffs[] = {{FFlag::LuauSolverV2, true}, {FFlag::LuauMagicFreezeCheckBlocked2, true}};
|
||||
ScopedFastFlag _ {FFlag::LuauSolverV2, true};
|
||||
// This is the original fuzzer version of the above issue.
|
||||
CheckResult results = check(R"(
|
||||
local function l0()
|
||||
|
@ -2116,8 +2101,6 @@ local _
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzz_missing_follow_table_freeze")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauMagicFreezeCheckBlocked2, true};
|
||||
|
||||
LUAU_REQUIRE_ERRORS(check(R"(
|
||||
if _:freeze(_)[_][_] then
|
||||
else
|
||||
|
|
|
@ -13,7 +13,6 @@ LUAU_FASTFLAG(LuauSolverV2)
|
|||
|
||||
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
||||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck2)
|
||||
LUAU_FASTFLAG(LuauFixEmptyTypePackStringification)
|
||||
|
||||
|
@ -1063,8 +1062,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "detect_cyclic_typepacks")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "detect_cyclic_typepacks2")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauReportSubtypingErrors, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
function _(l0:((typeof((pcall)))|((((t0)->())|(typeof(-67108864)))|(any)))|(any),...):(((typeof(0))|(any))|(any),typeof(-67108864),any)
|
||||
xpcall(_,_,_)
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
#include "doctest.h"
|
||||
|
||||
LUAU_FASTFLAG(LuauSolverV2)
|
||||
LUAU_FASTFLAG(LuauDoNotAddUpvalueTypesToLocalType)
|
||||
LUAU_FASTFLAG(LuauDfgIfBlocksShouldRespectControlFlow)
|
||||
LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
||||
LUAU_FASTFLAG(LuauEagerGeneralization4)
|
||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck2)
|
||||
LUAU_FASTFLAG(LuauDfgAllowUpdatesInLoops)
|
||||
|
@ -269,8 +266,6 @@ TEST_CASE_FIXTURE(TypeStateFixture, "local_assigned_in_only_one_branch_that_fall
|
|||
|
||||
TEST_CASE_FIXTURE(TypeStateFixture, "then_branch_assigns_and_else_branch_also_assigns_but_is_met_with_return")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDfgIfBlocksShouldRespectControlFlow, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
local x = nil
|
||||
if math.random() > 0.5 then
|
||||
|
@ -288,8 +283,6 @@ TEST_CASE_FIXTURE(TypeStateFixture, "then_branch_assigns_and_else_branch_also_as
|
|||
|
||||
TEST_CASE_FIXTURE(TypeStateFixture, "then_branch_assigns_but_is_met_with_return_and_else_branch_assigns")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDfgIfBlocksShouldRespectControlFlow, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
local x = nil
|
||||
if math.random() > 0.5 then
|
||||
|
@ -350,7 +343,6 @@ TEST_CASE_FIXTURE(TypeStateFixture, "local_t_is_assigned_a_fresh_table_with_x_as
|
|||
|
||||
TEST_CASE_FIXTURE(TypeStateFixture, "captured_locals_do_not_mutate_upvalue_type")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDoNotAddUpvalueTypesToLocalType, true};
|
||||
CheckResult result = check(R"(
|
||||
local x = nil
|
||||
|
||||
|
@ -372,7 +364,6 @@ TEST_CASE_FIXTURE(TypeStateFixture, "captured_locals_do_not_mutate_upvalue_type"
|
|||
|
||||
TEST_CASE_FIXTURE(TypeStateFixture, "captured_locals_do_not_mutate_upvalue_type_2")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDoNotAddUpvalueTypesToLocalType, true};
|
||||
CheckResult result = check(R"(
|
||||
local t = {x = nil}
|
||||
|
||||
|
@ -413,7 +404,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "prototyped_recursive_functions_but_has_futur
|
|||
{
|
||||
ScopedFastFlag sffs[] = {
|
||||
{FFlag::LuauSolverV2, true},
|
||||
{FFlag::LuauReportSubtypingErrors, true},
|
||||
{FFlag::LuauEagerGeneralization4, true},
|
||||
};
|
||||
|
||||
|
@ -477,25 +467,6 @@ TEST_CASE_FIXTURE(TypeStateFixture, "typestates_preserve_error_suppression")
|
|||
CHECK("*error-type* | string" == toString(requireTypeAtPosition({3, 14}), {true}));
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "typestates_preserve_error_suppression_properties")
|
||||
{
|
||||
// early return if the flag isn't set since this is blocking gated commits
|
||||
// unconditional return
|
||||
// CLI-117098 Type states with error suppressing properties doesn't infer the correct type for properties.
|
||||
if (!FFlag::LuauSolverV2 || FFlag::LuauSolverV2)
|
||||
return;
|
||||
|
||||
CheckResult result = check(R"(
|
||||
local a: {x: any} = {x = 51}
|
||||
a.x = "pickles" -- We'll have a new DefId for this iteration of `a.x`. Its type must also be error-suppressing
|
||||
print(a.x)
|
||||
)");
|
||||
|
||||
LUAU_REQUIRE_NO_ERRORS(result);
|
||||
CHECK("*error-type* | string" == toString(requireTypeAtPosition({3, 16}), {true}));
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "typestates_do_not_apply_to_the_initial_local_definition")
|
||||
{
|
||||
// early return if the flag isn't set since this is blocking gated commits
|
||||
|
@ -577,8 +548,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "fuzzer_normalized_type_variables_are_bad" *
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "oss_1547_simple")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDoNotAddUpvalueTypesToLocalType, true};
|
||||
|
||||
LUAU_REQUIRE_NO_ERRORS(check(R"(
|
||||
local rand = 0
|
||||
|
||||
|
@ -594,8 +563,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "oss_1547_simple")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "oss_1547")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDoNotAddUpvalueTypesToLocalType, true};
|
||||
|
||||
LUAU_REQUIRE_NO_ERRORS(check(R"(
|
||||
local rand = 0
|
||||
|
||||
|
@ -629,8 +596,6 @@ TEST_CASE_FIXTURE(Fixture, "modify_captured_table_field")
|
|||
|
||||
TEST_CASE_FIXTURE(Fixture, "oss_1561")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDoNotAddUpvalueTypesToLocalType, true};
|
||||
|
||||
loadDefinition(R"(
|
||||
declare class Vector3
|
||||
X: number
|
||||
|
@ -655,8 +620,6 @@ TEST_CASE_FIXTURE(Fixture, "oss_1561")
|
|||
|
||||
TEST_CASE_FIXTURE(Fixture, "oss_1575")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDoNotAddUpvalueTypesToLocalType, true};
|
||||
|
||||
LUAU_REQUIRE_NO_ERRORS(check(R"(
|
||||
local flag = true
|
||||
local function Flip()
|
||||
|
@ -667,8 +630,6 @@ TEST_CASE_FIXTURE(Fixture, "oss_1575")
|
|||
|
||||
TEST_CASE_FIXTURE(Fixture, "capture_upvalue_in_returned_function")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDoNotAddUpvalueTypesToLocalType, true};
|
||||
|
||||
LUAU_REQUIRE_NO_ERRORS(check(R"(
|
||||
function def()
|
||||
local i : number = 0
|
||||
|
@ -684,8 +645,6 @@ TEST_CASE_FIXTURE(Fixture, "capture_upvalue_in_returned_function")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "throw_in_else_branch")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDfgIfBlocksShouldRespectControlFlow, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
--!strict
|
||||
local x
|
||||
|
@ -707,8 +666,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "throw_in_else_branch")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "throw_in_if_branch")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDfgIfBlocksShouldRespectControlFlow, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
--!strict
|
||||
local x
|
||||
|
@ -731,8 +688,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "throw_in_if_branch")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "refinement_through_erroring")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDfgIfBlocksShouldRespectControlFlow, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
--!strict
|
||||
type Payload = { payload: number }
|
||||
|
@ -756,7 +711,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "refinement_through_erroring")
|
|||
TEST_CASE_FIXTURE(BuiltinsFixture, "refinement_through_erroring_in_loop")
|
||||
{
|
||||
ScopedFastFlag sffs[] = {
|
||||
{FFlag::LuauSolverV2, true}, {FFlag::LuauDfgIfBlocksShouldRespectControlFlow, true}, {FFlag::LuauDfgAllowUpdatesInLoops, true}
|
||||
{FFlag::LuauSolverV2, true}, {FFlag::LuauDfgAllowUpdatesInLoops, true}
|
||||
};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
|
@ -778,8 +733,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "refinement_through_erroring_in_loop")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "type_refinement_in_loop")
|
||||
{
|
||||
ScopedFastFlag _{FFlag::LuauDfgIfBlocksShouldRespectControlFlow, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
--!strict
|
||||
local function onEachString(t: { string | number })
|
||||
|
@ -800,10 +753,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "type_refinement_in_loop")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "throw_in_if_branch_and_do_nothing_in_else")
|
||||
{
|
||||
ScopedFastFlag sffs[] = {
|
||||
{FFlag::LuauSolverV2, true},
|
||||
{FFlag::LuauDfgIfBlocksShouldRespectControlFlow, true},
|
||||
};
|
||||
ScopedFastFlag _{FFlag::LuauSolverV2, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
--!strict
|
||||
|
@ -825,10 +775,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "throw_in_if_branch_and_do_nothing_in_else")
|
|||
|
||||
TEST_CASE_FIXTURE(BuiltinsFixture, "assign_in_an_if_branch_without_else")
|
||||
{
|
||||
ScopedFastFlag sffs[] = {
|
||||
{FFlag::LuauSolverV2, true},
|
||||
{FFlag::LuauDfgIfBlocksShouldRespectControlFlow, true},
|
||||
};
|
||||
ScopedFastFlag _{FFlag::LuauSolverV2, true};
|
||||
|
||||
CheckResult result = check(R"(
|
||||
--!strict
|
||||
|
|
|
@ -513,6 +513,23 @@ end
|
|||
assert(extramath3(2) == "number")
|
||||
assert(extramath3("2") == "number")
|
||||
|
||||
local function scopedrestorefailurea(format: string, b: buffer): (string, buffer)
|
||||
local H1F, H2F, H3F, H4F = buffer.readu32(b, 0), buffer.readu32(b, 8), buffer.readu32(b, 16), buffer.readu32(b, 24)
|
||||
local H5F, H6F, _, _ = buffer.readu32(b, 32), buffer.readu32(b, 40), buffer.readu32(b, 48), buffer.readu32(b, 56)
|
||||
local H1B, H2B, H3B, H4B = buffer.readu32(b, 4), buffer.readu32(b, 12), buffer.readu32(b, 20), buffer.readu32(b, 28)
|
||||
local H5B, H6B, _, _ = buffer.readu32(b, 36), buffer.readu32(b, 44), buffer.readu32(b, 52), buffer.readu32(b, 60)
|
||||
|
||||
return string.format(format, H1F, H1B, H2F, H2B, H3F, H3B, H4F, H4B, H5F, H5B, H6F, H6B), b
|
||||
end
|
||||
|
||||
local function scopedrestorefailureb()
|
||||
local data = buffer.create(64)
|
||||
buffer.fill(data, 0, 0x12, 64)
|
||||
assert(scopedrestorefailurea(string.rep("%08x", 12), data) == string.rep("12", 48))
|
||||
end
|
||||
|
||||
scopedrestorefailureb()
|
||||
|
||||
local function slotcachelimit1()
|
||||
local tbl = {
|
||||
f1 = function() return 1 end,
|
||||
|
|
Loading…
Add table
Reference in a new issue