mirror of
https://github.com/luau-lang/luau.git
synced 2025-04-16 01:43:51 +01:00
## What's Changed ### General - Allow types of tables to diverge after using `table.clone` (fixes #1617). - Allow 2-argument vector.create in Luau. - Fix a crash when suggesting autocomplete after encountering parsing errors. - Add lua_tolstringatom C API which returns the string length (whether or not the atom exists) and which extends the existing lua_tostringatom function the same way lua_tolstring/lua_tostring do. - Luau now retains the DFGs of typechecked modules. ### Magic Functions Migration Note We've made a change to the API used to define magic functions. Previously, we had a set of function pointers on each `FunctionType` that would be invoked by the type inference engine at the correct point. The problem we'd run into is that they were all `std::function`s, we'd grown quite a few of them, and Luau allocates tens of thousands of types as it performs type inference. This adds up to a large amount of memory for data that isn't used by 99% of types. To slim things down a bit, we've replaced all of those `std::function`s with a single `shared_ptr` to a new interface called `MagicFunction`. This slims down the memory footprint of each type by about 50 bytes. The virtual methods of `MagicFunction` have roughly 1:1 correspondence with the old interface, so updating things should not be too difficult: * `FunctionType::magicFunction` is now `MagicFunction::handleOldSolver` * `FunctionType::dcrMagicFunction` is now `MagicFunction::infer` * `FunctionType::dcrMagicRefinement` is now `MagicFunction::refine` * `FunctionType::dcrMagicTypeCheck` is now `MagicFunction::typeCheck` **Full Changelog**: https://github.com/luau-lang/luau/compare/0.657...0.658 --- Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Ariel Weiss <aaronweiss@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: Hunter Goldstein <hgoldstein@roblox.com> Co-authored-by: Talha Pathan <tpathan@roblox.com> Co-authored-by: Varun Saini <vsaini@roblox.com> Co-authored-by: Vighnesh Vijay <vvijay@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com>
153 lines
4.4 KiB
C++
153 lines
4.4 KiB
C++
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
|
|
#include "Luau/Constraint.h"
|
|
#include "Luau/VisitType.h"
|
|
|
|
namespace Luau
|
|
{
|
|
|
|
Constraint::Constraint(NotNull<Scope> scope, const Location& location, ConstraintV&& c)
|
|
: scope(scope)
|
|
, location(location)
|
|
, c(std::move(c))
|
|
{
|
|
}
|
|
|
|
struct ReferenceCountInitializer : TypeOnceVisitor
|
|
{
|
|
|
|
DenseHashSet<TypeId>* result;
|
|
|
|
ReferenceCountInitializer(DenseHashSet<TypeId>* result)
|
|
: result(result)
|
|
{
|
|
}
|
|
|
|
bool visit(TypeId ty, const FreeType&) override
|
|
{
|
|
result->insert(ty);
|
|
return false;
|
|
}
|
|
|
|
bool visit(TypeId ty, const BlockedType&) override
|
|
{
|
|
result->insert(ty);
|
|
return false;
|
|
}
|
|
|
|
bool visit(TypeId ty, const PendingExpansionType&) override
|
|
{
|
|
result->insert(ty);
|
|
return false;
|
|
}
|
|
|
|
bool visit(TypeId ty, const ClassType&) override
|
|
{
|
|
// ClassTypes never contain free types.
|
|
return false;
|
|
}
|
|
|
|
bool visit(TypeId, const TypeFunctionInstanceType&) override
|
|
{
|
|
// We do not consider reference counted types that are inside a type
|
|
// function to be part of the reachable reference counted types.
|
|
// Otherwise, code can be constructed in just the right way such
|
|
// that two type functions both claim to mutate a free type, which
|
|
// prevents either type function from trying to generalize it, so
|
|
// we potentially get stuck.
|
|
//
|
|
// The default behavior here is `true` for "visit the child types"
|
|
// of this type, hence:
|
|
return false;
|
|
}
|
|
};
|
|
|
|
bool isReferenceCountedType(const TypeId typ)
|
|
{
|
|
// n.b. this should match whatever `ReferenceCountInitializer` includes.
|
|
return get<FreeType>(typ) || get<BlockedType>(typ) || get<PendingExpansionType>(typ);
|
|
}
|
|
|
|
DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
|
|
{
|
|
// For the purpose of this function and reference counting in general, we are only considering
|
|
// mutations that affect the _bounds_ of the free type, and not something that may bind the free
|
|
// type itself to a new type. As such, `ReduceConstraint` and `GeneralizationConstraint` have no
|
|
// contribution to the output set here.
|
|
|
|
DenseHashSet<TypeId> types{{}};
|
|
ReferenceCountInitializer rci{&types};
|
|
|
|
if (auto ec = get<EqualityConstraint>(*this))
|
|
{
|
|
rci.traverse(ec->resultType);
|
|
// `EqualityConstraints` should not mutate `assignmentType`.
|
|
}
|
|
else if (auto sc = get<SubtypeConstraint>(*this))
|
|
{
|
|
rci.traverse(sc->subType);
|
|
rci.traverse(sc->superType);
|
|
}
|
|
else if (auto psc = get<PackSubtypeConstraint>(*this))
|
|
{
|
|
rci.traverse(psc->subPack);
|
|
rci.traverse(psc->superPack);
|
|
}
|
|
else if (auto itc = get<IterableConstraint>(*this))
|
|
{
|
|
for (TypeId ty : itc->variables)
|
|
rci.traverse(ty);
|
|
// `IterableConstraints` should not mutate `iterator`.
|
|
}
|
|
else if (auto nc = get<NameConstraint>(*this))
|
|
{
|
|
rci.traverse(nc->namedType);
|
|
}
|
|
else if (auto taec = get<TypeAliasExpansionConstraint>(*this))
|
|
{
|
|
rci.traverse(taec->target);
|
|
}
|
|
else if (auto fchc = get<FunctionCheckConstraint>(*this))
|
|
{
|
|
rci.traverse(fchc->argsPack);
|
|
}
|
|
else if (auto ptc = get<PrimitiveTypeConstraint>(*this))
|
|
{
|
|
rci.traverse(ptc->freeType);
|
|
}
|
|
else if (auto hpc = get<HasPropConstraint>(*this))
|
|
{
|
|
rci.traverse(hpc->resultType);
|
|
// `HasPropConstraints` should not mutate `subjectType`.
|
|
}
|
|
else if (auto hic = get<HasIndexerConstraint>(*this))
|
|
{
|
|
rci.traverse(hic->resultType);
|
|
// `HasIndexerConstraint` should not mutate `subjectType` or `indexType`.
|
|
}
|
|
else if (auto apc = get<AssignPropConstraint>(*this))
|
|
{
|
|
rci.traverse(apc->lhsType);
|
|
rci.traverse(apc->rhsType);
|
|
}
|
|
else if (auto aic = get<AssignIndexConstraint>(*this))
|
|
{
|
|
rci.traverse(aic->lhsType);
|
|
rci.traverse(aic->indexType);
|
|
rci.traverse(aic->rhsType);
|
|
}
|
|
else if (auto uc = get<UnpackConstraint>(*this))
|
|
{
|
|
for (TypeId ty : uc->resultPack)
|
|
rci.traverse(ty);
|
|
// `UnpackConstraint` should not mutate `sourcePack`.
|
|
}
|
|
else if (auto rpc = get<ReducePackConstraint>(*this))
|
|
{
|
|
rci.traverse(rpc->tp);
|
|
}
|
|
|
|
return types;
|
|
}
|
|
|
|
} // namespace Luau
|