Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
765591c
Sync to origin/release/656
hgoldstein Jan 10, 2025
a0ed331
Merge branch 'upstream' into merge
hgoldstein Jan 10, 2025
ba71ff1
Explicitly cast size_t to uint64_t in buffer_readbits / buffer_writebits
hgoldstein Jan 10, 2025
aaaeae5
Sync to upstream/release/657
vrn-sn Jan 17, 2025
790dc17
Merge branch 'master' into merge
vrn-sn Jan 17, 2025
c6e2b53
Merge branch 'upstream' into merge
vrn-sn Jan 17, 2025
76e0958
Include <algorithm> and <vector> in IrUtils.cpp
vrn-sn Jan 17, 2025
23241e2
Sync to upstream/release/658
ayoungbloodrbx Jan 24, 2025
6167275
Merge branch 'master' into merge
ayoungbloodrbx Jan 24, 2025
ec5643d
Merge branch 'upstream' into merge
ayoungbloodrbx Jan 24, 2025
768a3a2
Remove duplicate flag
ayoungbloodrbx Jan 24, 2025
c31654d
Move duplicate flag back
ayoungbloodrbx Jan 24, 2025
072195b
Merge branch 'master' into merge
menarulalam Feb 1, 2025
5f0bd2f
Sync to upstream/release/659
menarulalam Feb 1, 2025
a699a21
Merge branch 'upstream' into merge
menarulalam Feb 1, 2025
a3630ef
Merge branch 'upstream' into merge
menarulalam Feb 1, 2025
df60533
Sync to upstream/release/659
menarulalam Feb 1, 2025
7199da8
Sync to upstream/release/660
Feb 7, 2025
fd9b8b0
Merge branch 'master' into merge
Feb 7, 2025
198c1f7
Merge branch 'upstream' into merge
Feb 7, 2025
6b30374
Cast types appropriately to fix compilation error.
Feb 7, 2025
d17d70d
Merge branch 'upstream' into merge
Feb 7, 2025
c9a4113
Explicitly enable FFlags in interpolated string Transpiler tests
Feb 8, 2025
587cf13
Sync to upstream/release/661
Vighnesh-V Feb 14, 2025
aab18f3
Merge branch 'master' into merge
Vighnesh-V Feb 14, 2025
1d001c4
Merge branch 'upstream' into merge
Vighnesh-V Feb 14, 2025
69afd59
Correctly apply unsigned casting patch to merge branch
Vighnesh-V Feb 14, 2025
279e15a
Sync to upstream/release/662
vegorov-rbx Feb 21, 2025
1c3720a
Merge branch 'master' into merge
vegorov-rbx Feb 21, 2025
4717228
Merge branch 'upstream' into merge
vegorov-rbx Feb 21, 2025
6a8da81
Merge fix
vegorov-rbx Feb 21, 2025
b6ca2a0
Sync to upstream/release/663
aatxe Feb 28, 2025
4b3b32a
Merge branch 'master' into merge
aatxe Feb 28, 2025
f43ebc2
Merge branch 'upstream' into merge
aatxe Feb 28, 2025
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
3 changes: 3 additions & 0 deletions Analysis/include/Luau/ConstraintGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ struct ConstraintGenerator
// will enqueue them during solving.
std::vector<ConstraintPtr> unqueuedConstraints;

// Map a function's signature scope back to its signature type.
DenseHashMap<Scope*, TypeId> scopeToFunction{nullptr};

// The private scope of type aliases for which the type parameters belong to.
DenseHashMap<const AstStatTypeAlias*, ScopePtr> astTypeAliasDefiningScopes{nullptr};

Expand Down
5 changes: 5 additions & 0 deletions Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct ConstraintSolver
NotNull<TypeFunctionRuntime> typeFunctionRuntime;
// The entire set of constraints that the solver is trying to resolve.
std::vector<NotNull<Constraint>> constraints;
NotNull<DenseHashMap<Scope*, TypeId>> scopeToFunction;
NotNull<Scope> rootScope;
ModuleName currentModuleName;

