Skip to content

Commit 994b641

Browse files
hgoldsteinvrn-snayoungbloodrbxmenarulalamAviral Goel
authored
Sync to upstream/release/699 (#2082)
Hello all! Another week, another release! # Analysis * Fixed `table.clone` in the old solver to ensure intersections of tables were being entirely cloned: prior only the _first_ table in the intersection would be copied: ```luau type FIRST = { some: string } type SECOND = FIRST & { thing: string } local b: SECOND -- c's type used to be FIRST, but should be the full type of SECOND local c = table.clone(b) ``` * Fixed `table.clone` in the old solver to be more permissive and treat a variadic return as having _at least_ one element. This works around some unfortunate behavior in the old solver version of nonstrict mode, see: ```luau -- A.luau --!nonstrict return function() return {} end -- B.luau local A = require("A") -- This line would previously error as `A` has type `() -> (...any)`, so -- we might not be providing enough parameters to `table.clone`. local _ = table.clone(A()) ``` * Fixed a bug in the new solver where error suppression was not kicking in for indexing, as in: ```luau local function f(value: any) if value ~= nil then for k = 1, #value do -- Previously this would error, claiming you cannot index into a `*error-type* | ~nil` local _ = value[k] end end end ``` * Fix the `getmetatable` type function in the new solver to accept `*error-type*` and `table` as valid type inputs. * Changed how error reporting for invalid `for ... in` loops works: for now this may result in slightly worse error messages (see the example below), but should mean error suppression is more consistent going forward: ```luau function my_iter(state: string, index: number) return state, index end local my_state = {} local first_index = "first" -- Prior we would claim `my_state` and `first_index` are of the incorrect types, -- now we claim that `my_iter` is of the incorrect type, which can be considered -- true, but is less helpful. for a, b in my_iter, my_state, first_index do end ``` # Runtime * Introduced `lua_rawgetptagged` and `lua_rawsetptagged`, as well as Lua 5.2+ compatibility macros `lua_rawgetp` and `lua_rawsetp`, to be able to perform lookups into tables using tagged or untagged `lightuserdata` without additional calls and stack manipulation. This enables a more efficient lookup way for `lightuserdata` keys similar to how `lua_rawgetfield` and `lua_rawgeti` avoid extra operations for their corresponding types. --- Co-authored-by: Andy Friesen <[email protected]> Co-authored-by: Annie Tang <[email protected]> Co-authored-by: Ariel Weiss <[email protected]> Co-authored-by: Hunter Goldstein <[email protected]> Co-authored-by: Varun Saini <[email protected]> Co-authored-by: Vyacheslav Egorov <[email protected]> --------- Co-authored-by: Varun Saini <[email protected]> Co-authored-by: Alexander Youngblood <[email protected]> Co-authored-by: Menarul Alam <[email protected]> Co-authored-by: Aviral Goel <[email protected]> Co-authored-by: Vighnesh <[email protected]> Co-authored-by: Vyacheslav Egorov <[email protected]> Co-authored-by: Ariel Weiss <[email protected]> Co-authored-by: Andy Friesen <[email protected]>
1 parent ff6d381 commit 994b641

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+585
-808
lines changed

Analysis/include/Luau/Frontend.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,6 @@ struct Frontend
228228
// If provided, 'executeTasks' function is allowed to call any item in 'tasks' on any thread and return without waiting for them to complete
229229
void queueModuleCheck(const std::vector<ModuleName>& names);
230230
void queueModuleCheck(const ModuleName& name);
231-
std::vector<ModuleName> checkQueuedModules_DEPRECATED(
232-
std::optional<FrontendOptions> optionOverride = {},
233-
std::function<void(std::function<void()> task)> executeTask = {},
234-
std::function<bool(size_t done, size_t total)> progress = {}
235-
);
236231
std::vector<ModuleName> checkQueuedModules(
237232
std::optional<FrontendOptions> optionOverride = {},
238233
std::function<void(std::vector<std::function<void()>> tasks)> executeTasks = {},
@@ -275,7 +270,6 @@ struct Frontend
275270
void checkBuildQueueItems(std::vector<BuildQueueItem>& items);
276271
void recordItemResult(const BuildQueueItem& item);
277272
void performQueueItemTask(std::shared_ptr<BuildQueueWorkState> state, size_t itemPos);
278-
void sendQueueItemTask_DEPRECATED(std::shared_ptr<BuildQueueWorkState> state, size_t itemPos);
279273
void sendQueueItemTasks(std::shared_ptr<BuildQueueWorkState> state, const std::vector<size_t>& items);
280274
void sendQueueCycleItemTask(std::shared_ptr<BuildQueueWorkState> state);
281275

Analysis/include/Luau/Instantiation.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#include "Luau/Unifiable.h"
88
#include "Luau/VisitType.h"
99

10-
LUAU_FASTFLAG(LuauExplicitSkipBoundTypes)
1110

1211
namespace Luau
1312
{
@@ -95,7 +94,7 @@ struct GenericTypeFinder : TypeOnceVisitor
9594
bool found = false;
9695

9796
GenericTypeFinder()
98-
: TypeOnceVisitor("GenericTypeFinder", FFlag::LuauExplicitSkipBoundTypes)
97+
: TypeOnceVisitor("GenericTypeFinder", /* skipBoundTypes */ true)
9998
{
10099
}
101100

Analysis/src/BuiltinDefinitions.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@
3232
*/
3333

3434
LUAU_FASTFLAG(LuauSolverV2)
35-
LUAU_FASTFLAGVARIABLE(LuauTableCloneClonesType3)
35+
LUAU_FASTFLAGVARIABLE(LuauTableCloneClonesType4)
3636
LUAU_FASTFLAG(LuauUseWorkspacePropToChooseSolver)
3737
LUAU_FASTFLAG(LuauEmplaceNotPushBack)
3838
LUAU_FASTFLAG(LuauBuiltinTypeFunctionsArentGlobal)
39+
LUAU_FASTFLAGVARIABLE(LuauCloneForIntersectionsUnions)
3940

4041
namespace Luau
4142
{
@@ -556,7 +557,7 @@ void registerBuiltinGlobals(Frontend& frontend, GlobalTypes& globals, bool typeC
556557
ttv->props["foreachi"].deprecated = true;
557558

558559
attachMagicFunction(*ttv->props["pack"].readTy, std::make_shared<MagicPack>());
559-
if (FFlag::LuauTableCloneClonesType3)
560+
if (FFlag::LuauTableCloneClonesType4)
560561
attachMagicFunction(*ttv->props["clone"].readTy, std::make_shared<MagicClone>());
561562
attachMagicFunction(*ttv->props["freeze"].readTy, std::make_shared<MagicFreeze>());
562563
}
@@ -1579,20 +1580,24 @@ bool MagicPack::infer(const MagicFunctionCallContext& context)
15791580
return true;
15801581
}
15811582

1583+
// ({+ +}) -> {+ +}
1584+
// <T: {}>(T) -> T
15821585
std::optional<WithPredicate<TypePackId>> MagicClone::handleOldSolver(
15831586
TypeChecker& typechecker,
15841587
const ScopePtr& scope,
15851588
const AstExprCall& expr,
15861589
WithPredicate<TypePackId> withPredicate
15871590
)
15881591
{
1589-
LUAU_ASSERT(FFlag::LuauTableCloneClonesType3);
1592+
LUAU_ASSERT(FFlag::LuauTableCloneClonesType4);
15901593

15911594
auto [paramPack, _predicates] = std::move(withPredicate);
15921595

15931596
TypeArena& arena = typechecker.currentModule->internalTypes;
15941597

1595-
const auto& [paramTypes, paramTail] = flatten(paramPack);
1598+
// in the old solver, nonstrict in particular is really bad about inferring `...any` for things that are definitely present
1599+
// and the only real way for us to deal with this is to just be more permissive here
1600+
const auto& [paramTypes, paramTail] = extendTypePack(arena, typechecker.builtinTypes, paramPack, 1);
15961601
if (paramTypes.empty() || expr.args.size == 0)
15971602
{
15981603
typechecker.reportError(expr.argLocation, CountMismatch{1, std::nullopt, 0});
@@ -1601,8 +1606,23 @@ std::optional<WithPredicate<TypePackId>> MagicClone::handleOldSolver(
16011606

16021607
TypeId inputType = follow(paramTypes[0]);
16031608

1604-
if (!get<TableType>(inputType))
1605-
return std::nullopt;
1609+
if (FFlag::LuauCloneForIntersectionsUnions)
1610+
{
1611+
if (!get<TableType>(inputType) && !get<IntersectionType>(inputType))
1612+
return std::nullopt;
1613+
1614+
if (auto intersectionTy = get<IntersectionType>(inputType))
1615+
{
1616+
for (auto ty : intersectionTy)
1617+
if (!get<TableType>(ty))
1618+
return std::nullopt;
1619+
}
1620+
}
1621+
else
1622+
{
1623+
if (!get<TableType>(inputType))
1624+
return std::nullopt;
1625+
}
16061626

16071627
CloneState cloneState{typechecker.builtinTypes};
16081628
TypeId resultType = shallowClone(inputType, arena, cloneState, /* clonePersistentTypes */ false);
@@ -1613,7 +1633,7 @@ std::optional<WithPredicate<TypePackId>> MagicClone::handleOldSolver(
16131633

16141634
bool MagicClone::infer(const MagicFunctionCallContext& context)
16151635
{
1616-
LUAU_ASSERT(FFlag::LuauTableCloneClonesType3);
1636+
LUAU_ASSERT(FFlag::LuauTableCloneClonesType4);
16171637

16181638
TypeArena* arena = context.solver->arena;
16191639

Analysis/src/BuiltinTypeFunctions.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ LUAU_FASTFLAG(LuauReduceSetTypeStackPressure)
2525
LUAU_FASTFLAGVARIABLE(LuauRefineNoRefineAlways)
2626
LUAU_FASTFLAGVARIABLE(LuauRefineDistributesOverUnions)
2727
LUAU_FASTFLAG(LuauEGFixGenericsList)
28-
LUAU_FASTFLAG(LuauExplicitSkipBoundTypes)
2928
LUAU_FASTFLAG(LuauNoMoreComparisonTypeFunctions)
3029
LUAU_FASTFLAGVARIABLE(LuauBuiltinTypeFunctionsArentGlobal)
3130
LUAU_FASTFLAG(LuauPassBindableGenericsByReference)
3231
LUAU_FASTFLAG(LuauEnqueueUnionsOfDistributedTypeFunctions)
32+
LUAU_FASTFLAGVARIABLE(LuauGetmetatableError)
3333

3434
namespace Luau
3535
{
@@ -1062,7 +1062,7 @@ struct FindRefinementBlockers : TypeOnceVisitor
10621062
DenseHashSet<TypeId> found{nullptr};
10631063

10641064
FindRefinementBlockers()
1065-
: TypeOnceVisitor("FindRefinementBlockers", FFlag::LuauExplicitSkipBoundTypes)
1065+
: TypeOnceVisitor("FindRefinementBlockers", /* skipBoundTypes */ true)
10661066
{
10671067
}
10681068

@@ -2489,7 +2489,16 @@ static TypeFunctionReductionResult<TypeId> getmetatableHelper(TypeId targetTy, c
24892489

24902490
if (auto primitive = get<PrimitiveType>(targetTy))
24912491
{
2492-
result = primitive->metatable;
2492+
if (FFlag::LuauGetmetatableError && primitive->type == PrimitiveType::Table)
2493+
{
2494+
// If we have `table` then we could have something with a
2495+
// metatable, so claim the result is `table?`.
2496+
result = ctx->arena->addType(UnionType{{ctx->builtins->tableType, ctx->builtins->nilType}});
2497+
}
2498+
else
2499+
{
2500+
result = primitive->metatable;
2501+
}
24932502
erroneous = false;
24942503
}
24952504

@@ -2510,6 +2519,13 @@ static TypeFunctionReductionResult<TypeId> getmetatableHelper(TypeId targetTy, c
25102519
erroneous = false;
25112520
}
25122521

2522+
if (FFlag::LuauGetmetatableError && get<ErrorType>(targetTy))
2523+
{
2524+
// getmetatable<error> ~ error
2525+
result = targetTy;
2526+
erroneous = false;
2527+
}
2528+
25132529
if (erroneous)
25142530
return {std::nullopt, Reduction::Erroneous, {}, {}};
25152531

Analysis/src/Clone.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "Luau/Type.h"
77
#include "Luau/TypeOrPack.h"
88
#include "Luau/TypePack.h"
9+
#include "Luau/TypeUtils.h"
910
#include "Luau/Unifiable.h"
1011
#include "Luau/VisitType.h"
1112

Analysis/src/Constraint.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include "Luau/TypeFunction.h"
55
#include "Luau/VisitType.h"
66

7-
LUAU_FASTFLAGVARIABLE(LuauExplicitSkipBoundTypes)
87
LUAU_FASTFLAG(LuauNoOrderingTypeFunctions)
98

109
namespace Luau
@@ -23,7 +22,7 @@ struct ReferenceCountInitializer : TypeOnceVisitor
2322
bool traverseIntoTypeFunctions = true;
2423

2524
explicit ReferenceCountInitializer(NotNull<TypeIds> result)
26-
: TypeOnceVisitor("ReferenceCountInitializer", FFlag::LuauExplicitSkipBoundTypes)
25+
: TypeOnceVisitor("ReferenceCountInitializer", /* skipBoundTypes */ true)
2726
, result(result)
2827
{
2928
}

Analysis/src/ConstraintGenerator.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ LUAU_FASTFLAG(DebugLuauMagicTypes)
4040
LUAU_FASTINTVARIABLE(LuauPrimitiveInferenceInTableLimit, 500)
4141
LUAU_FASTFLAG(LuauEmplaceNotPushBack)
4242
LUAU_FASTFLAG(LuauReduceSetTypeStackPressure)
43-
LUAU_FASTFLAG(LuauExplicitSkipBoundTypes)
4443
LUAU_FASTFLAG(DebugLuauStringSingletonBasedOnQuotes)
45-
LUAU_FASTFLAGVARIABLE(LuauInstantiateResolvedTypeFunctions)
4644
LUAU_FASTFLAGVARIABLE(LuauPushTypeConstraint2)
4745
LUAU_FASTFLAGVARIABLE(LuauEGFixGenericsList)
4846
LUAU_FASTFLAGVARIABLE(LuauNumericUnaryOpsDontProduceNegationRefinements)
@@ -145,7 +143,7 @@ struct HasFreeType : TypeOnceVisitor
145143
bool result = false;
146144

147145
HasFreeType()
148-
: TypeOnceVisitor("TypeOnceVisitor", FFlag::LuauExplicitSkipBoundTypes)
146+
: TypeOnceVisitor("TypeOnceVisitor", /* skipBoundTypes */ true)
149147
{
150148
}
151149

@@ -619,7 +617,7 @@ struct FindSimplificationBlockers : TypeOnceVisitor
619617
bool found = false;
620618

621619
FindSimplificationBlockers()
622-
: TypeOnceVisitor("FindSimplificationBlockers", FFlag::LuauExplicitSkipBoundTypes)
620+
: TypeOnceVisitor("FindSimplificationBlockers", /* skipBoundTypes */ true)
623621
{
624622
}
625623

@@ -4096,16 +4094,12 @@ TypeId ConstraintGenerator::resolveReferenceType(
40964094
result = freshType(scope, Polarity::Mixed);
40974095
}
40984096

4099-
if (FFlag::LuauInstantiateResolvedTypeFunctions)
4097+
if (is<TypeFunctionInstanceType>(follow(result)))
41004098
{
4101-
if (is<TypeFunctionInstanceType>(follow(result)))
4102-
{
4103-
reportError(ty->location, UnappliedTypeFunction{});
4104-
addConstraint(scope, ty->location, ReduceConstraint{result});
4105-
}
4099+
reportError(ty->location, UnappliedTypeFunction{});
4100+
addConstraint(scope, ty->location, ReduceConstraint{result});
41064101
}
41074102

4108-
41094103
return result;
41104104
}
41114105

Analysis/src/ConstraintSolver.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ LUAU_FASTFLAGVARIABLE(LuauCollapseShouldNotCrash)
4444
LUAU_FASTFLAGVARIABLE(LuauDontDynamicallyCreateRedundantSubtypeConstraints)
4545
LUAU_FASTFLAGVARIABLE(LuauExtendSealedTableUpperBounds)
4646
LUAU_FASTFLAG(LuauReduceSetTypeStackPressure)
47-
LUAU_FASTFLAG(LuauExplicitSkipBoundTypes)
4847
LUAU_FASTFLAG(DebugLuauStringSingletonBasedOnQuotes)
4948
LUAU_FASTFLAG(LuauPushTypeConstraint2)
5049
LUAU_FASTFLAGVARIABLE(LuauScopedSeenSetInLookupTableProp)
@@ -341,7 +340,7 @@ struct InfiniteTypeFinder : TypeOnceVisitor
341340
bool foundInfiniteType = false;
342341

343342
explicit InfiniteTypeFinder(ConstraintSolver* solver, const InstantiationSignature& signature, NotNull<Scope> scope)
344-
: TypeOnceVisitor("InfiniteTypeFinder", FFlag::LuauExplicitSkipBoundTypes)
343+
: TypeOnceVisitor("InfiniteTypeFinder", /* skipBoundTypes */ true)
345344
, solver(solver)
346345
, signature(signature)
347346
, scope(scope)
@@ -670,7 +669,7 @@ struct TypeSearcher : TypeVisitor
670669
}
671670

672671
explicit TypeSearcher(TypeId needle, Polarity initialPolarity)
673-
: TypeVisitor("TypeSearcher", FFlag::LuauExplicitSkipBoundTypes)
672+
: TypeVisitor("TypeSearcher", /* skipBoundTypes */ true)
674673
, needle(needle)
675674
, current(initialPolarity)
676675
{
@@ -1635,7 +1634,7 @@ struct ContainsGenerics : public TypeOnceVisitor
16351634
NotNull<DenseHashSet<const void*>> generics;
16361635

16371636
explicit ContainsGenerics(NotNull<DenseHashSet<const void*>> generics)
1638-
: TypeOnceVisitor("ContainsGenerics", FFlag::LuauExplicitSkipBoundTypes)
1637+
: TypeOnceVisitor("ContainsGenerics", /* skipBoundTypes */ true)
16391638
, generics{generics}
16401639
{
16411640
}
@@ -2149,7 +2148,7 @@ struct BlockedTypeFinder : TypeOnceVisitor
21492148
std::optional<TypeId> blocked;
21502149

21512150
BlockedTypeFinder()
2152-
: TypeOnceVisitor("ContainsGenerics_DEPRECATED", FFlag::LuauExplicitSkipBoundTypes)
2151+
: TypeOnceVisitor("ContainsGenerics_DEPRECATED", /* skipBoundTypes */ true)
21532152
{
21542153
}
21552154

@@ -3521,7 +3520,7 @@ struct Blocker : TypeOnceVisitor
35213520
bool blocked = false;
35223521

35233522
explicit Blocker(NotNull<ConstraintSolver> solver, NotNull<const Constraint> constraint)
3524-
: TypeOnceVisitor("Blocker", FFlag::LuauExplicitSkipBoundTypes)
3523+
: TypeOnceVisitor("Blocker", /* skipBoundTypes */ true)
35253524
, solver(solver)
35263525
, constraint(constraint)
35273526
{

Analysis/src/Error.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ LUAU_FASTINTVARIABLE(LuauIndentTypeMismatchMaxTypeLength, 10)
2020

2121
LUAU_FASTFLAGVARIABLE(LuauNewNonStrictReportsOneIndexedErrors)
2222
LUAU_FASTFLAG(LuauSubtypingReportGenericBoundMismatches2)
23+
LUAU_FASTFLAG(LuauUnknownGlobalFixSuggestion)
2324
LUAU_FASTFLAGVARIABLE(LuauNewNonStrictBetterCheckedFunctionErrorMessage)
2425

2526
static std::string wrongNumberOfArgsString(
@@ -172,7 +173,8 @@ struct ErrorConverter
172173
switch (e.context)
173174
{
174175
case UnknownSymbol::Binding:
175-
return "Unknown global '" + e.name + "'";
176+
return FFlag::LuauUnknownGlobalFixSuggestion ? "Unknown global '" + e.name + "'; consider assigning to it first"
177+
: "Unknown global '" + e.name + "'";
176178
case UnknownSymbol::Type:
177179
return "Unknown type '" + e.name + "'";
178180
}

0 commit comments

Comments
 (0)