Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 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
7568957
Sync to upstream/release/664
vegorov-rbx Mar 7, 2025
a0fad72
Merge branch 'master' into merge
vegorov-rbx Mar 7, 2025
23bc546
Merge branch 'upstream' into merge
vegorov-rbx Mar 7, 2025
af20253
Sync to upstream/release/665
hgoldstein Mar 14, 2025
df92b6c
Merge branch 'master' into merge
hgoldstein Mar 14, 2025
de3f3d2
Merge branch 'upstream' into merge
hgoldstein Mar 14, 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
67 changes: 62 additions & 5 deletions Analysis/include/Luau/FileResolver.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once

#include <string>
#include <memory>
#include <optional>
#include <string>
#include <vector>

namespace Luau
Expand Down Expand Up @@ -32,15 +33,71 @@ struct ModuleInfo
bool optional = false;
};

struct RequireAlias
{
std::string alias; // Unprefixed alias name (no leading `@`).
std::vector<std::string> tags = {};
};

struct RequireNode
{
virtual ~RequireNode() {}

// Get the path component representing this node.
virtual std::string getPathComponent() const = 0;

// Get the displayed user-facing label for this node, defaults to getPathComponent()
virtual std::string getLabel() const
{
return getPathComponent();
}

// Get tags to attach to this node's RequireSuggestion (defaults to none).
virtual std::vector<std::string> getTags() const
{
return {};
}

// TODO: resolvePathToNode() can ultimately be replaced with a call into
// require-by-string's path resolution algorithm. This will first require
// generalizing that algorithm to work with a virtual file system.
virtual std::unique_ptr<RequireNode> resolvePathToNode(const std::string& path) const = 0;

// Get children of this node, if any (if this node represents a directory).
virtual std::vector<std::unique_ptr<RequireNode>> getChildren() const = 0;

// A list of the aliases available to this node.
virtual std::vector<RequireAlias> getAvailableAliases() const = 0;
};

struct RequireSuggestion
{
std::string label;
std::string fullPath;
std::vector<std::string> tags;
};
using RequireSuggestions = std::vector<RequireSuggestion>;

struct RequireSuggester
{
virtual ~RequireSuggester() {}
std::optional<RequireSuggestions> getRequireSuggestions(const ModuleName& requirer, const std::optional<std::string>& pathString) const;

protected:
virtual std::unique_ptr<RequireNode> getNode(const ModuleName& name) const = 0;

private:
std::optional<RequireSuggestions> getRequireSuggestionsImpl(const ModuleName& requirer, const std::optional<std::string>& path) const;
};

struct FileResolver
{
FileResolver() = default;
FileResolver(std::shared_ptr<RequireSuggester> requireSuggester)
: requireSuggester(std::move(requireSuggester))
{
}

virtual ~FileResolver() {}

virtual std::optional<SourceCode> readSource(const ModuleName& name) = 0;
Expand All @@ -60,10 +117,10 @@ struct FileResolver
return std::nullopt;
}

virtual std::optional<RequireSuggestions> getRequireSuggestions(const ModuleName& requirer, const std::optional<std::string>& pathString) const
{
return std::nullopt;
}
// Make non-virtual when removing FFlagLuauImproveRequireByStringAutocomplete.
virtual std::optional<RequireSuggestions> getRequireSuggestions(const ModuleName& requirer, const std::optional<std::string>& pathString) const;

std::shared_ptr<RequireSuggester> requireSuggester;
};

