Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 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
2eefa3f
Sync to upstream/release/666
vrn-sn Mar 21, 2025
a371d16
Merge branch 'master' into merge
vrn-sn Mar 21, 2025
716f524
Merge branch 'upstream' into merge
vrn-sn Mar 21, 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
1 change: 1 addition & 0 deletions Analysis/include/Luau/BuiltinDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Property makeProperty(TypeId ty, std::optional<std::string> documentationSymbol
void assignPropDocumentationSymbols(TableType::Props& props, const std::string& baseName);

std::string getBuiltinDefinitionSource();
std::string getTypeFunctionDefinitionSource();

void addGlobalBinding(GlobalTypes& globals, const std::string& name, TypeId ty, const std::string& packageName);
void addGlobalBinding(GlobalTypes& globals, const std::string& name, Binding binding);
Expand Down
4 changes: 4 additions & 0 deletions Analysis/include/Luau/ConstraintGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,15 @@ struct ConstraintGenerator

// Needed to register all available type functions for execution at later stages.
NotNull<TypeFunctionRuntime> typeFunctionRuntime;
DenseHashMap<const AstStatTypeFunction*, ScopePtr> astTypeFunctionEnvironmentScopes{nullptr};

// Needed to resolve modules to make 'require' import types properly.
NotNull<ModuleResolver> moduleResolver;
// Occasionally constraint generation needs to produce an ICE.
const NotNull<InternalErrorReporter> ice;

ScopePtr globalScope;
ScopePtr typeFunctionScope;

std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope;
std::vector<RequireCycle> requireCycles;
Expand All @@ -140,6 +143,7 @@ struct ConstraintGenerator
NotNull<BuiltinTypes> builtinTypes,
NotNull<InternalErrorReporter> ice,
const ScopePtr& globalScope,
const ScopePtr& typeFunctionScope,
std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope,
DcrLogger* logger,
NotNull<DataFlowGraph> dfg,
Expand Down
2 changes: 2 additions & 0 deletions Analysis/include/Luau/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ ModulePtr check(
NotNull<ModuleResolver> moduleResolver,
NotNull<FileResolver> fileResolver,
const ScopePtr& globalScope,
const ScopePtr& typeFunctionScope,
std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope,
FrontendOptions options,
TypeCheckLimits limits
Expand All @@ -319,6 +320,7 @@ ModulePtr check(
NotNull<ModuleResolver> moduleResolver,
NotNull<FileResolver> fileResolver,
const ScopePtr& globalScope,
const ScopePtr& typeFunctionScope,
std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope,
FrontendOptions options,
TypeCheckLimits limits,
Expand Down
3 changes: 2 additions & 1 deletion Analysis/include/Luau/Generalization.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ std::optional<TypeId> generalize(
NotNull<TypeArena> arena,
NotNull<BuiltinTypes> builtinTypes,
NotNull<Scope> scope,
NotNull<DenseHashSet<TypeId>> bakedTypes,
NotNull<DenseHashSet<TypeId>> cachedTypes,
TypeId ty,
/* avoid sealing tables*/ bool avoidSealingTables = false
);

}
2 changes: 2 additions & 0 deletions Analysis/include/Luau/GlobalTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ struct GlobalTypes

TypeArena globalTypes;
SourceModule globalNames; // names for symbols entered into globalScope

ScopePtr globalScope; // shared by all modules
ScopePtr globalTypeFunctionScope; // shared by all modules
};

} // namespace Luau
5 changes: 4 additions & 1 deletion Analysis/include/Luau/Scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct Scope
explicit Scope(TypePackId returnType); // root scope
explicit Scope(const ScopePtr& parent, int subLevel = 0); // child scope. Parent must not be nullptr.

const ScopePtr parent; // null for the root
ScopePtr parent; // null for the root

// All the children of this scope.
std::vector<NotNull<Scope>> children;
Expand All @@ -59,6 +59,8 @@ struct Scope

std::optional<TypeId> lookup(Symbol sym) const;
std::optional<TypeId> lookupUnrefinedType(DefId def) const;

