Skip to content

Commit c2e7266

Browse files
vegorov-rbxhgoldsteinTalha Pathanvrn-snVighnesh-V
authored
Sync to upstream/release/662 (#1681)
## What's new This update brings improvements to the new type solver, roundtrippable AST parsing mode and closes multiple issues reported in this repository. * `require` dependency tracing for non-string requires now supports `()` groups in expressions and types as well as an ability to type annotate a value with a `typeof` of a different module path * Fixed rare misaligned memory access in Compiler/Typechecker on 32 bit platforms (Closes #1572) ## New Solver * Fixed crash/UB in subtyping of type packs (Closes #1449) * Fixed incorrect type errors when calling `debug.info` (Closes #1534 and Resolves #966) * Fixed incorrect boolean and string equality comparison result in user-defined type functions (Closes #1623) * Fixed incorrect class types being produced in user-defined type functions when multiple classes share the same name (Closes #1639) * Improved bidirectional typechecking for table literals containing elements that have not been solved yet (Closes #1641) ## Roundtrippable AST * Added source information for `AstStatTypeAlias` * Fixed an issue with `AstTypeGroup` node (added in #1643) producing invalid AST json. Contained type is now named 'inner' instead of 'type' * Fixed end location of the `do ... end` statement --- Internal Contributors: Co-authored-by: Hunter Goldstein <[email protected]> Co-authored-by: Talha Pathan <[email protected]> Co-authored-by: Varun Saini <[email protected]> Co-authored-by: Vighnesh Vijay <[email protected]> Co-authored-by: Vyacheslav Egorov <[email protected]>
1 parent 86bf4ae commit c2e7266

Some content is hidden

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

51 files changed

+1047
-290
lines changed

Analysis/include/Luau/Constraint.h

+17-1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,21 @@ struct FunctionCheckConstraint
109109
NotNull<DenseHashMap<const AstExpr*, TypeId>> astExpectedTypes;
110110
};
111111

112+
// table_check expectedType exprType
113+
//
114+
// If `expectedType` is a table type and `exprType` is _also_ a table type,
115+
// propogate the member types of `expectedType` into the types of `exprType`.
116+
// This is used to implement bidirectional inference on table assignment.
117+
// Also see: FunctionCheckConstraint.
118+
struct TableCheckConstraint
119+
{
120+
TypeId expectedType;
121+
TypeId exprType;
122+
AstExprTable* table = nullptr;
123+
NotNull<DenseHashMap<const AstExpr*, TypeId>> astTypes;
124+
NotNull<DenseHashMap<const AstExpr*, TypeId>> astExpectedTypes;
125+
};
126+
112127
// prim FreeType ExpectedType PrimitiveType
113128
//
114129
// FreeType is bounded below by the singleton type and above by PrimitiveType
@@ -273,7 +288,8 @@ using ConstraintV = Variant<
273288
UnpackConstraint,
274289
ReduceConstraint,
275290
ReducePackConstraint,
276-
EqualityConstraint>;
291+
EqualityConstraint,
292+
TableCheckConstraint>;
277293

278294
struct Constraint
279295
{

Analysis/include/Luau/ConstraintSolver.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ struct ConstraintSolver
118118
// A mapping from free types to the number of unresolved constraints that mention them.
119119
DenseHashMap<TypeId, size_t> unresolvedConstraints{{}};
120120

121+
std::unordered_map<NotNull<const Constraint>, DenseHashSet<TypeId>> maybeMutatedFreeTypes;
122+
121123
// Irreducible/uninhabited type functions or type pack functions.
122124
DenseHashSet<const void*> uninhabitedTypeFunctions{{}};
123125

@@ -201,6 +203,7 @@ struct ConstraintSolver
201203
bool tryDispatch(const NameConstraint& c, NotNull<const Constraint> constraint);
202204
bool tryDispatch(const TypeAliasExpansionConstraint& c, NotNull<const Constraint> constraint);
203205
bool tryDispatch(const FunctionCallConstraint& c, NotNull<const Constraint> constraint);
206+
bool tryDispatch(const TableCheckConstraint& c, NotNull<const Constraint> constraint);
204207
bool tryDispatch(const FunctionCheckConstraint& c, NotNull<const Constraint> constraint);
205208
bool tryDispatch(const PrimitiveTypeConstraint& c, NotNull<const Constraint> constraint);
206209
bool tryDispatch(const HasPropConstraint& c, NotNull<const Constraint> constraint);
@@ -421,10 +424,7 @@ struct ConstraintSolver
421424

422425
ToStringOptions opts;
423426

424-
void fillInDiscriminantTypes(
425-
NotNull<const Constraint> constraint,
426-
const std::vector<std::optional<TypeId>>& discriminantTypes
427-
);
427+
void fillInDiscriminantTypes(NotNull<const Constraint> constraint, const std::vector<std::optional<TypeId>>& discriminantTypes);
428428
};
429429

