mirror of
https://github.com/luau-lang/luau.git
synced 2024-11-15 14:25:44 +08:00
c2ba1058c3
# What's changed? - Record the location of properties for table types (closes #802) - Implement stricter UTF-8 validations as per the RFC (https://github.com/luau-lang/rfcs/pull/1) - Implement `buffer` as a new type in both the old and new solvers. - Changed errors produced by some `buffer` builtins to be a bit more generic to avoid platform-dependent error messages. - Fixed a bug where `Unifier` would copy some persistent types, tripping some internal assertions. - Type checking rules on relational operators is now a little bit more lax. - Improve dead code elimination for some `if` statements with complex always-false conditions ## New type solver - Dataflow analysis now generates phi nodes on exit of branches. - Dataflow analysis avoids producing a new definition for locals or properties that are not owned by that loop. - If a function parameter has been constrained to `never`, report errors at all uses of that parameter within that function. - Switch to using the new `Luau::Set` to replace `std::unordered_set` to alleviate some poor allocation characteristics which was negatively affecting overall performance. - Subtyping can now report many failing reasons instead of just the first one that we happened to find during the test. - Subtyping now also report reasons for type pack mismatches. - When visiting `if` statements or expressions, the resulting context are the common terms in both branches. ## Native codegen - Implement support for `buffer` builtins to its IR for x64 and A64. - Optimized `table.insert` by not inserting a table barrier if it is fastcalled with a constant. ## 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: Arseny Kapoulkine <arseny@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: Lily Brown <lbrown@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com>
106 lines
2.3 KiB
C++
106 lines
2.3 KiB
C++
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
#pragma once
|
|
|
|
#include "Luau/DenseHash.h"
|
|
|
|
namespace Luau
|
|
{
|
|
|
|
template<typename T>
|
|
using SetHashDefault = std::conditional_t<std::is_pointer_v<T>, DenseHashPointer, std::hash<T>>;
|
|
|
|
// This is an implementation of `unordered_set` using `DenseHashMap<T, bool>` to support erasure.
|
|
// This lets us work around `DenseHashSet` limitations and get a more traditional set interface.
|
|
template<typename T, typename Hash = SetHashDefault<T>>
|
|
class Set
|
|
{
|
|
private:
|
|
DenseHashMap<T, bool, Hash> mapping;
|
|
size_t entryCount = 0;
|
|
|
|
public:
|
|
Set(const T& empty_key)
|
|
: mapping{empty_key}
|
|
{
|
|
}
|
|
|
|
bool insert(const T& element)
|
|
{
|
|
bool& entry = mapping[element];
|
|
bool fresh = !entry;
|
|
|
|
if (fresh)
|
|
{
|
|
entry = true;
|
|
entryCount++;
|
|
}
|
|
|
|
return fresh;
|
|
}
|
|
|
|
template<class Iterator>
|
|
void insert(Iterator begin, Iterator end)
|
|
{
|
|
for (Iterator it = begin; it != end; ++it)
|
|
insert(*it);
|
|
}
|
|
|
|
void erase(const T& element)
|
|
{
|
|
bool& entry = mapping[element];
|
|
|
|
if (entry)
|
|
{
|
|
entry = false;
|
|
entryCount--;
|
|
}
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
mapping.clear();
|
|
entryCount = 0;
|
|
}
|
|
|
|
size_t size() const
|
|
{
|
|
return entryCount;
|
|
}
|
|
|
|
bool empty() const
|
|
{
|
|
return entryCount == 0;
|
|
}
|
|
|
|
size_t count(const T& element) const
|
|
{
|
|
const bool* entry = mapping.find(element);
|
|
return (entry && *entry) ? 1 : 0;
|
|
}
|
|
|
|
bool contains(const T& element) const
|
|
{
|
|
return count(element) != 0;
|
|
}
|
|
|
|
bool operator==(const Set<T>& there) const
|
|
{
|
|
// if the sets are unequal sizes, then they cannot possibly be equal.
|
|
if (size() != there.size())
|
|
return false;
|
|
|
|
// otherwise, we'll need to check that every element we have here is in `there`.
|
|
for (auto [elem, present] : mapping)
|
|
{
|
|
// if it's not, we'll return `false`
|
|
if (present && there.contains(elem))
|
|
return false;
|
|
}
|
|
|
|
// otherwise, we've proven the two equal!
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace Luau
|