std::optional<TypeId> lookupRValueRefinementType(DefId def) const;
std::optional<TypeId> lookup(DefId def) const;
std::optional<std::pair<TypeId, Scope*>> lookupEx(DefId def);
std::optional<std::pair<Binding*, Scope*>> lookupEx(Symbol sym);
Expand All @@ -71,6 +73,7 @@ struct Scope

// WARNING: This function linearly scans for a string key of equal value! It is thus O(n**2)
std::optional<Binding> linearSearchForBinding(const std::string& name, bool traverseScopeChain = true) const;
std::optional<std::pair<Symbol, Binding>> linearSearchForBindingPair(const std::string& name, bool traverseScopeChain) const;

RefinementMap refinements;

Expand Down
1 change: 0 additions & 1 deletion Analysis/include/Luau/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,6 @@ struct UserDefinedFunctionData
AstStatTypeFunction* definition = nullptr;

DenseHashMap<Name, std::pair<AstStatTypeFunction*, size_t>> environment{""};
DenseHashMap<Name, AstStatTypeFunction*> environment_DEPRECATED{""};
};

/**
Expand Down
21 changes: 17 additions & 4 deletions Analysis/include/Luau/TypeChecker2.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include "Luau/TypeOrPack.h"
#include "Luau/TypeUtils.h"

LUAU_FASTFLAG(LuauImproveTypePathsInErrors)

namespace Luau
{

Expand All @@ -38,18 +40,29 @@ struct Reasonings

std::string toString()
{
if (FFlag::LuauImproveTypePathsInErrors && reasons.empty())
return "";

// DenseHashSet ordering is entirely undefined, so we want to
// sort the reasons here to achieve a stable error
// stringification.
std::sort(reasons.begin(), reasons.end());
std::string allReasons;
std::string allReasons = FFlag::LuauImproveTypePathsInErrors ? "\nthis is because " : "";
bool first = true;
for (const std::string& reason : reasons)
{
if (first)
first = false;
if (FFlag::LuauImproveTypePathsInErrors)
{
if (reasons.size() > 1)
allReasons += "\n\t * ";
}
else
allReasons += "\n\t";
{
if (first)
first = false;
else
allReasons += "\n\t";
}

allReasons += reason;
}
Expand Down
3 changes: 3 additions & 0 deletions Analysis/include/Luau/TypeFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ struct TypeFunctionRuntime
// Evaluation of type functions should only be performed in the absence of parse errors in the source module
bool allowEvaluation = true;

// Root scope in which the type function operates in, set up by ConstraintGenerator
ScopePtr rootScope;

// Output created by 'print' function
std::vector<std::string> messages;

Expand Down
2 changes: 0 additions & 2 deletions Analysis/include/Luau/TypeFunctionRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,6 @@ struct TypeFunctionClassType
std::optional<TypeFunctionTypeId> writeParent;

TypeId classTy;

std::string name_DEPRECATED;
};

struct TypeFunctionGenericType
Expand Down
8 changes: 1 addition & 7 deletions Analysis/include/Luau/TypeFunctionRuntimeBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,8 @@ struct TypeFunctionRuntimeBuilderState
{
NotNull<TypeFunctionContext> ctx;

// Mapping of class name to ClassType
// Invariant: users can not create a new class types -> any class types that get deserialized must have been an argument to the type function
// Using this invariant, whenever a ClassType is serialized, we can put it into this map
// whenever a ClassType is deserialized, we can use this map to return the corresponding value
DenseHashMap<std::string, TypeId> classesSerialized_DEPRECATED{{}};

// List of errors that occur during serialization/deserialization
// At every iteration of serialization/deserialzation, if this list.size() != 0, we halt the process
// At every iteration of serialization/deserialization, if this list.size() != 0, we halt the process
std::vector<std::string> errors{};

TypeFunctionRuntimeBuilderState(NotNull<TypeFunctionContext> ctx)
Expand Down
13 changes: 13 additions & 0 deletions Analysis/include/Luau/TypePath.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,19 @@ struct Property
/// element.
struct Index
{
enum class Variant
{
Pack,
Union,
Intersection
};

/// The 0-based index to use for the lookup.
size_t index;

/// The sort of thing we're indexing from, this is used in stringifying the type path for errors.
Variant variant;

bool operator==(const Index& other) const;
};

Expand Down Expand Up @@ -205,6 +215,9 @@ using Path = TypePath::Path;
/// terribly clear to end users of the Luau type system.
std::string toString(const TypePath::Path& path, bool prefixDot = false);

/// Converts a Path to a human readable string for error reporting.
std::string toStringHuman(const TypePath::Path& path);

std::optional<TypeOrPack> traverse(TypeId root, const Path& path, NotNull<BuiltinTypes> builtinTypes);
std::optional<TypeOrPack> traverse(TypePackId root, const Path& path, NotNull<BuiltinTypes> builtinTypes);

Expand Down
5 changes: 5 additions & 0 deletions Analysis/src/AstJsonEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,11 @@ struct AstJsonEncoder : public AstVisitor
);
}

void write(class AstTypeOptional* node)
{
writeNode(node, "AstTypeOptional", [&]() {});
}

void write(class AstTypeUnion* node)
{
writeNode(
Expand Down
16 changes: 16 additions & 0 deletions Analysis/src/AutocompleteCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ LUAU_FASTFLAG(LuauExposeRequireByStringAutocomplete)
LUAU_FASTFLAGVARIABLE(LuauAutocompleteRefactorsForIncrementalAutocomplete)

LUAU_FASTFLAGVARIABLE(LuauAutocompleteUsesModuleForTypeCompatibility)
LUAU_FASTFLAGVARIABLE(LuauAutocompleteUnionCopyPreviousSeen)

static const std::unordered_set<std::string> kStatementStartingKeywords =
{"while", "if", "local", "repeat", "function", "do", "for", "return", "break", "continue", "type", "export"};
Expand Down Expand Up @@ -484,6 +485,21 @@ static void autocompleteProps(
AutocompleteEntryMap inner;
std::unordered_set<TypeId> innerSeen;

// If we don't do this, and we have the misfortune of receiving a
// recursive union like:
//
// t1 where t1 = t1 | Class
//
// Then we are on a one way journey to a stack overflow.
if (FFlag::LuauAutocompleteUnionCopyPreviousSeen)
{
for (auto ty: seen)
{
if (is<UnionType, IntersectionType>(ty))
innerSeen.insert(ty);
}
}

if (isNil(*iter))
{
++iter;
Expand Down
94 changes: 85 additions & 9 deletions Analysis/src/BuiltinDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ LUAU_FASTFLAG(LuauSolverV2)
LUAU_FASTFLAGVARIABLE(LuauStringFormatErrorSuppression)
LUAU_FASTFLAGVARIABLE(LuauTableCloneClonesType3)
LUAU_FASTFLAG(LuauTrackInteriorFreeTypesOnScope)
LUAU_FASTFLAGVARIABLE(LuauFreezeIgnorePersistent)
LUAU_FASTFLAGVARIABLE(LuauFollowTableFreeze)
LUAU_FASTFLAGVARIABLE(LuauUserTypeFunTypecheck)

namespace Luau
{
Expand Down Expand Up @@ -288,6 +288,22 @@ void assignPropDocumentationSymbols(TableType::Props& props, const std::string&
}
}

static void finalizeGlobalBindings(ScopePtr scope)
{
LUAU_ASSERT(FFlag::LuauUserTypeFunTypecheck);

for (const auto& pair : scope->bindings)
{
persist(pair.second.typeId);

if (TableType* ttv = getMutable<TableType>(pair.second.typeId))
{
if (!ttv->name)
ttv->name = "typeof(" + toString(pair.first) + ")";
}
}
}

void registerBuiltinGlobals(Frontend& frontend, GlobalTypes& globals, bool typeCheckForAutocomplete)
{
LUAU_ASSERT(!globals.globalTypes.types.isFrozen());
Expand Down Expand Up @@ -399,14 +415,21 @@ void registerBuiltinGlobals(Frontend& frontend, GlobalTypes& globals, bool typeC
// clang-format on
}

for (const auto& pair : globals.globalScope->bindings)
if (FFlag::LuauUserTypeFunTypecheck)
{
persist(pair.second.typeId);

if (TableType* ttv = getMutable<TableType>(pair.second.typeId))
finalizeGlobalBindings(globals.globalScope);
}
else
{
for (const auto& pair : globals.globalScope->bindings)
{
if (!ttv->name)
ttv->name = "typeof(" + toString(pair.first) + ")";
persist(pair.second.typeId);

if (TableType* ttv = getMutable<TableType>(pair.second.typeId))
{
if (!ttv->name)
ttv->name = "typeof(" + toString(pair.first) + ")";
}
}
}

Expand Down Expand Up @@ -467,6 +490,59 @@ void registerBuiltinGlobals(Frontend& frontend, GlobalTypes& globals, bool typeC
TypeId requireTy = getGlobalBinding(globals, "require");
attachTag(requireTy, kRequireTagName);
attachMagicFunction(requireTy, std::make_shared<MagicRequire>());

if (FFlag::LuauUserTypeFunTypecheck)
{
// Global scope cannot be the parent of the type checking environment because it can be changed by the embedder
globals.globalTypeFunctionScope->exportedTypeBindings = globals.globalScope->exportedTypeBindings;
globals.globalTypeFunctionScope->builtinTypeNames = globals.globalScope->builtinTypeNames;

// Type function runtime also removes a few standard libraries and globals, so we will take only the ones that are defined
static const char* typeFunctionRuntimeBindings[] = {
// Libraries
"math",
"table",
"string",
"bit32",
"utf8",
"buffer",

// Globals
"assert",
"error",
"print",
"next",
"ipairs",
"pairs",
"select",
"unpack",
"getmetatable",
"setmetatable",
"rawget",
"rawset",
"rawlen",
"rawequal",
"tonumber",
"tostring",
"type",
"typeof",
};

for (auto& name : typeFunctionRuntimeBindings)
{
AstName astName = globals.globalNames.names->get(name);
LUAU_ASSERT(astName.value);

globals.globalTypeFunctionScope->bindings[astName] = globals.globalScope->bindings[astName];
}

LoadDefinitionFileResult typeFunctionLoadResult = frontend.loadDefinitionFile(
globals, globals.globalTypeFunctionScope, getTypeFunctionDefinitionSource(), "@luau", /* captureComments */ false, false
);
LUAU_ASSERT(typeFunctionLoadResult.success);