430430
void dump(NotNull<Scope> rootScope, struct ToStringOptions& opts);

Analysis/include/Luau/EqSatSimplificationImpl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ struct TTable
105105
std::vector<Id> storage;
106106
};
107107

108-
template <typename L>
108+
template<typename L>
109109
using Node = EqSat::Node<L>;
110110

111111
using EType = EqSat::Language<

Analysis/include/Luau/RequireTracer.h

+2-4
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@
1111
namespace Luau
1212
{
1313

14-
class AstStat;
15-
class AstExpr;
14+
class AstNode;
1615
class AstStatBlock;
17-
struct AstLocal;
1816

1917
struct RequireTraceResult
2018
{
21-
DenseHashMap<const AstExpr*, ModuleInfo> exprs{nullptr};
19+
DenseHashMap<const AstNode*, ModuleInfo> exprs{nullptr};
2220

2321
std::vector<std::pair<ModuleName, Location>> requireList;
2422
};

Analysis/include/Luau/Type.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ struct MagicFunctionTypeCheckContext
310310

311311
struct MagicFunction
312312
{
313-
virtual std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) = 0;
313+
virtual std::optional<WithPredicate<TypePackId>>
314+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) = 0;
314315

315316
// Callback to allow custom typechecking of builtin function calls whose argument types
316317
// will only be resolved after constraint solving. For example, the arguments to string.format

Analysis/include/Luau/TypeFunctionRuntime.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "Luau/Common.h"
55
#include "Luau/Variant.h"
6+
#include "Luau/TypeFwd.h"
67

78
#include <optional>
89
#include <string>
@@ -217,7 +218,9 @@ struct TypeFunctionClassType
217218

218219
std::optional<TypeFunctionTypeId> parent;
219220

220-
std::string name;
221+
TypeId classTy;
222+
223+
std::string name_DEPRECATED;
221224
};
222225

223226
struct TypeFunctionGenericType

Analysis/include/Luau/TypeFunctionRuntimeBuilder.h

+1-3
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,14 @@ struct TypeFunctionRuntimeBuilderState
3232
// Invariant: users can not create a new class types -> any class types that get deserialized must have been an argument to the type function
3333
// Using this invariant, whenever a ClassType is serialized, we can put it into this map
3434
// whenever a ClassType is deserialized, we can use this map to return the corresponding value
35-
DenseHashMap<std::string, TypeId> classesSerialized{{}};
35+
DenseHashMap<std::string, TypeId> classesSerialized_DEPRECATED{{}};
3636

3737
// List of errors that occur during serialization/deserialization
3838
// At every iteration of serialization/deserialzation, if this list.size() != 0, we halt the process
3939
std::vector<std::string> errors{};
4040

4141
TypeFunctionRuntimeBuilderState(NotNull<TypeFunctionContext> ctx)
4242
: ctx(ctx)
43-
, classesSerialized({})
44-
, errors({})
4543
{
4644
}
4745
};

Analysis/include/Luau/UnifierSharedState.h

-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ struct UnifierSharedState
5151
UnifierCounters counters;
5252

5353
bool reentrantTypeReduction = false;
54-
5554
};
5655

5756
struct TypeReductionRentrancyGuard final

Analysis/src/AstJsonEncoder.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1168,7 +1168,7 @@ struct AstJsonEncoder : public AstVisitor
11681168
"AstTypeGroup",
11691169
[&]()
11701170
{
1171-
write("type", node->type);
1171+
write("inner", node->type);
11721172
}
11731173
);
11741174
return false;