struct NullFileResolver : FileResolver
Expand Down
29 changes: 27 additions & 2 deletions Analysis/include/Luau/FragmentAutocomplete.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,28 @@ namespace Luau
{
struct FrontendOptions;

enum class FragmentAutocompleteWaypoint
{
ParseFragmentEnd,
CloneModuleStart,
CloneModuleEnd,
DfgBuildEnd,
CloneAndSquashScopeStart,
CloneAndSquashScopeEnd,
ConstraintSolverStart,
ConstraintSolverEnd,
TypecheckFragmentEnd,
AutocompleteEnd,
COUNT,
};

class IFragmentAutocompleteReporter
{
public:
virtual void reportWaypoint(FragmentAutocompleteWaypoint) = 0;
virtual void reportFragmentString(std::string_view) = 0;
};

enum class FragmentTypeCheckStatus
{
SkipAutocomplete,
Expand Down Expand Up @@ -70,7 +92,8 @@ std::pair<FragmentTypeCheckStatus, FragmentTypeCheckResult> typecheckFragment(
const Position& cursorPos,
std::optional<FrontendOptions> opts,
std::string_view src,
std::optional<Position> fragmentEndPosition
std::optional<Position> fragmentEndPosition,
IFragmentAutocompleteReporter* reporter = nullptr
);

FragmentAutocompleteResult fragmentAutocomplete(
Expand All @@ -80,7 +103,8 @@ FragmentAutocompleteResult fragmentAutocomplete(
Position cursorPosition,
std::optional<FrontendOptions> opts,
StringCompletionCallback callback,
std::optional<Position> fragmentEndPosition = std::nullopt
std::optional<Position> fragmentEndPosition = std::nullopt,
IFragmentAutocompleteReporter* reporter = nullptr
);

enum class FragmentAutocompleteStatus
Expand All @@ -102,6 +126,7 @@ struct FragmentContext
const ParseResult& freshParse;
std::optional<FrontendOptions> opts;
std::optional<Position> DEPRECATED_fragmentEndPosition;
IFragmentAutocompleteReporter* reporter = nullptr;
};

/**
Expand Down
9 changes: 0 additions & 9 deletions Analysis/include/Luau/Quantify.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,4 @@ struct OrderedMap
}
};

struct QuantifierResult
{
TypeId result;
OrderedMap<TypeId, TypeId> insertedGenerics;
OrderedMap<TypePackId, TypePackId> insertedGenericPacks;
};

std::optional<QuantifierResult> quantify(TypeArena* arena, TypeId ty, Scope* scope);

} // namespace Luau
8 changes: 7 additions & 1 deletion Analysis/src/AutocompleteCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ LUAU_FASTINT(LuauTypeInferIterationLimit)
LUAU_FASTINT(LuauTypeInferRecursionLimit)
LUAU_FASTFLAGVARIABLE(DebugLuauMagicVariableNames)

LUAU_FASTFLAG(LuauExposeRequireByStringAutocomplete)

LUAU_FASTFLAGVARIABLE(LuauAutocompleteRefactorsForIncrementalAutocomplete)

LUAU_FASTFLAGVARIABLE(LuauAutocompleteUsesModuleForTypeCompatibility)
Expand Down Expand Up @@ -1519,10 +1521,14 @@ static std::optional<AutocompleteEntryMap> convertRequireSuggestionsToAutocomple
return std::nullopt;

AutocompleteEntryMap result;
for (const RequireSuggestion& suggestion : *suggestions)
for (RequireSuggestion& suggestion : *suggestions)
{
AutocompleteEntry entry = {AutocompleteEntryKind::RequirePath};
entry.insertText = std::move(suggestion.fullPath);
if (FFlag::LuauExposeRequireByStringAutocomplete)
{
entry.tags = std::move(suggestion.tags);
}
result[std::move(suggestion.label)] = std::move(entry);
}
return result;
Expand Down
29 changes: 19 additions & 10 deletions Analysis/src/Clone.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/Clone.h"

#include "Luau/Common.h"
#include "Luau/NotNull.h"
#include "Luau/Type.h"
#include "Luau/TypePack.h"
Expand All @@ -12,6 +13,8 @@ LUAU_FASTFLAG(LuauFreezeIgnorePersistent)

// For each `Luau::clone` call, we will clone only up to N amount of types _and_ packs, as controlled by this limit.
LUAU_FASTINTVARIABLE(LuauTypeCloneIterationLimit, 100'000)
LUAU_FASTFLAGVARIABLE(LuauClonedTableAndFunctionTypesMustHaveScopes)
LUAU_FASTFLAGVARIABLE(LuauDoNotClonePersistentBindings)

namespace Luau
{
Expand Down Expand Up @@ -477,7 +480,7 @@ class TypeCloner

class FragmentAutocompleteTypeCloner final : public TypeCloner
{
Scope* freeTypeReplacementScope = nullptr;
Scope* replacementForNullScope = nullptr;

public:
FragmentAutocompleteTypeCloner(
Expand All @@ -487,12 +490,12 @@ class FragmentAutocompleteTypeCloner final : public TypeCloner
NotNull<SeenTypePacks> packs,
TypeId forceTy,
TypePackId forceTp,
Scope* freeTypeReplacementScope
Scope* replacementForNullScope
)
: TypeCloner(arena, builtinTypes, types, packs, forceTy, forceTp)
, freeTypeReplacementScope(freeTypeReplacementScope)
, replacementForNullScope(replacementForNullScope)
{
LUAU_ASSERT(freeTypeReplacementScope);
LUAU_ASSERT(replacementForNullScope);
}

TypeId shallowClone(TypeId ty) override
Expand All @@ -512,12 +515,18 @@ class FragmentAutocompleteTypeCloner final : public TypeCloner
generic->scope = nullptr;
else if (auto free = getMutable<FreeType>(target))
{
free->scope = freeTypeReplacementScope;
free->scope = replacementForNullScope;
}
else if (auto tt = getMutable<TableType>(target))
{
if (FFlag::LuauClonedTableAndFunctionTypesMustHaveScopes)
tt->scope = replacementForNullScope;
}
else if (auto fn = getMutable<FunctionType>(target))
fn->scope = nullptr;
else if (auto table = getMutable<TableType>(target))
table->scope = nullptr;
{
if (FFlag::LuauClonedTableAndFunctionTypesMustHaveScopes)
fn->scope = replacementForNullScope;
}

(*types)[ty] = target;
queue.emplace_back(target);
Expand All @@ -538,7 +547,7 @@ class FragmentAutocompleteTypeCloner final : public TypeCloner
if (auto generic = getMutable<GenericTypePack>(target))
generic->scope = nullptr;
else if (auto free = getMutable<FreeTypePack>(target))
free->scope = freeTypeReplacementScope;
free->scope = replacementForNullScope;

(*packs)[tp] = target;
queue.emplace_back(target);
Expand Down Expand Up @@ -728,7 +737,7 @@ Binding cloneIncremental(const Binding& binding, TypeArena& dest, CloneState& cl
b.deprecatedSuggestion = binding.deprecatedSuggestion;
b.documentationSymbol = binding.documentationSymbol;
b.location = binding.location;
b.typeId = cloner.clone(binding.typeId);
b.typeId = FFlag::LuauDoNotClonePersistentBindings && binding.typeId->persistent ? binding.typeId : cloner.clone(binding.typeId);

return b;
}
Expand Down
11 changes: 10 additions & 1 deletion Analysis/src/ConstraintGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
LUAU_FASTFLAGVARIABLE(LuauTrackInteriorFreeTypesOnScope)
LUAU_FASTFLAGVARIABLE(LuauDeferBidirectionalInferenceForTableAssignment)
LUAU_FASTFLAGVARIABLE(LuauUngeneralizedTypesForRecursiveFunctions)
LUAU_FASTFLAGVARIABLE(LuauGlobalSelfAssignmentCycle)

LUAU_FASTFLAG(LuauFreeTypesMustHaveBounds)
LUAU_FASTFLAGVARIABLE(LuauInferLocalTypesInMultipleAssignments)
LUAU_FASTFLAGVARIABLE(LuauDoNotLeakNilInRefinement)
LUAU_FASTFLAGVARIABLE(LuauExtraFollows)

namespace Luau
{
Expand Down Expand Up @@ -2082,7 +2084,7 @@ InferencePack ConstraintGenerator::checkPack(const ScopePtr& scope, AstExprCall*
{
std::vector<TypeId> unpackedTypes;
if (args.size() > 0)
target = args[0];
target = FFlag::LuauExtraFollows ? follow(args[0]) : args[0];
else
{
target = arena->addType(BlockedType{});
Expand Down Expand Up @@ -2891,6 +2893,13 @@ void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprGlobal* glob
DefId def = dfg->getDef(global);
rootScope->lvalueTypes[def] = rhsType;

if (FFlag::LuauGlobalSelfAssignmentCycle)
{
// Ignore possible self-assignment, it doesn't create a new constraint
if (annotatedTy == follow(rhsType))
return;
}

// Sketchy: We're specifically looking for BlockedTypes that were
// initially created by ConstraintGenerator::prepopulateGlobalScope.
if (auto bt = get<BlockedType>(follow(*annotatedTy)); bt && !bt->getOwner())
Expand Down
43 changes: 24 additions & 19 deletions Analysis/src/ConstraintSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ LUAU_FASTFLAG(LuauTrackInteriorFreeTypesOnScope)
LUAU_FASTFLAGVARIABLE(LuauTrackInteriorFreeTablesOnScope)
LUAU_FASTFLAGVARIABLE(LuauPrecalculateMutatedFreeTypes2)
LUAU_FASTFLAGVARIABLE(DebugLuauGreedyGeneralization)
LUAU_FASTFLAG(LuauSearchForRefineableType)

namespace Luau
{
Expand Down Expand Up @@ -907,26 +908,16 @@ bool ConstraintSolver::tryDispatch(const GeneralizationConstraint& c, NotNull<co
else if (get<PendingExpansionType>(generalizedType))
return block(generalizedType, constraint);

std::optional<QuantifierResult> generalized;

std::optional<TypeId> generalizedTy = generalize(NotNull{arena}, builtinTypes, constraint->scope, generalizedTypes, c.sourceType);
if (generalizedTy)
generalized = QuantifierResult{*generalizedTy}; // FIXME insertedGenerics and insertedGenericPacks
else
if (!generalizedTy)
reportError(CodeTooComplex{}, constraint->location);

if (generalized)
if (generalizedTy)
{
if (get<BlockedType>(generalizedType))
bind(constraint, generalizedType, generalized->result);
bind(constraint, generalizedType, *generalizedTy);
else
unify(constraint, generalizedType, generalized->result);

for (auto [free, gen] : generalized->insertedGenerics.pairings)
unify(constraint, free, gen);

for (auto [free, gen] : generalized->insertedGenericPacks.pairings)
unify(constraint, free, gen);
unify(constraint, generalizedType, *generalizedTy);
}
else
{
Expand Down Expand Up @@ -1356,15 +1347,29 @@ void ConstraintSolver::fillInDiscriminantTypes(NotNull<const Constraint> constra
if (!ty)
continue;

// If the discriminant type has been transmuted, we need to unblock them.
if (!isBlocked(*ty))
if (FFlag::LuauSearchForRefineableType)
{
if (isBlocked(*ty))
// We bind any unused discriminants to the `*no-refine*` type indicating that it can be safely ignored.
emplaceType<BoundType>(asMutable(follow(*ty)), builtinTypes->noRefineType);

// We also need to unconditionally unblock these types, otherwise
// you end up with funky looking "Blocked on *no-refine*."
unblock(*ty, constraint->location);
continue;
}
else
{

// We bind any unused discriminants to the `*no-refine*` type indicating that it can be safely ignored.
emplaceType<BoundType>(asMutable(follow(*ty)), builtinTypes->noRefineType);
// If the discriminant type has been transmuted, we need to unblock them.
if (!isBlocked(*ty))
{
unblock(*ty, constraint->location);
continue;
}

// We bind any unused discriminants to the `*no-refine*` type indicating that it can be safely ignored.
emplaceType<BoundType>(asMutable(follow(*ty)), builtinTypes->noRefineType);
}
}
}

Expand Down
Loading