finalizeGlobalBindings(globals.globalTypeFunctionScope);
}
}

static std::vector<TypeId> parseFormatString(NotNull<BuiltinTypes> builtinTypes, const char* data, size_t size)
Expand Down Expand Up @@ -1444,7 +1520,7 @@ bool MagicClone::infer(const MagicFunctionCallContext& context)
return false;

CloneState cloneState{context.solver->builtinTypes};
TypeId resultType = shallowClone(inputType, *arena, cloneState, /* ignorePersistent */ FFlag::LuauFreezeIgnorePersistent);
TypeId resultType = shallowClone(inputType, *arena, cloneState, /* ignorePersistent */ true);

if (auto tableType = getMutable<TableType>(resultType))
{
Expand Down Expand Up @@ -1481,7 +1557,7 @@ static std::optional<TypeId> freezeTable(TypeId inputType, const MagicFunctionCa
{
// Clone the input type, this will become our final result type after we mutate it.
CloneState cloneState{context.solver->builtinTypes};
TypeId resultType = shallowClone(inputType, *arena, cloneState, /* ignorePersistent */ FFlag::LuauFreezeIgnorePersistent);
TypeId resultType = shallowClone(inputType, *arena, cloneState, /* ignorePersistent */ true);
auto tableTy = getMutable<TableType>(resultType);
// `clone` should not break this.
LUAU_ASSERT(tableTy);
Expand Down
Loading