Skip to content

Commit

Permalink
Sync to upstream/release/629 (#1290)
Browse files Browse the repository at this point in the history
### 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 <[email protected]>
Co-authored-by: Alexander McCord <[email protected]>
Co-authored-by: Andy Friesen <[email protected]>
Co-authored-by: Aviral Goel <[email protected]>
Co-authored-by: Vighnesh Vijay <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>
  • Loading branch information
6 people authored Jun 7, 2024
1 parent 81b2cc7 commit 0fa6a51
Show file tree
Hide file tree
Showing 68 changed files with 2,711 additions and 686 deletions.
22 changes: 11 additions & 11 deletions Analysis/include/Luau/Constraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ struct GeneralizationConstraint
struct IterableConstraint
{
TypePackId iterator;
TypePackId variables;
std::vector<TypeId> variables;

const AstNode* nextAstFragment;
DenseHashMap<const AstNode*, TypeId>* astForInNextTypes;
Expand Down Expand Up @@ -192,13 +192,7 @@ struct HasIndexerConstraint
TypeId indexType;
};

struct AssignConstraint
{
TypeId lhsType;
TypeId rhsType;
};

// assign lhsType propName rhsType
// assignProp lhsType propName rhsType
//
// Assign a value of type rhsType into the named property of lhsType.

Expand All @@ -212,6 +206,12 @@ struct AssignPropConstraint
/// populate astTypes during constraint resolution. Nothing should ever
/// block on it.
TypeId propType;

// When we generate constraints, we increment the remaining prop count on
// the table if we are able. This flag informs the solver as to whether or
// not it should in turn decrement the prop count when this constraint is
// dispatched.
bool decrementPropCount = false;
};

struct AssignIndexConstraint
Expand All @@ -226,13 +226,13 @@ struct AssignIndexConstraint
TypeId propType;
};

// resultType ~ unpack sourceTypePack
// resultTypes ~ unpack sourceTypePack
//
// Similar to PackSubtypeConstraint, but with one important difference: If the
// sourcePack is blocked, this constraint blocks.
struct UnpackConstraint
{
TypePackId resultPack;
std::vector<TypeId> resultPack;
TypePackId sourcePack;
};

Expand All @@ -254,7 +254,7 @@ struct ReducePackConstraint

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

