Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions Analysis/include/Luau/AstUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,15 @@ namespace Luau
// uniquely held references. Append these types to 'uniqueTypes'.
void findUniqueTypes(NotNull<DenseHashSet<TypeId>> uniqueTypes, AstExpr* expr, NotNull<const DenseHashMap<const AstExpr*, TypeId>> astTypes);

void findUniqueTypes(NotNull<DenseHashSet<TypeId>> uniqueTypes, AstArray<AstExpr*> exprs, NotNull<const DenseHashMap<const AstExpr*, TypeId>> astTypes);
void findUniqueTypes(NotNull<DenseHashSet<TypeId>> uniqueTypes, const std::vector<AstExpr*>& exprs, NotNull<const DenseHashMap<const AstExpr*, TypeId>> astTypes);
void findUniqueTypes(
NotNull<DenseHashSet<TypeId>> uniqueTypes,
AstArray<AstExpr*> exprs,
NotNull<const DenseHashMap<const AstExpr*, TypeId>> astTypes
);
void findUniqueTypes(
NotNull<DenseHashSet<TypeId>> uniqueTypes,
const std::vector<AstExpr*>& exprs,
NotNull<const DenseHashMap<const AstExpr*, TypeId>> astTypes
);

}
} // namespace Luau
1 change: 1 addition & 0 deletions Analysis/include/Luau/BuiltinDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ TypeId getGlobalBinding(GlobalTypes& globals, const std::string& name);
bool matchSetMetatable(const AstExprCall& call);
bool matchTableFreeze(const AstExprCall& call);
bool matchAssert(const AstExprCall& call);
bool matchTypeOf(const AstExprCall& call);

// Returns `true` if the function should introduce typestate for its first argument.
bool shouldTypestateForFirstArgument(const AstExprCall& call);
Expand Down
4 changes: 3 additions & 1 deletion Analysis/include/Luau/BuiltinTypeFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace Luau
struct BuiltinTypeFunctions
{
BuiltinTypeFunctions();
BuiltinTypeFunctions(const BuiltinTypeFunctions&) = delete;
void operator=(const BuiltinTypeFunctions&) = delete;

TypeFunction userFunc;

Expand Down Expand Up @@ -51,6 +53,6 @@ struct BuiltinTypeFunctions
void addToScope(NotNull<TypeArena> arena, NotNull<Scope> scope) const;
};

const BuiltinTypeFunctions& builtinTypeFunctions();
const BuiltinTypeFunctions& builtinTypeFunctions_DEPRECATED();

} // namespace Luau
33 changes: 19 additions & 14 deletions Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,18 +218,6 @@ struct ConstraintSolver

void generalizeOneType(TypeId ty);

/**
* Bind a type variable to another type.
*
* A constraint is required and will validate that blockedTy is owned by this
* constraint. This prevents one constraint from interfering with another's
* blocked types.
*
* Bind will also unblock the type variable for you.
*/
void bind(NotNull<const Constraint> constraint, TypeId ty, TypeId boundTo);
void bind(NotNull<const Constraint> constraint, TypePackId tp, TypePackId boundTo);

template<typename T, typename... Args>
void emplace(NotNull<const Constraint> constraint, TypeId ty, Args&&... args);

Expand Down Expand Up @@ -300,7 +288,7 @@ struct ConstraintSolver
ValueContext context,
bool inConditional,
bool suppressSimplification,
DenseHashSet<TypeId>& seen
Set<TypeId>& seen
);

/**
Expand Down Expand Up @@ -404,6 +392,18 @@ struct ConstraintSolver
*/
void shiftReferences(TypeId source, TypeId target);

/**
* Bind a type variable to another type.
*
* A constraint is required and will validate that blockedTy is owned by this
* constraint. This prevents one constraint from interfering with another's
* blocked types.
*
* Bind will also unblock the type variable for you.
*/
void bind(NotNull<const Constraint> constraint, TypeId ty, TypeId boundTo);
void bind(NotNull<const Constraint> constraint, TypePackId tp, TypePackId boundTo);