Expand Down Expand Up @@ -119,6 +120,7 @@ struct ConstraintSolver
DenseHashMap<TypeId, size_t> unresolvedConstraints{{}};

std::unordered_map<NotNull<const Constraint>, DenseHashSet<TypeId>> maybeMutatedFreeTypes;
std::unordered_map<TypeId, DenseHashSet<const Constraint*>> mutatedFreeTypeToConstraint;

// Irreducible/uninhabited type functions or type pack functions.
DenseHashSet<const void*> uninhabitedTypeFunctions{{}};
Expand All @@ -144,6 +146,7 @@ struct ConstraintSolver
NotNull<TypeFunctionRuntime> typeFunctionRuntime,
NotNull<Scope> rootScope,
std::vector<NotNull<Constraint>> constraints,
NotNull<DenseHashMap<Scope*, TypeId>> scopeToFunction,
ModuleName moduleName,
NotNull<ModuleResolver> moduleResolver,
std::vector<RequireCycle> requireCycles,
Expand Down Expand Up @@ -171,6 +174,8 @@ struct ConstraintSolver
bool isDone() const;

private:
void generalizeOneType(TypeId ty);

/**
* Bind a type variable to another type.
*
Expand Down
60 changes: 60 additions & 0 deletions Analysis/include/Luau/FragmentAutocomplete.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,65 @@ FragmentAutocompleteResult fragmentAutocomplete(
std::optional<Position> fragmentEndPosition = std::nullopt
);

enum class FragmentAutocompleteStatus
{
Success,
FragmentTypeCheckFail,
InternalIce
};

struct FragmentAutocompleteStatusResult
{
FragmentAutocompleteStatus status;
std::optional<FragmentAutocompleteResult> result;
};

struct FragmentContext
{
std::string_view newSrc;
const ParseResult& newAstRoot;
std::optional<FrontendOptions> opts;
std::optional<Position> DEPRECATED_fragmentEndPosition;
};

/**
* @brief Attempts to compute autocomplete suggestions from the fragment context.
*
* This function computes autocomplete suggestions using outdated frontend typechecking data
* by patching the fragment context of the new script source content.
*
* @param frontend The Luau Frontend data structure, which may contain outdated typechecking data.
*
* @param moduleName The name of the target module, specifying which script the caller wants to request autocomplete for.
*
* @param cursorPosition The position in the script where the caller wants to trigger autocomplete.
*
* @param context The fragment context that this API will use to patch the outdated typechecking data.
*
* @param stringCompletionCB A callback function that provides autocomplete suggestions for string contexts.
*
* @return
* The status indicating whether `fragmentAutocomplete` ran successfully or failed, along with the reason for failure.
* Also includes autocomplete suggestions if the status is successful.
*
* @usage
* FragmentAutocompleteStatusResult acStatusResult;
* if (shouldFragmentAC)
* acStatusResult = Luau::tryFragmentAutocomplete(...);
*
* if (acStatusResult.status != Successful)
* {
* frontend.check(moduleName, options);
* acStatusResult.acResult = Luau::autocomplete(...);
* }
* return convertResultWithContext(acStatusResult.acResult);
*/
FragmentAutocompleteStatusResult tryFragmentAutocomplete(
Frontend& frontend,
const ModuleName& moduleName,
Position cursorPosition,
FragmentContext context,
StringCompletionCallback stringCompletionCB
);

} // namespace Luau
2 changes: 2 additions & 0 deletions Analysis/include/Luau/TableLiteralInference.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "Luau/NotNull.h"
#include "Luau/TypeFwd.h"

#include <vector>