struct Constraint
{
Expand Down
4 changes: 4 additions & 0 deletions Analysis/include/Luau/ConstraintGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ struct ConstraintGenerator
std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope;
std::vector<RequireCycle> requireCycles;

DenseHashMap<TypeId, std::vector<TypeId>> localTypes{nullptr};

DcrLogger* logger;

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

bool recordPropertyAssignment(TypeId ty);

// Record the fact that a particular local has a particular type in at least
// one of its states.
void recordInferredBinding(AstLocal* local, TypeId ty);
Expand Down
14 changes: 8 additions & 6 deletions Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ struct ConstraintSolver
std::pair<bool, std::optional<TypeId>> tryDispatchSetIndexer(
NotNull<const Constraint> constraint, TypeId subjectType, TypeId indexType, TypeId propType, bool expandFreeTypeBounds);

bool tryDispatch(const AssignConstraint& c, NotNull<const Constraint> constraint);
bool tryDispatch(const AssignPropConstraint& c, NotNull<const Constraint> constraint);
bool tryDispatch(const AssignIndexConstraint& c, NotNull<const Constraint> constraint);

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

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

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

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

void block(NotNull<const Constraint> target, NotNull<const Constraint> constraint);
/**
Expand Down
30 changes: 9 additions & 21 deletions Analysis/include/Luau/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,24 +86,6 @@ struct FreeType
TypeId upperBound = nullptr;
};

/** A type that tracks the domain of a local variable.
*
* We consider each local's domain to be the union of all types assigned to it.
* We accomplish this with LocalType. Each time we dispatch an assignment to a
* local, we accumulate this union and decrement blockCount.
*
* When blockCount reaches 0, we can consider the LocalType to be "fully baked"
* and replace it with the union we've built.
*/
struct LocalType
{
TypeId domain;
int blockCount = 0;

// Used for debugging
std::string name;
};

struct GenericType
{
// By default, generics are global, with a synthetic name
Expand Down Expand Up @@ -148,6 +130,7 @@ struct BlockedType

Constraint* getOwner() const;
void setOwner(Constraint* newOwner);
void replaceOwner(Constraint* newOwner);

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

// Methods of this table that have an untyped self will use the same shared self type.
std::optional<TypeId> selfTy;

// We track the number of as-yet-unadded properties to unsealed tables.
// Some constraints will use this information to decide whether or not they
// are able to dispatch.
size_t remainingProps = 0;
};

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

using ErrorType = Unifiable::Error;

using TypeVariant = Unifiable::Variant<TypeId, FreeType, LocalType, GenericType, PrimitiveType, BlockedType, PendingExpansionType, SingletonType,
FunctionType, TableType, MetatableType, ClassType, AnyType, UnionType, IntersectionType, LazyType, UnknownType, NeverType, NegationType,
TypeFamilyInstanceType>;
using TypeVariant =
Unifiable::Variant<TypeId, FreeType, GenericType, PrimitiveType, BlockedType, PendingExpansionType, SingletonType, FunctionType, TableType,
MetatableType, ClassType, AnyType, UnionType, IntersectionType, LazyType, UnknownType, NeverType, NegationType, TypeFamilyInstanceType>;

struct Type final
{
Expand Down
1 change: 0 additions & 1 deletion Analysis/include/Luau/Unifier2.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ struct Unifier2
*/
bool unify(TypeId subTy, TypeId superTy);
bool unifyFreeWithType(TypeId subTy, TypeId superTy);
bool unify(const LocalType* subTy, TypeId superFn);
bool unify(TypeId subTy, const FunctionType* superFn);
bool unify(const UnionType* subUnion, TypeId superTy);
bool unify(TypeId subTy, const UnionType* superUnion);
Expand Down
9 changes: 0 additions & 9 deletions Analysis/include/Luau/VisitType.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,6 @@ struct GenericTypeVisitor
{
return visit(ty);
}
virtual bool visit(TypeId ty, const LocalType& ftv)
{
return visit(ty);
}
virtual bool visit(TypeId ty, const GenericType& gtv)
{
return visit(ty);
Expand Down Expand Up @@ -248,11 +244,6 @@ struct GenericTypeVisitor
else
visit(ty, *ftv);
}
else if (auto lt = get<LocalType>(ty))
{
if (visit(ty, *lt))
traverse(lt->domain);
}
else if (auto gtv = get<GenericType>(ty))
visit(ty, *gtv);
else if (auto etv = get<ErrorType>(ty))
Expand Down
5 changes: 0 additions & 5 deletions Analysis/src/Clone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,6 @@ class TypeCloner
t->upperBound = shallowClone(t->upperBound);
}

void cloneChildren(LocalType* t)
{
t->domain = shallowClone(t->domain);
}

void cloneChildren(GenericType* t)
{
// TOOD: clone upper bounds.
Expand Down
11 changes: 4 additions & 7 deletions Analysis/src/Constraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
}
else if (auto itc = get<IterableConstraint>(*this))
{
rci.traverse(itc->variables);
for (TypeId ty : itc->variables)
rci.traverse(ty);
// `IterableConstraints` should not mutate `iterator`.
}
else if (auto nc = get<NameConstraint>(*this))
Expand All @@ -106,11 +107,6 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
rci.traverse(hic->resultType);
// `HasIndexerConstraint` should not mutate `subjectType` or `indexType`.
}
else if (auto ac = get<AssignConstraint>(*this))
{
rci.traverse(ac->lhsType);
rci.traverse(ac->rhsType);
}
else if (auto apc = get<AssignPropConstraint>(*this))
{
rci.traverse(apc->lhsType);
Expand All @@ -124,7 +120,8 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
}
else if (auto uc = get<UnpackConstraint>(*this))
{
rci.traverse(uc->resultPack);
for (TypeId ty : uc->resultPack)
rci.traverse(ty);
// `UnpackConstraint` should not mutate `sourcePack`.
}
else if (auto rpc = get<ReducePackConstraint>(*this))
Expand Down
Loading

0 comments on commit 0fa6a51

Please sign in to comment.