/**
* Generalizes the given free type if the reference counting allows it.
* @param the scope to generalize in
Expand Down Expand Up @@ -462,7 +462,12 @@ struct ConstraintSolver
void reproduceConstraints(NotNull<Scope> scope, const Location& location, const Substitution& subst);

TypeId simplifyIntersection(NotNull<Scope> scope, Location location, TypeId left, TypeId right);
TypeId simplifyIntersection(NotNull<Scope> scope, Location location, std::set<TypeId> parts);

// Clip with LuauSimplifyIntersectionNoTreeSet
TypeId simplifyIntersection_DEPRECATED(NotNull<Scope> scope, Location location, std::set<TypeId> parts);

TypeId simplifyIntersection(NotNull<Scope> scope, Location location, TypeIds parts);

TypeId simplifyUnion(NotNull<Scope> scope, Location location, TypeId left, TypeId right);

TypePackId anyifyModuleReturnTypePackGenerics(TypePackId tp);
Expand Down
12 changes: 9 additions & 3 deletions Analysis/include/Luau/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,14 +225,19 @@ struct Frontend
);

// Batch module checking. Queue modules and check them together, retrieve results with 'getCheckResult'
// If provided, 'executeTask' function is allowed to call the 'task' function on any thread and return without waiting for 'task' to complete
// If provided, 'executeTasks' function is allowed to call any item in 'tasks' on any thread and return without waiting for them to complete
void queueModuleCheck(const std::vector<ModuleName>& names);
void queueModuleCheck(const ModuleName& name);
std::vector<ModuleName> checkQueuedModules(
std::vector<ModuleName> checkQueuedModules_DEPRECATED(
std::optional<FrontendOptions> optionOverride = {},
std::function<void(std::function<void()> task)> executeTask = {},
std::function<bool(size_t done, size_t total)> progress = {}
);
std::vector<ModuleName> checkQueuedModules(
std::optional<FrontendOptions> optionOverride = {},
std::function<void(std::vector<std::function<void()>> tasks)> executeTasks = {},
std::function<bool(size_t done, size_t total)> progress = {}
);

std::optional<CheckResult> getCheckResult(const ModuleName& name, bool accumulateNested, bool forAutocomplete = false);
std::vector<ModuleName> getRequiredScripts(const ModuleName& name);
Expand Down Expand Up @@ -270,7 +275,8 @@ struct Frontend
void checkBuildQueueItems(std::vector<BuildQueueItem>& items);
void recordItemResult(const BuildQueueItem& item);
void performQueueItemTask(std::shared_ptr<BuildQueueWorkState> state, size_t itemPos);
void sendQueueItemTask(std::shared_ptr<BuildQueueWorkState> state, size_t itemPos);
void sendQueueItemTask_DEPRECATED(std::shared_ptr<BuildQueueWorkState> state, size_t itemPos);
void sendQueueItemTasks(std::shared_ptr<BuildQueueWorkState> state, const std::vector<size_t>& items);
void sendQueueCycleItemTask(std::shared_ptr<BuildQueueWorkState> state);

static LintResult classifyLints(const std::vector<LintWarning>& warnings, const Config& config);
Expand Down
28 changes: 28 additions & 0 deletions Analysis/include/Luau/NativeStackGuard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once

#include <stdint.h>

namespace Luau
{

struct NativeStackGuard
{
NativeStackGuard();

// Returns true if we are not dangerously close to overrunning the C stack.
bool isOk() const;

private:
uintptr_t high;
uintptr_t low;
};

}

namespace Luau
{

uintptr_t getStackAddressSpaceSize();

}
39 changes: 30 additions & 9 deletions Analysis/include/Luau/Normalize.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ enum class NormalizationResult
// * G is a union of generic/free/blocked types, intersected with a normalized type
struct NormalizedType
{
NotNull<BuiltinTypes> builtinTypes;

// The top part of the type.
// This type is either never, unknown, or any.
// If this type is not never, all the other fields are null.
Expand Down Expand Up @@ -315,6 +317,8 @@ class Normalizer
DenseHashMap<TypeId, bool> cachedIsInhabited{nullptr};
DenseHashMap<std::pair<TypeId, TypeId>, bool, TypeIdPairHash> cachedIsInhabitedIntersection{{nullptr, nullptr}};

std::optional<int> fuel{std::nullopt};

bool withinResourceLimits();
bool useNewLuauSolver() const;

Expand All @@ -340,13 +344,29 @@ class Normalizer

// If this returns null, the typechecker should emit a "too complex" error
std::shared_ptr<const NormalizedType> normalize(TypeId ty);
void clearNormal(NormalizedType& norm);

void clearCaches();

NormalizationResult isIntersectionInhabited(TypeId left, TypeId right);

// Check for inhabitance
NormalizationResult isInhabited(TypeId ty);
NormalizationResult isInhabited(const NormalizedType* norm);

// -------- Convert back from a normalized type to a type
TypeId typeFromNormal(const NormalizedType& norm);

std::optional<TypePackId> intersectionOfTypePacks(TypePackId here, TypePackId there);

// Move to private with LuauNormalizerStepwiseFuel
std::optional<TypePackId> intersectionOfTypePacks_INTERNAL(TypePackId here, TypePackId there);

private:
// ------- Cached TypeIds
TypeId unionType(TypeId here, TypeId there);
TypeId intersectionType(TypeId here, TypeId there);
const TypeIds* cacheTypeIds(TypeIds tys);
void clearCaches();
void clearNormal(NormalizedType& norm);

// ------- Normalizing unions
void unionTysWithTy(TypeIds& here, TypeId there);
Expand Down Expand Up @@ -387,7 +407,6 @@ class Normalizer
void intersectExternTypes(NormalizedExternType& heres, const NormalizedExternType& theres);
void intersectExternTypesWithExternType(NormalizedExternType& heres, TypeId there);
void intersectStrings(NormalizedStringType& here, const NormalizedStringType& there);
std::optional<TypePackId> intersectionOfTypePacks(TypePackId here, TypePackId there);
std::optional<TypeId> intersectionOfTables(TypeId here, TypeId there, SeenTablePropPairs& seenTablePropPairs, Set<TypeId>& seenSet);
void intersectTablesWithTable(TypeIds& heres, TypeId there, SeenTablePropPairs& seenTablePropPairs, Set<TypeId>& seenSetTypes);
void intersectTables(TypeIds& heres, const TypeIds& theres);
Expand All @@ -409,18 +428,20 @@ class Normalizer
Set<TypeId>& seenSet
);

// Check for inhabitance
NormalizationResult isInhabited(TypeId ty);
NormalizationResult isInhabited(TypeId ty, Set<TypeId>& seen);
NormalizationResult isInhabited(const NormalizedType* norm);
NormalizationResult isInhabited(const NormalizedType* norm, Set<TypeId>& seen);

// Check for intersections being inhabited
NormalizationResult isIntersectionInhabited(TypeId left, TypeId right);
NormalizationResult isIntersectionInhabited(TypeId left, TypeId right, SeenTablePropPairs& seenTablePropPairs, Set<TypeId>& seenSet);

// -------- Convert back from a normalized type to a type
TypeId typeFromNormal(const NormalizedType& norm);

// Fuel setup

bool initializeFuel();
void clearFuel();
void consumeFuel();

friend struct FuelInitializer;
};

} // namespace Luau
12 changes: 12 additions & 0 deletions Analysis/include/Luau/OverloadResolution.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,18 @@ struct OverloadResolver
std::optional<TypeId> failedSubTy,
std::optional<TypeId> failedSuperTy
) const;

// Checks if the candidate args are arity-compatible with the desired parameters.
// Used during overload selection to do arity-based filtering of overloads.
// We do not accept nil in place of a generic unless that generic is explicitly optional.
bool isArityCompatible(TypePackId candidate, TypePackId desired, NotNull<BuiltinTypes> builtinTypes) const;

bool testFunctionTypeForOverloadSelection(
const FunctionType* ftv,
NotNull<DenseHashSet<TypeId>> uniqueTypes,
TypePackId argsPack,
bool useFreeTypeBounds
);
};

struct SolveResult
Expand Down
35 changes: 12 additions & 23 deletions Analysis/include/Luau/RecursionCounter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "Luau/Common.h"
#include "Luau/Error.h"
#include "Luau/NativeStackGuard.h"

#include <stdexcept>
#include <exception>
Expand All @@ -12,40 +13,28 @@ namespace Luau

struct RecursionLimitException : public InternalCompilerError
{
RecursionLimitException(const std::string system)
: InternalCompilerError("Internal recursion counter limit exceeded in " + system)
{
}
explicit RecursionLimitException(const std::string& system);
};

struct RecursionCounter
{
RecursionCounter(int* count)
: count(count)
{
++(*count);
}

~RecursionCounter()
{
LUAU_ASSERT(*count > 0);
--(*count);
}
explicit RecursionCounter(int* count);
~RecursionCounter();

RecursionCounter(const RecursionCounter&) = delete;
RecursionCounter& operator=(const RecursionCounter&) = delete;
RecursionCounter(RecursionCounter&&) = delete;
RecursionCounter& operator=(RecursionCounter&&) = delete;

protected:
int* count;
};

struct RecursionLimiter : RecursionCounter
{
RecursionLimiter(const std::string system, int* count, int limit)
: RecursionCounter(count)
{
if (limit > 0 && *count > limit)
{
throw RecursionLimitException(system);
}
}
NativeStackGuard nativeStackGuard;

RecursionLimiter(const std::string& system, int* count, int limit);
};

} // namespace Luau
7 changes: 6 additions & 1 deletion Analysis/include/Luau/Simplify.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Luau/DenseHash.h"
#include "Luau/NotNull.h"
#include "Luau/TypeFwd.h"
#include "Luau/TypeIds.h"

#include <optional>
#include <set>
Expand All @@ -22,7 +23,11 @@ struct SimplifyResult
};

SimplifyResult simplifyIntersection(NotNull<BuiltinTypes> builtinTypes, NotNull<TypeArena> arena, TypeId left, TypeId right);
SimplifyResult simplifyIntersection(NotNull<BuiltinTypes> builtinTypes, NotNull<TypeArena> arena, std::set<TypeId> parts);

// Clip with LuauSimplifyIntersectionNoTreeSet
SimplifyResult simplifyIntersection_DEPRECATED(NotNull<BuiltinTypes> builtinTypes, NotNull<TypeArena> arena, std::set<TypeId> parts);

SimplifyResult simplifyIntersection(NotNull<BuiltinTypes> builtinTypes, NotNull<TypeArena> arena, TypeIds parts);

SimplifyResult simplifyUnion(NotNull<BuiltinTypes> builtinTypes, NotNull<TypeArena> arena, TypeId left, TypeId right);

Expand Down
Loading