Skip to content

Commit

Permalink
Sync to upstream/release/601 (#1084)
Browse files Browse the repository at this point in the history
## What's changed

- `bit32.byteswap` added
([RFC](https://github.com/luau-lang/rfcs/blob/4f543ec23b6a1b53396e0803dd253c83041bae62/docs/function-bit32-byteswap.md))
- Buffer library implementation
([RFC](https://github.com/luau-lang/rfcs/blob/4f543ec23b6a1b53396e0803dd253c83041bae62/docs/type-byte-buffer.md))
- Fixed a missing `stdint.h` include
- Fixed parser limiter for recursive type annotations being kind of
weird (fixes #645)

### Native Codegen
- Fixed a pair of issues when lowering `bit32.extract`
- Fixed a narrow edge case that could result in an infinite loop without
an interruption
- Fixed a negative array out-of-bounds access issue
- Temporarily reverted linear block predecessor value propagation

### New type solver
- We now type check assignments to annotated variables
- Fixed some test cases under local type inference
- Moved `isPending` checks for type families to improve performance
- Optimized our process for testing if a free type is sufficiently
solved
- Removed "none ptr" from lea instruction disassembly logging

### Build system & tooling
- CMake configuration now validates dependencies to maintain separation
between components
- Improvements to the fuzzer coverage
- Deduplicator for fuzzed callstacks

---------

Co-authored-by: Arseny Kapoulkine <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>
Co-authored-by: Andy Friesen <[email protected]>
Co-authored-by: Aaron Weiss <[email protected]>
Co-authored-by: Vighnesh Vijay <[email protected]>
  • Loading branch information
6 people authored Oct 27, 2023
1 parent 87d955d commit e5ec0cd
Show file tree
Hide file tree
Showing 41 changed files with 1,817 additions and 433 deletions.
2 changes: 2 additions & 0 deletions Analysis/include/Luau/Constraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ struct Constraint
ConstraintV c;

std::vector<NotNull<Constraint>> dependencies;

DenseHashSet<TypeId> getFreeTypes() const;
};

using ConstraintPtr = std::unique_ptr<Constraint>;
Expand Down
3 changes: 3 additions & 0 deletions Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ struct ConstraintSolver
// Memoized instantiations of type aliases.
DenseHashMap<InstantiationSignature, TypeId, HashInstantiationSignature> instantiatedAliases{{}};

// A mapping from free types to the number of unresolved constraints that mention them.
DenseHashMap<TypeId, size_t> unresolvedConstraints{{}};

// Recorded errors that take place within the solver.
ErrorVec errors;

Expand Down
1 change: 0 additions & 1 deletion Analysis/include/Luau/TypePairHash.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "Luau/TypeFwd.h"

#include <stdint.h>

#include <utility>

namespace Luau
Expand Down
37 changes: 37 additions & 0 deletions Analysis/src/Constraint.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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
{
Expand All @@ -12,4 +13,40 @@ Constraint::Constraint(NotNull<Scope> scope, const Location& location, Constrain
{
}

struct FreeTypeCollector : TypeOnceVisitor
{

DenseHashSet<TypeId>* result;

FreeTypeCollector(DenseHashSet<TypeId>* result)
: result(result)
{
}

bool visit(TypeId ty, const FreeType&) override
{
result->insert(ty);
return false;
}
};

DenseHashSet<TypeId> Constraint::getFreeTypes() const
{
DenseHashSet<TypeId> types{{}};
FreeTypeCollector ftc{&types};

if (auto sc = get<SubtypeConstraint>(*this))
{
ftc.traverse(sc->subType);
ftc.traverse(sc->superType);
}
else if (auto psc = get<PackSubtypeConstraint>(*this))
{
ftc.traverse(psc->subPack);
ftc.traverse(psc->superPack);
}

return types;
}

} // namespace Luau
53 changes: 14 additions & 39 deletions Analysis/src/ConstraintSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,13 @@ ConstraintSolver::ConstraintSolver(NotNull<Normalizer> normalizer, NotNull<Scope
{
unsolvedConstraints.push_back(c);

// initialize the reference counts for the free types in this constraint.
for (auto ty : c->getFreeTypes())
{
// increment the reference count for `ty`
unresolvedConstraints[ty] += 1;
}

for (NotNull<const Constraint> dep : c->dependencies)
{
block(dep, c);
Expand Down Expand Up @@ -360,6 +367,10 @@ void ConstraintSolver::run()
unblock(c);
unsolvedConstraints.erase(unsolvedConstraints.begin() + i);

// decrement the referenced free types for this constraint if we dispatched successfully!
for (auto ty : c->getFreeTypes())
unresolvedConstraints[ty] -= 1;

if (logger)
{
logger->commitStepSnapshot(snapshot);
Expand Down Expand Up @@ -2380,48 +2391,12 @@ void ConstraintSolver::reportError(TypeError e)
errors.back().moduleName = currentModuleName;
}

struct ContainsType : TypeOnceVisitor
{
TypeId needle;
bool found = false;

explicit ContainsType(TypeId needle)
: needle(needle)
{
}

bool visit(TypeId) override
{
return !found; // traverse into the type iff we have yet to find the needle
}

bool visit(TypeId ty, const FreeType&) override
{
found |= ty == needle;
return false;
}
};

bool ConstraintSolver::hasUnresolvedConstraints(TypeId ty)
{
if (!get<FreeType>(ty) || unsolvedConstraints.empty())
return false; // if it's not free, it never has any unresolved constraints, maybe?
if (auto refCount = unresolvedConstraints.find(ty))
return *refCount > 0;

ContainsType containsTy{ty};

for (auto constraint : unsolvedConstraints)
{
if (auto sc = get<SubtypeConstraint>(*constraint))
{
containsTy.traverse(sc->subType);
containsTy.traverse(sc->superType);

if (containsTy.found)
return true;
}
}

return containsTy.found;
return false;
}

TypeId ConstraintSolver::errorRecoveryType() const
Expand Down
40 changes: 40 additions & 0 deletions Analysis/src/EmbeddedBuiltinDefinitions.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,45 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#include "Luau/BuiltinDefinitions.h"

LUAU_FASTFLAGVARIABLE(LuauBufferDefinitions, false)

namespace Luau
{

static const std::string kBuiltinDefinitionBufferSrc = R"BUILTIN_SRC(
-- TODO: this will be replaced with a built-in primitive type
declare class buffer end
declare buffer: {
create: (size: number) -> buffer,
fromstring: (str: string) -> buffer,
tostring: () -> string,
len: (b: buffer) -> number,
copy: (target: buffer, targetOffset: number, source: buffer, sourceOffset: number?, count: number?) -> (),
fill: (b: buffer, offset: number, value: number, count: number?) -> (),
readi8: (b: buffer, offset: number) -> number,
readu8: (b: buffer, offset: number) -> number,
readi16: (b: buffer, offset: number) -> number,
readu16: (b: buffer, offset: number) -> number,
readi32: (b: buffer, offset: number) -> number,
readu32: (b: buffer, offset: number) -> number,
readf32: (b: buffer, offset: number) -> number,
readf64: (b: buffer, offset: number) -> number,
writei8: (b: buffer, offset: number, value: number) -> (),
writeu8: (b: buffer, offset: number, value: number) -> (),
writei16: (b: buffer, offset: number, value: number) -> (),
writeu16: (b: buffer, offset: number, value: number) -> (),
writei32: (b: buffer, offset: number, value: number) -> (),
writeu32: (b: buffer, offset: number, value: number) -> (),
writef32: (b: buffer, offset: number, value: number) -> (),
writef64: (b: buffer, offset: number, value: number) -> (),
readstring: (b: buffer, offset: number, count: number) -> string,
writestring: (b: buffer, offset: number, value: string, count: number?) -> (),
}
)BUILTIN_SRC";

static const std::string kBuiltinDefinitionLuaSrc = R"BUILTIN_SRC(
declare bit32: {
Expand Down Expand Up @@ -199,6 +235,10 @@ declare function unpack<V>(tab: {V}, i: number?, j: number?): ...V
std::string getBuiltinDefinitionSource()
{
std::string result = kBuiltinDefinitionLuaSrc;

if (FFlag::LuauBufferDefinitions)
result = kBuiltinDefinitionBufferSrc + result;

return result;
}

Expand Down
26 changes: 25 additions & 1 deletion Analysis/src/TypeChecker2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,22 @@ struct TypeChecker2
}
}

std::optional<TypeId> getBindingType(AstExpr* expr)
{
if (auto localExpr = expr->as<AstExprLocal>())
{
Scope* s = stack.back();
return s->lookup(localExpr->local);
}
else if (auto globalExpr = expr->as<AstExprGlobal>())
{
Scope* s = stack.back();
return s->lookup(globalExpr->name);
}
else
return std::nullopt;
}

void visit(AstStatAssign* assign)
{
size_t count = std::min(assign->vars.size, assign->values.size);
Expand All @@ -885,7 +901,15 @@ struct TypeChecker2
if (get<NeverType>(lhsType))
continue;

testIsSubtype(rhsType, lhsType, rhs->location);
bool ok = testIsSubtype(rhsType, lhsType, rhs->location);

// If rhsType </: lhsType, then it's not useful to also report that rhsType </: bindingType
if (ok)
{
std::optional<TypeId> bindingType = getBindingType(lhs);
if (bindingType)
testIsSubtype(rhsType, *bindingType, rhs->location);
}
}
}

Expand Down
Loading

0 comments on commit e5ec0cd

Please sign in to comment.