Skip to content

Commit 0fa6a51

Browse files
andyfriesenaatxealexmccordAviral GoelVighnesh-V
authored
Sync to upstream/release/629 (#1290)
### What's new * Implemented parsing logic for attributes * Added `lua_setuserdatametatable` and `lua_getuserdatametatable` C API methods for a faster userdata metatable fetch compared to `luaL_getmetatable`. Note that metatable reference has to still be pinned in memory! ### New Solver * Further improvement to the assignment inference logic * Fix many bugs surrounding constraint dispatch order ### Native Codegen * Add IR lowering hooks for custom host userdata types * Add IR to create new tagged userdata objects * Remove outdated NativeState --- ### Internal Contributors Co-authored-by: Aaron Weiss <aaronweiss@roblox.com> Co-authored-by: Alexander McCord <amccord@roblox.com> Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: Vighnesh Vijay <vvijay@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com>
1 parent 81b2cc7 commit 0fa6a51

Some content is hidden

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

68 files changed

+2711
-686
lines changed

Analysis/include/Luau/Constraint.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct GeneralizationConstraint
5757
struct IterableConstraint
5858
{
5959
TypePackId iterator;
60-
TypePackId variables;
60+
std::vector<TypeId> variables;
6161

6262
const AstNode* nextAstFragment;
6363
DenseHashMap<const AstNode*, TypeId>* astForInNextTypes;
@@ -192,13 +192,7 @@ struct HasIndexerConstraint
192192
TypeId indexType;
193193
};
194194

195-
struct AssignConstraint
196-
{
197-
TypeId lhsType;
198-
TypeId rhsType;
199-
};
200-
201-
// assign lhsType propName rhsType
195+
// assignProp lhsType propName rhsType
202196
//
203197
// Assign a value of type rhsType into the named property of lhsType.
204198

@@ -212,6 +206,12 @@ struct AssignPropConstraint
212206
/// populate astTypes during constraint resolution. Nothing should ever
213207
/// block on it.
214208
TypeId propType;
209+
210+
// When we generate constraints, we increment the remaining prop count on
211+
// the table if we are able. This flag informs the solver as to whether or
212+
// not it should in turn decrement the prop count when this constraint is
213+
// dispatched.
214+
bool decrementPropCount = false;
215215
};
216216

217217
struct AssignIndexConstraint
@@ -226,13 +226,13 @@ struct AssignIndexConstraint
226226
TypeId propType;
227227
};
228228

229-
// resultType ~ unpack sourceTypePack
229+
// resultTypes ~ unpack sourceTypePack
230230
//
231231
// Similar to PackSubtypeConstraint, but with one important difference: If the
232232
// sourcePack is blocked, this constraint blocks.
233233
struct UnpackConstraint
234234
{
235-
TypePackId resultPack;
235+
std::vector<TypeId> resultPack;
236236
TypePackId sourcePack;
237237
};
238238

@@ -254,7 +254,7 @@ struct ReducePackConstraint
254254

255255
using ConstraintV = Variant<SubtypeConstraint, PackSubtypeConstraint, GeneralizationConstraint, IterableConstraint, NameConstraint,
256256
TypeAliasExpansionConstraint, FunctionCallConstraint, FunctionCheckConstraint, PrimitiveTypeConstraint, HasPropConstraint, HasIndexerConstraint,
257-
AssignConstraint, AssignPropConstraint, AssignIndexConstraint, UnpackConstraint, ReduceConstraint, ReducePackConstraint, EqualityConstraint>;
257+
AssignPropConstraint, AssignIndexConstraint, UnpackConstraint, ReduceConstraint, ReducePackConstraint, EqualityConstraint>;
258258

