luau/EqSat/src/UnionFind.cpp
Hunter Goldstein a36a3c41cc
Sync to upstream/release/651 (#1513)
### What's New?

* Fragment Autocomplete: a new API allows for type checking a small
fragment of code against an existing file, significantly speeding up
autocomplete performance in large files.

### New Solver

* E-Graphs have landed: this is an ongoing approach to make the new type
solver simplify types in a more consistent and principled manner, based
on similar work (see: https://egraphs-good.github.io/).
* Adds support for exporting / local user type functions (previously
they were always exported).
* Fixes a set of bugs in which the new solver will fail to complete
inference for simple expressions with just literals and operators.

### General Updates
* Requiring a path with a ".lua" or ".luau" extension will now have a
bespoke error suggesting to remove said extension.
* Fixes a bug in which whether two `Luau::Symbol`s are equal depends on
whether the new solver is enabled.

---

Internal Contributors:

Co-authored-by: Aaron Weiss <aaronweiss@roblox.com>
Co-authored-by: Andy Friesen <afriesen@roblox.com>
Co-authored-by: David Cope <dcope@roblox.com>
Co-authored-by: Hunter Goldstein <hgoldstein@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>
2024-11-08 13:41:45 -08:00

74 lines
1.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#include "Luau/UnionFind.h"
#include "Luau/Common.h"
#include <limits>
namespace Luau::EqSat
{
Id UnionFind::makeSet()
{
LUAU_ASSERT(parents.size() < std::numeric_limits<uint32_t>::max());
Id id{uint32_t(parents.size())};
parents.push_back(id);
ranks.push_back(0);
return id;
}
Id UnionFind::find(Id id) const
{
return canonicalize(id);
}
Id UnionFind::find(Id id)
{
Id set = canonicalize(id);
// An e-class id 𝑎 is canonical iff find(𝑎) = 𝑎.
while (id != parents[uint32_t(id)])
{
// Note: we don't update the ranks here since a rank
// represents the upper bound on the maximum depth of a tree
Id parent = parents[uint32_t(id)];
parents[uint32_t(id)] = set;
id = parent;
}
return set;
}
Id UnionFind::merge(Id a, Id b)
{
Id aSet = find(a);
Id bSet = find(b);
if (aSet == bSet)
return aSet;
// Ensure that the rank of set A is greater than the rank of set B
if (ranks[uint32_t(aSet)] > ranks[uint32_t(bSet)])
std::swap(aSet, bSet);
parents[uint32_t(bSet)] = aSet;
if (ranks[uint32_t(aSet)] == ranks[uint32_t(bSet)])
ranks[uint32_t(aSet)]++;
return aSet;
}
Id UnionFind::canonicalize(Id id) const
{
LUAU_ASSERT(uint32_t(id) < parents.size());
// An e-class id 𝑎 is canonical iff find(𝑎) = 𝑎.
while (id != parents[uint32_t(id)])
id = parents[uint32_t(id)];
return id;
}
} // namespace Luau::EqSat