namespace Luau
{

Expand Down
3 changes: 1 addition & 2 deletions Analysis/include/Luau/TxnLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,10 @@ T* getMutable(PendingTypePack* pending)
// Log of what TypeIds we are rebinding, to be committed later.
struct TxnLog
{
explicit TxnLog(bool useScopes = false)
explicit TxnLog()
: typeVarChanges(nullptr)
, typePackChanges(nullptr)
, ownedSeen()
, useScopes(useScopes)
, sharedSeen(&ownedSeen)
{
}
Expand Down
6 changes: 5 additions & 1 deletion Analysis/include/Luau/TypeFunctionRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,11 @@ struct TypeFunctionClassType

std::optional<TypeFunctionTypeId> metatable; // metaclass?

std::optional<TypeFunctionTypeId> parent;
// this was mistaken, and we should actually be keeping separate read/write types here.
std::optional<TypeFunctionTypeId> parent_DEPRECATED;

std::optional<TypeFunctionTypeId> readParent;
std::optional<TypeFunctionTypeId> writeParent;

TypeId classTy;

Expand Down
10 changes: 0 additions & 10 deletions Analysis/include/Luau/Unifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,6 @@ struct Unifier

Unifier(NotNull<Normalizer> normalizer, NotNull<Scope> scope, const Location& location, Variance variance, TxnLog* parentLog = nullptr);

// Configure the Unifier to test for scope subsumption via embedded Scope
// pointers rather than TypeLevels.
void enableNewSolver();

// Test whether the two type vars unify. Never commits the result.
ErrorVec canUnify(TypeId subTy, TypeId superTy);
ErrorVec canUnify(TypePackId subTy, TypePackId superTy, bool isFunctionCall = false);
Expand Down Expand Up @@ -169,7 +165,6 @@ struct Unifier

std::optional<TypeId> findTablePropertyRespectingMeta(TypeId lhsType, Name name);

TxnLog combineLogsIntoIntersection(std::vector<TxnLog> logs);
TxnLog combineLogsIntoUnion(std::vector<TxnLog> logs);

public:
Expand All @@ -195,11 +190,6 @@ struct Unifier

// Available after regular type pack unification errors
std::optional<int> firstPackErrorPos;

// If true, we do a bunch of small things differently to work better with
// the new type inference engine. Most notably, we use the Scope hierarchy
// directly rather than using TypeLevels.
bool useNewSolver = false;
};

void promoteTypeLevels(TxnLog& log, const TypeArena* arena, TypeLevel minLevel, Scope* outerScope, bool useScope, TypePackId tp);
Expand Down
4 changes: 4 additions & 0 deletions Analysis/src/Autocomplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "Luau/Autocomplete.h"

#include "Luau/AstQuery.h"
#include "Luau/TimeTrace.h"
#include "Luau/TypeArena.h"
#include "Luau/Module.h"
#include "Luau/Frontend.h"
Expand All @@ -15,6 +16,9 @@ namespace Luau

AutocompleteResult autocomplete(Frontend& frontend, const ModuleName& moduleName, Position position, StringCompletionCallback callback)
{
LUAU_TIMETRACE_SCOPE("Luau::autocomplete", "Autocomplete");
LUAU_TIMETRACE_ARGUMENT("name", moduleName.c_str());

const SourceModule* sourceModule = frontend.getSourceModule(moduleName);
if (!sourceModule)
return {};
Expand Down
100 changes: 75 additions & 25 deletions Analysis/src/AutocompleteCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "Luau/Common.h"
#include "Luau/FileResolver.h"
#include "Luau/Frontend.h"
#include "Luau/TimeTrace.h"
#include "Luau/ToString.h"
#include "Luau/Subtyping.h"
#include "Luau/TypeInfer.h"
Expand All @@ -24,7 +25,8 @@ LUAU_FASTINT(LuauTypeInferIterationLimit)
LUAU_FASTINT(LuauTypeInferRecursionLimit)

LUAU_FASTFLAGVARIABLE(LuauAutocompleteRefactorsForIncrementalAutocomplete)
LUAU_FASTFLAGVARIABLE(LuauAutocompleteUseLimits)

LUAU_FASTFLAGVARIABLE(LuauAutocompleteUsesModuleForTypeCompatibility)

static const std::unordered_set<std::string> kStatementStartingKeywords =
{"while", "if", "local", "repeat", "function", "do", "for", "return", "break", "continue", "type", "export"};
Expand Down Expand Up @@ -146,44 +148,91 @@ static std::optional<TypeId> findExpectedTypeAt(const Module& module, AstNode* n
return *it;
}

static bool checkTypeMatch(TypeId subTy, TypeId superTy, NotNull<Scope> scope, TypeArena* typeArena, NotNull<BuiltinTypes> builtinTypes)
static bool checkTypeMatch(
const Module& module,
TypeId subTy,
TypeId superTy,
NotNull<Scope> scope,
TypeArena* typeArena,
NotNull<BuiltinTypes> builtinTypes
)
{
InternalErrorReporter iceReporter;
UnifierSharedState unifierState(&iceReporter);
SimplifierPtr simplifier = newSimplifier(NotNull{typeArena}, builtinTypes);
Normalizer normalizer{typeArena, builtinTypes, NotNull{&unifierState}};

if (FFlag::LuauSolverV2)
if (FFlag::LuauAutocompleteUsesModuleForTypeCompatibility)
{
TypeCheckLimits limits;
TypeFunctionRuntime typeFunctionRuntime{
NotNull{&iceReporter}, NotNull{&limits}
}; // TODO: maybe subtyping checks should not invoke user-defined type function runtime
if (module.checkedInNewSolver)
{
TypeCheckLimits limits;
TypeFunctionRuntime typeFunctionRuntime{
NotNull{&iceReporter}, NotNull{&limits}
}; // TODO: maybe subtyping checks should not invoke user-defined type function runtime

unifierState.counters.recursionLimit = FInt::LuauTypeInferRecursionLimit;
unifierState.counters.iterationLimit = FInt::LuauTypeInferIterationLimit;

unifierState.counters.recursionLimit = FInt::LuauTypeInferRecursionLimit;
unifierState.counters.iterationLimit = FInt::LuauTypeInferIterationLimit;
Subtyping subtyping{
builtinTypes,
NotNull{typeArena},
NotNull{simplifier.get()},
NotNull{&normalizer},
NotNull{&typeFunctionRuntime},
NotNull{&iceReporter}
};

Subtyping subtyping{
builtinTypes, NotNull{typeArena}, NotNull{simplifier.get()}, NotNull{&normalizer}, NotNull{&typeFunctionRuntime}, NotNull{&iceReporter}
};
return subtyping.isSubtype(subTy, superTy, scope).isSubtype;
}
else
{
Unifier unifier(NotNull<Normalizer>{&normalizer}, scope, Location(), Variance::Covariant);

// Cost of normalization can be too high for autocomplete response time requirements
unifier.normalize = false;
unifier.checkInhabited = false;

return subtyping.isSubtype(subTy, superTy, scope).isSubtype;
unifierState.counters.recursionLimit = FInt::LuauTypeInferRecursionLimit;
unifierState.counters.iterationLimit = FInt::LuauTypeInferIterationLimit;

return unifier.canUnify(subTy, superTy).empty();
}
}
else
{
Unifier unifier(NotNull<Normalizer>{&normalizer}, scope, Location(), Variance::Covariant);
if (FFlag::LuauSolverV2)
{
TypeCheckLimits limits;
TypeFunctionRuntime typeFunctionRuntime{
NotNull{&iceReporter}, NotNull{&limits}
}; // TODO: maybe subtyping checks should not invoke user-defined type function runtime

// Cost of normalization can be too high for autocomplete response time requirements
unifier.normalize = false;
unifier.checkInhabited = false;
unifierState.counters.recursionLimit = FInt::LuauTypeInferRecursionLimit;
unifierState.counters.iterationLimit = FInt::LuauTypeInferIterationLimit;

if (FFlag::LuauAutocompleteUseLimits)
Subtyping subtyping{
builtinTypes,
NotNull{typeArena},
NotNull{simplifier.get()},
NotNull{&normalizer},
NotNull{&typeFunctionRuntime},
NotNull{&iceReporter}
};

return subtyping.isSubtype(subTy, superTy, scope).isSubtype;
}
else
{
Unifier unifier(NotNull<Normalizer>{&normalizer}, scope, Location(), Variance::Covariant);

// Cost of normalization can be too high for autocomplete response time requirements
unifier.normalize = false;
unifier.checkInhabited = false;
unifierState.counters.recursionLimit = FInt::LuauTypeInferRecursionLimit;
unifierState.counters.iterationLimit = FInt::LuauTypeInferIterationLimit;
}

return unifier.canUnify(subTy, superTy).empty();
return unifier.canUnify(subTy, superTy).empty();
}
}
}

Expand All @@ -209,10 +258,10 @@ static TypeCorrectKind checkTypeCorrectKind(

TypeId expectedType = follow(*typeAtPosition);

auto checkFunctionType = [typeArena, builtinTypes, moduleScope, &expectedType](const FunctionType* ftv)
auto checkFunctionType = [typeArena, builtinTypes, moduleScope, &expectedType, &module](const FunctionType* ftv)
{
if (std::optional<TypeId> firstRetTy = first(ftv->retTypes))
return checkTypeMatch(*firstRetTy, expectedType, moduleScope, typeArena, builtinTypes);
return checkTypeMatch(module, *firstRetTy, expectedType, moduleScope, typeArena, builtinTypes);

return false;
};
Expand All @@ -235,7 +284,7 @@ static TypeCorrectKind checkTypeCorrectKind(
}
}

return checkTypeMatch(ty, expectedType, moduleScope, typeArena, builtinTypes) ? TypeCorrectKind::Correct : TypeCorrectKind::None;
return checkTypeMatch(module, ty, expectedType, moduleScope, typeArena, builtinTypes) ? TypeCorrectKind::Correct : TypeCorrectKind::None;
}