259259
struct Constraint
260260
{

Analysis/include/Luau/ConstraintGenerator.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ struct ConstraintGenerator
118118
std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope;
119119
std::vector<RequireCycle> requireCycles;
120120

121+
DenseHashMap<TypeId, std::vector<TypeId>> localTypes{nullptr};
122+
121123
DcrLogger* logger;
122124

123125
ConstraintGenerator(ModulePtr module, NotNull<Normalizer> normalizer, NotNull<ModuleResolver> moduleResolver, NotNull<BuiltinTypes> builtinTypes,
@@ -354,6 +356,8 @@ struct ConstraintGenerator
354356
*/
355357
void prepopulateGlobalScope(const ScopePtr& globalScope, AstStatBlock* program);
356358

359+
bool recordPropertyAssignment(TypeId ty);
360+
357361
// Record the fact that a particular local has a particular type in at least
358362
// one of its states.
359363
void recordInferredBinding(AstLocal* local, TypeId ty);

Analysis/include/Luau/ConstraintSolver.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ struct ConstraintSolver
142142
std::pair<bool, std::optional<TypeId>> tryDispatchSetIndexer(
143143
NotNull<const Constraint> constraint, TypeId subjectType, TypeId indexType, TypeId propType, bool expandFreeTypeBounds);
144144

145-
bool tryDispatch(const AssignConstraint& c, NotNull<const Constraint> constraint);
146145
bool tryDispatch(const AssignPropConstraint& c, NotNull<const Constraint> constraint);
147146
bool tryDispatch(const AssignIndexConstraint& c, NotNull<const Constraint> constraint);
148147

@@ -158,8 +157,7 @@ struct ConstraintSolver
158157
bool tryDispatchIterableTable(TypeId iteratorTy, const IterableConstraint& c, NotNull<const Constraint> constraint, bool force);
159158

160159
// for a, ... in next_function, t, ... do
161-
bool tryDispatchIterableFunction(
162-
TypeId nextTy, TypeId tableTy, TypeId firstIndexTy, const IterableConstraint& c, NotNull<const Constraint> constraint, bool force);
160+
bool tryDispatchIterableFunction(TypeId nextTy, TypeId tableTy, const IterableConstraint& c, NotNull<const Constraint> constraint, bool force);
163161

164162
std::pair<std::vector<TypeId>, std::optional<TypeId>> lookupTableProp(NotNull<const Constraint> constraint, TypeId subjectType,
165163
const std::string& propName, ValueContext context, bool inConditional = false, bool suppressSimplification = false);
@@ -168,14 +166,18 @@ struct ConstraintSolver
168166

169167
/**
170168
* Generate constraints to unpack the types of srcTypes and assign each
171-
* value to the corresponding LocalType in destTypes.
169+
* value to the corresponding BlockedType in destTypes.
172170
*
173-
* @param destTypes A finite TypePack comprised of LocalTypes.
171+
* This function also overwrites the owners of each BlockedType. This is
172+
* okay because this function is only used to decompose IterableConstraint
173+
* into an UnpackConstraint.
174+
*
175+
* @param destTypes A vector of types comprised of BlockedTypes.
174176
* @param srcTypes A TypePack that represents rvalues to be assigned.
175177
* @returns The underlying UnpackConstraint. There's a bit of code in
176178
* iteration that needs to pass blocks on to this constraint.
177179
*/
178-
NotNull<const Constraint> unpackAndAssign(TypePackId destTypes, TypePackId srcTypes, NotNull<const Constraint> constraint);
180+
NotNull<const Constraint> unpackAndAssign(const std::vector<TypeId> destTypes, TypePackId srcTypes, NotNull<const Constraint> constraint);
179181

180182
void block(NotNull<const Constraint> target, NotNull<const Constraint> constraint);
181183
/**

Analysis/include/Luau/Type.h

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,24 +86,6 @@ struct FreeType
8686
TypeId upperBound = nullptr;
8787
};
8888

89-
/** A type that tracks the domain of a local variable.
90-
*
91-
* We consider each local's domain to be the union of all types assigned to it.
92-
* We accomplish this with LocalType. Each time we dispatch an assignment to a
93-
* local, we accumulate this union and decrement blockCount.
94-
*
95-
* When blockCount reaches 0, we can consider the LocalType to be "fully baked"
96-
* and replace it with the union we've built.
97-
*/
98-
struct LocalType
99-
{
100-
TypeId domain;
101-
int blockCount = 0;
102-
103-
// Used for debugging
104-
std::string name;
105-
};
106-
10789
struct GenericType
10890
{
10991
// By default, generics are global, with a synthetic name
@@ -148,6 +130,7 @@ struct BlockedType
148130

149131
Constraint* getOwner() const;
150132
void setOwner(Constraint* newOwner);
133+
void replaceOwner(Constraint* newOwner);
151134

152135
private:
153136
// The constraint that is intended to unblock this type. Other constraints
@@ -471,6 +454,11 @@ struct TableType
471454

472455
// Methods of this table that have an untyped self will use the same shared self type.
473456
std::optional<TypeId> selfTy;
457+
458+
// We track the number of as-yet-unadded properties to unsealed tables.
459+
// Some constraints will use this information to decide whether or not they
460+
// are able to dispatch.
461+
size_t remainingProps = 0;
474462
};
475463

476464
// Represents a metatable attached to a table type. Somewhat analogous to a bound type.
@@ -669,9 +657,9 @@ struct NegationType
669657

670658
using ErrorType = Unifiable::Error;
671659

672-
using TypeVariant = Unifiable::Variant<TypeId, FreeType, LocalType, GenericType, PrimitiveType, BlockedType, PendingExpansionType, SingletonType,
673-
FunctionType, TableType, MetatableType, ClassType, AnyType, UnionType, IntersectionType, LazyType, UnknownType, NeverType, NegationType,
674-
TypeFamilyInstanceType>;
660+
using TypeVariant =
661+
Unifiable::Variant<TypeId, FreeType, GenericType, PrimitiveType, BlockedType, PendingExpansionType, SingletonType, FunctionType, TableType,
662+
MetatableType, ClassType, AnyType, UnionType, IntersectionType, LazyType, UnknownType, NeverType, NegationType, TypeFamilyInstanceType>;
675663

676664
struct Type final
677665
{

Analysis/include/Luau/Unifier2.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ struct Unifier2
6969
*/
7070
bool unify(TypeId subTy, TypeId superTy);
7171
bool unifyFreeWithType(TypeId subTy, TypeId superTy);
72-
bool unify(const LocalType* subTy, TypeId superFn);
7372
bool unify(TypeId subTy, const FunctionType* superFn);
7473
bool unify(const UnionType* subUnion, TypeId superTy);
7574
bool unify(TypeId subTy, const UnionType* superUnion);

Analysis/include/Luau/VisitType.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,6 @@ struct GenericTypeVisitor
100100
{
101101
return visit(ty);
102102
}
103-
virtual bool visit(TypeId ty, const LocalType& ftv)
104-
{
105-
return visit(ty);
106-
}
107103
virtual bool visit(TypeId ty, const GenericType& gtv)
108104
{
109105
return visit(ty);
@@ -248,11 +244,6 @@ struct GenericTypeVisitor
248244
else
249245
visit(ty, *ftv);
250246
}
251-
else if (auto lt = get<LocalType>(ty))
252-
{
253-
if (visit(ty, *lt))
254-
traverse(lt->domain);
255-
}
256247
else if (auto gtv = get<GenericType>(ty))
257248
visit(ty, *gtv);
258249
else if (auto etv = get<ErrorType>(ty))

Analysis/src/Clone.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,11 +271,6 @@ class TypeCloner
271271
t->upperBound = shallowClone(t->upperBound);
272272
}
273273

274-
void cloneChildren(LocalType* t)
275-
{
276-
t->domain = shallowClone(t->domain);
277-
}
278-
279274
void cloneChildren(GenericType* t)
280275
{
281276
// TOOD: clone upper bounds.

Analysis/src/Constraint.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
8181
}
8282
else if (auto itc = get<IterableConstraint>(*this))
8383
{
84-
rci.traverse(itc->variables);
84+
for (TypeId ty : itc->variables)
85+
rci.traverse(ty);
8586
// `IterableConstraints` should not mutate `iterator`.
8687
}
8788
else if (auto nc = get<NameConstraint>(*this))
@@ -106,11 +107,6 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
106107
rci.traverse(hic->resultType);
107108
// `HasIndexerConstraint` should not mutate `subjectType` or `indexType`.
108109
}
109-
else if (auto ac = get<AssignConstraint>(*this))
110-
{
111-
rci.traverse(ac->lhsType);
112-
rci.traverse(ac->rhsType);
113-
}
114110
else if (auto apc = get<AssignPropConstraint>(*this))
115111
{
116112
rci.traverse(apc->lhsType);
@@ -124,7 +120,8 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
124120
}
125121
else if (auto uc = get<UnpackConstraint>(*this))
126122
{
127-
rci.traverse(uc->resultPack);
123+
for (TypeId ty : uc->resultPack)
124+
rci.traverse(ty);
128125
// `UnpackConstraint` should not mutate `sourcePack`.
129126
}
130127
else if (auto rpc = get<ReducePackConstraint>(*this))

0 commit comments

Comments
 (0)