Analysis/src/AutocompleteCore.cpp

+2-6
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include <utility>
2121

2222
LUAU_FASTFLAG(LuauSolverV2)
23-
LUAU_FASTFLAGVARIABLE(AutocompleteRequirePathSuggestions2)
2423
LUAU_FASTINT(LuauTypeInferIterationLimit)
2524
LUAU_FASTINT(LuauTypeInferRecursionLimit)
2625

@@ -1521,12 +1520,9 @@ static std::optional<AutocompleteEntryMap> autocompleteStringParams(
15211520
{
15221521
for (const std::string& tag : funcType->tags)
15231522
{
1524-
if (FFlag::AutocompleteRequirePathSuggestions2)
1523+
if (tag == kRequireTagName && fileResolver)
15251524
{
1526-
if (tag == kRequireTagName && fileResolver)
1527-
{
1528-
return convertRequireSuggestionsToAutocompleteEntryMap(fileResolver->getRequireSuggestions(module->name, candidateString));
1529-
}
1525+
return convertRequireSuggestionsToAutocompleteEntryMap(fileResolver->getRequireSuggestions(module->name, candidateString));
15301526
}
15311527
if (std::optional<AutocompleteEntryMap> ret = callback(tag, getMethodContainingClass(module, candidate->func), candidateString))
15321528
{

Analysis/src/BuiltinDefinitions.cpp

+36-32
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030

3131
LUAU_FASTFLAG(LuauSolverV2)
3232
LUAU_FASTFLAGVARIABLE(LuauStringFormatErrorSuppression)
33-
LUAU_FASTFLAG(AutocompleteRequirePathSuggestions2)
3433
LUAU_FASTFLAGVARIABLE(LuauTableCloneClonesType3)
3534
LUAU_FASTFLAG(LuauTrackInteriorFreeTypesOnScope)
3635
LUAU_FASTFLAGVARIABLE(LuauFreezeIgnorePersistent)
@@ -41,68 +40,79 @@ namespace Luau
4140

4241
struct MagicSelect final : MagicFunction
4342
{
44-
std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
43+
std::optional<WithPredicate<TypePackId>>
44+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
4545
bool infer(const MagicFunctionCallContext& ctx) override;
4646
};
4747

4848
struct MagicSetMetatable final : MagicFunction
4949
{
50-
std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
50+
std::optional<WithPredicate<TypePackId>>
51+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
5152
bool infer(const MagicFunctionCallContext& ctx) override;
5253
};
5354

5455
struct MagicAssert final : MagicFunction
5556
{
56-
std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
57+
std::optional<WithPredicate<TypePackId>>
58+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
5759
bool infer(const MagicFunctionCallContext& ctx) override;
5860
};
5961

6062
struct MagicPack final : MagicFunction
6163
{
62-
std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
64+
std::optional<WithPredicate<TypePackId>>
65+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
6366
bool infer(const MagicFunctionCallContext& ctx) override;
6467
};
6568

6669
struct MagicRequire final : MagicFunction
6770
{
68-
std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
71+
std::optional<WithPredicate<TypePackId>>
72+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
6973
bool infer(const MagicFunctionCallContext& ctx) override;
7074
};
7175

7276
struct MagicClone final : MagicFunction
7377
{
74-
std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
78+
std::optional<WithPredicate<TypePackId>>
79+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
7580
bool infer(const MagicFunctionCallContext& ctx) override;
7681
};
7782

7883
struct MagicFreeze final : MagicFunction
7984
{
80-
std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
85+
std::optional<WithPredicate<TypePackId>>
86+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
8187
bool infer(const MagicFunctionCallContext& ctx) override;
8288
};
8389

8490
struct MagicFormat final : MagicFunction
8591
{
86-
std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
92+
std::optional<WithPredicate<TypePackId>>
93+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
8794
bool infer(const MagicFunctionCallContext& ctx) override;
8895
bool typeCheck(const MagicFunctionTypeCheckContext& ctx) override;
8996
};
9097

9198
struct MagicMatch final : MagicFunction
9299
{
93-
std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
100+
std::optional<WithPredicate<TypePackId>>
101+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
94102
bool infer(const MagicFunctionCallContext& ctx) override;
95103
};
96104

97105
struct MagicGmatch final : MagicFunction
98106
{
99-
std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
107+
std::optional<WithPredicate<TypePackId>>
108+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
100109
bool infer(const MagicFunctionCallContext& ctx) override;
101110
};
102111

103112
struct MagicFind final : MagicFunction
104113
{
105-
std::optional<WithPredicate<TypePackId>> handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
114+
std::optional<WithPredicate<TypePackId>>
115+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>) override;
106116
bool infer(const MagicFunctionCallContext& ctx) override;
107117
};
108118

@@ -454,16 +464,9 @@ void registerBuiltinGlobals(Frontend& frontend, GlobalTypes& globals, bool typeC
454464
attachMagicFunction(ttv->props["freeze"].type(), std::make_shared<MagicFreeze>());
455465
}
456466

457-
if (FFlag::AutocompleteRequirePathSuggestions2)
458-
{
459-
TypeId requireTy = getGlobalBinding(globals, "require");
460-
attachTag(requireTy, kRequireTagName);
461-
attachMagicFunction(requireTy, std::make_shared<MagicRequire>());
462-
}
463-
else
464-
{
465-
attachMagicFunction(getGlobalBinding(globals, "require"), std::make_shared<MagicRequire>());
466-
}
467+
TypeId requireTy = getGlobalBinding(globals, "require");
468+
attachTag(requireTy, kRequireTagName);
469+
attachMagicFunction(requireTy, std::make_shared<MagicRequire>());
467470
}
468471

469472
static std::vector<TypeId> parseFormatString(NotNull<BuiltinTypes> builtinTypes, const char* data, size_t size)
@@ -637,15 +640,15 @@ bool MagicFormat::typeCheck(const MagicFunctionTypeCheckContext& context)
637640
{
638641
switch (shouldSuppressErrors(NotNull{&context.typechecker->normalizer}, actualTy))
639642
{
640-
case ErrorSuppression::Suppress:
641-
break;
642-
case ErrorSuppression::NormalizationFailed:
643-
break;
644-
case ErrorSuppression::DoNotSuppress:
645-
Reasonings reasonings = context.typechecker->explainReasonings(actualTy, expectedTy, location, result);
646-
647-
if (!reasonings.suppressed)
648-
context.typechecker->reportError(TypeMismatch{expectedTy, actualTy, reasonings.toString()}, location);
643+
case ErrorSuppression::Suppress:
644+
break;
645+
case ErrorSuppression::NormalizationFailed:
646+
break;
647+
case ErrorSuppression::DoNotSuppress:
648+
Reasonings reasonings = context.typechecker->explainReasonings(actualTy, expectedTy, location, result);
649+
650+
if (!reasonings.suppressed)
651+
context.typechecker->reportError(TypeMismatch{expectedTy, actualTy, reasonings.toString()}, location);
649652
}
650653
}
651654
else
@@ -1503,7 +1506,8 @@ static std::optional<TypeId> freezeTable(TypeId inputType, const MagicFunctionCa
15031506
return std::nullopt;
15041507
}
15051508

1506-
std::optional<WithPredicate<TypePackId>> MagicFreeze::handleOldSolver(struct TypeChecker &, const std::shared_ptr<struct Scope> &, const class AstExprCall &, WithPredicate<TypePackId>)
1509+
std::optional<WithPredicate<TypePackId>> MagicFreeze::
1510+
handleOldSolver(struct TypeChecker&, const std::shared_ptr<struct Scope>&, const class AstExprCall&, WithPredicate<TypePackId>)
15071511
{
15081512
return std::nullopt;
15091513
}

Analysis/src/Constraint.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
146146
{
147147
rci.traverse(rpc->tp);
148148
}
149+
else if (auto tcc = get<TableCheckConstraint>(*this))
150+
{
151+
rci.traverse(tcc->exprType);
152+
}
149153

150154
return types;
151155
}

0 commit comments

Comments
 (0)