enum class PropIndexType
Expand Down Expand Up @@ -286,7 +335,7 @@ static void autocompleteProps(
// When called with '.', but declared with 'self', it is considered invalid if first argument is compatible
if (std::optional<TypeId> firstArgTy = first(ftv->argTypes))
{
if (checkTypeMatch(rootTy, *firstArgTy, NotNull{module.getModuleScope().get()}, typeArena, builtinTypes))
if (checkTypeMatch(module, rootTy, *firstArgTy, NotNull{module.getModuleScope().get()}, typeArena, builtinTypes))
return calledWithSelf;
}

Expand Down Expand Up @@ -1714,6 +1763,7 @@ AutocompleteResult autocomplete_(
StringCompletionCallback callback
)
{
LUAU_TIMETRACE_SCOPE("Luau::autocomplete_", "AutocompleteCore");
AstNode* node = ancestry.back();

AstExprConstantNil dummy{Location{}};
Expand Down
10 changes: 9 additions & 1 deletion Analysis/src/Constraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "Luau/Constraint.h"
#include "Luau/VisitType.h"

LUAU_FASTFLAG(DebugLuauGreedyGeneralization)

namespace Luau
{

Expand Down Expand Up @@ -111,14 +113,20 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
{
rci.traverse(fchc->argsPack);
}
else if (auto fcc = get<FunctionCallConstraint>(*this); fcc && FFlag::DebugLuauGreedyGeneralization)
{
rci.traverse(fcc->fn);
rci.traverse(fcc->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`.
if (FFlag::DebugLuauGreedyGeneralization)
rci.traverse(hpc->subjectType);
}
else if (auto hic = get<HasIndexerConstraint>(*this))
{
Expand Down
Loading