Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 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
d4c2c64
Sync to upstream/release/667
ayoungbloodrbx Mar 28, 2025
9ae5f37
Merge branch 'master' into merge
ayoungbloodrbx Mar 28, 2025
08f07a1
Merge branch 'upstream' into merge
ayoungbloodrbx Mar 28, 2025
d9e8ded
Sync to upstream/release/668
Apr 4, 2025
f85407b
Merge branch 'master' into merge
Apr 4, 2025
6e90f90
Merge branch 'upstream' into merge
Apr 4, 2025
d2969f0
Disable failing tests until fixes have been found.
Apr 4, 2025
7a6b561
Sync to upstream/release/669
menarulalam Apr 11, 2025
c3f6c48
Merge branch 'master' into merge
menarulalam Apr 11, 2025
567876e
Merge branch 'upstream' into merge
menarulalam Apr 11, 2025
afaceca
Add missing MIT License header
vrn-sn Apr 11, 2025
8f61efb
Make RequireNavigator depend on Config (hacky, will improve later)
vrn-sn Apr 12, 2025
217c14d
Sync to upstream/release/670
Vighnesh-V Apr 18, 2025
3d1ac20
Merge branch 'master' into merge
Vighnesh-V Apr 18, 2025
2f6fb98
Merge branch 'upstream' into merge
Vighnesh-V Apr 18, 2025
500f8d4
update test cases to use NonReentrantGeneralization2
Vighnesh-V Apr 18, 2025
2b7a89d
Sync to upstream/release/671
andyfriesen Apr 25, 2025
e9ef63d
Merge branch 'master' into merge
andyfriesen Apr 25, 2025
1b78172
Merge branch 'upstream' into merge
andyfriesen Apr 25, 2025
18b36c1
Delete .clang-tidy
andyfriesen Apr 25, 2025
3adf258
Sync to upstream/release/672
aatxe May 2, 2025
7d27130
Merge branch 'master' into merge
aatxe May 2, 2025
27a8fd0
Merge branch 'upstream' into merge
aatxe May 2, 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
4 changes: 0 additions & 4 deletions Analysis/include/Luau/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ struct FreeType
// This one got promoted to explicit
explicit FreeType(Scope* scope, TypeId lowerBound, TypeId upperBound, Polarity polarity = Polarity::Unknown);
explicit FreeType(Scope* scope, TypeLevel level, TypeId lowerBound, TypeId upperBound);
// Old constructors
explicit FreeType(TypeLevel level);
explicit FreeType(Scope* scope);
FreeType(Scope* scope, TypeLevel level);

int index;
TypeLevel level;
Expand Down
4 changes: 0 additions & 4 deletions Analysis/include/Luau/TypeArena.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ struct TypeArena
TypeId freshType(NotNull<BuiltinTypes> builtins, Scope* scope);
TypeId freshType(NotNull<BuiltinTypes> builtins, Scope* scope, TypeLevel level);

TypeId freshType_DEPRECATED(TypeLevel level);
TypeId freshType_DEPRECATED(Scope* scope);
TypeId freshType_DEPRECATED(Scope* scope, TypeLevel level);

TypePackId freshTypePack(Scope* scope, Polarity polarity = Polarity::Unknown);

TypePackId addTypePack(std::initializer_list<TypeId> types);
Expand Down
2 changes: 2 additions & 0 deletions Analysis/include/Luau/TypePack.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ TypePackIterator begin(TypePackId tp);
TypePackIterator begin(TypePackId tp, const TxnLog* log);
TypePackIterator end(TypePackId tp);

TypePackId getTail(TypePackId tp);

using SeenSet = std::set<std::pair<const void*, const void*>>;

bool areEqual(SeenSet& seen, const TypePackVar& lhs, const TypePackVar& rhs);
Expand Down
16 changes: 8 additions & 8 deletions Analysis/src/AstJsonEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,26 +475,26 @@ struct AstJsonEncoder : public AstVisitor
writeRaw("}");
}

void write(const AstGenericType& genericType)
void write(class AstGenericType* genericType)
{
writeRaw("{");
bool c = pushComma();
writeType("AstGenericType");
write("name", genericType.name);
if (genericType.defaultValue)
write("luauType", genericType.defaultValue);
write("name", genericType->name);
if (genericType->defaultValue)
write("luauType", genericType->defaultValue);
popComma(c);
writeRaw("}");
}

void write(const AstGenericTypePack& genericTypePack)
void write(class AstGenericTypePack* genericTypePack)
{
writeRaw("{");
bool c = pushComma();
writeType("AstGenericTypePack");
write("name", genericTypePack.name);
if (genericTypePack.defaultValue)
write("luauType", genericTypePack.defaultValue);
write("name", genericTypePack->name);
if (genericTypePack->defaultValue)
write("luauType", genericTypePack->defaultValue);
popComma(c);
writeRaw("}");
}
Expand Down
4 changes: 1 addition & 3 deletions Analysis/src/BuiltinDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
LUAU_FASTFLAG(LuauSolverV2)
LUAU_FASTFLAG(LuauNonReentrantGeneralization2)
LUAU_FASTFLAGVARIABLE(LuauTableCloneClonesType3)
LUAU_FASTFLAGVARIABLE(LuauFollowTableFreeze)
LUAU_FASTFLAGVARIABLE(LuauUserTypeFunTypecheck)
LUAU_FASTFLAGVARIABLE(LuauMagicFreezeCheckBlocked)
LUAU_FASTFLAGVARIABLE(LuauFormatUseLastPosition)
Expand Down Expand Up @@ -1550,8 +1549,7 @@ bool MagicClone::infer(const MagicFunctionCallContext& context)
static std::optional<TypeId> freezeTable(TypeId inputType, const MagicFunctionCallContext& context)
{
TypeArena* arena = context.solver->arena;
if (FFlag::LuauFollowTableFreeze)
inputType = follow(inputType);
inputType = follow(inputType);
if (auto mt = get<MetatableType>(inputType))
{
std::optional<TypeId> frozenTable = freezeTable(mt->table, context);
Expand Down
19 changes: 8 additions & 11 deletions Analysis/src/Constraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,7 @@ struct ReferenceCountInitializer : TypeOnceVisitor

bool visit(TypeId, const TypeFunctionInstanceType&) override
{
// We do not consider reference counted types that are inside a type
// function to be part of the reachable reference counted types.
// Otherwise, code can be constructed in just the right way such
// that two type functions both claim to mutate a free type, which
// prevents either type function from trying to generalize it, so
// we potentially get stuck.
//
// The default behavior here is `true` for "visit the child types"
// of this type, hence:
return false;
return FFlag::DebugLuauGreedyGeneralization;
}
};

Expand Down Expand Up @@ -130,8 +121,10 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
}
else if (auto hic = get<HasIndexerConstraint>(*this))
{
if (FFlag::DebugLuauGreedyGeneralization)
rci.traverse(hic->subjectType);
rci.traverse(hic->resultType);
// `HasIndexerConstraint` should not mutate `subjectType` or `indexType`.
// `HasIndexerConstraint` should not mutate `indexType`.
}
else if (auto apc = get<AssignPropConstraint>(*this))
{
Expand All @@ -150,6 +143,10 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
rci.traverse(ty);
// `UnpackConstraint` should not mutate `sourcePack`.
}
else if (auto rpc = get<ReduceConstraint>(*this); FFlag::DebugLuauGreedyGeneralization && rpc)
{
rci.traverse(rpc->ty);
}
else if (auto rpc = get<ReducePackConstraint>(*this))
{
rci.traverse(rpc->tp);
Expand Down
42 changes: 27 additions & 15 deletions Analysis/src/ConstraintGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ LUAU_FASTFLAG(DebugLuauGreedyGeneralization)

LUAU_FASTFLAGVARIABLE(LuauUngeneralizedTypesForRecursiveFunctions)

LUAU_FASTFLAG(LuauFreeTypesMustHaveBounds)
LUAU_FASTFLAG(LuauUserTypeFunTypecheck)
LUAU_FASTFLAGVARIABLE(LuauRetainDefinitionAliasLocations)

Expand All @@ -52,6 +51,7 @@ LUAU_FASTFLAG(LuauGlobalVariableModuleIsolation)

LUAU_FASTFLAGVARIABLE(LuauNoTypeFunctionsNamedTypeOf)
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
LUAU_FASTFLAG(LuauDoNotAddUpvalueTypesToLocalType)

namespace Luau
{
Expand Down Expand Up @@ -1409,7 +1409,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatLocalFuncti
FunctionSignature sig = checkFunctionSignature(scope, function->func, /* expectedType */ std::nullopt, function->name->location);
sig.bodyScope->bindings[function->name] = Binding{sig.signature, function->name->location};

bool sigFullyDefined = !hasFreeType(sig.signature);
bool sigFullyDefined = FFlag::DebugLuauGreedyGeneralization ? false : !hasFreeType(sig.signature);
if (sigFullyDefined)
emplaceType<BoundType>(asMutable(functionType), sig.signature);

Expand Down Expand Up @@ -1471,7 +1471,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatFunction* f

Checkpoint start = checkpoint(this);
FunctionSignature sig = checkFunctionSignature(scope, function->func, /* expectedType */ std::nullopt, function->name->location);
bool sigFullyDefined = !hasFreeType(sig.signature);
bool sigFullyDefined = FFlag::DebugLuauGreedyGeneralization ? false : !hasFreeType(sig.signature);

DefId def = dfg->getDef(function->name);

Expand Down Expand Up @@ -2389,9 +2389,12 @@ InferencePack ConstraintGenerator::checkPack(const ScopePtr& scope, AstExprCall*
this,
[checkConstraint, callConstraint](const ConstraintPtr& constraint)
{
constraint->dependencies.emplace_back(checkConstraint);
if (!(FFlag::DebugLuauGreedyGeneralization && get<PrimitiveTypeConstraint>(*constraint)))
{
constraint->dependencies.emplace_back(checkConstraint);

callConstraint->dependencies.emplace_back(constraint.get());
callConstraint->dependencies.emplace_back(constraint.get());
}
}
);

Expand Down Expand Up @@ -2496,8 +2499,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprConstantStrin
}
else
{
FreeType ft =
FFlag::LuauFreeTypesMustHaveBounds ? FreeType{scope.get(), builtinTypes->neverType, builtinTypes->unknownType} : FreeType{scope.get()};
FreeType ft = FreeType{scope.get(), builtinTypes->neverType, builtinTypes->unknownType};
ft.lowerBound = arena->addType(SingletonType{StringSingleton{std::string{string->value.data, string->value.size}}});
ft.upperBound = builtinTypes->stringType;
freeTy = arena->addType(ft);
Expand All @@ -2524,8 +2526,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprConstantBool*
}
else
{
FreeType ft =
FFlag::LuauFreeTypesMustHaveBounds ? FreeType{scope.get(), builtinTypes->neverType, builtinTypes->unknownType} : FreeType{scope.get()};
FreeType ft = FreeType{scope.get(), builtinTypes->neverType, builtinTypes->unknownType};
ft.lowerBound = singletonType;
ft.upperBound = builtinTypes->booleanType;
freeTy = arena->addType(ft);
Expand Down Expand Up @@ -3076,7 +3077,7 @@ void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprLocal* local
if (ty)
{
TypeIds* localDomain = localTypes.find(*ty);
if (localDomain)
if (localDomain && !(FFlag::LuauDoNotAddUpvalueTypesToLocalType && local->upvalue))
localDomain->insert(rhsType);
}
else
Expand Down Expand Up @@ -3107,8 +3108,10 @@ void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprLocal* local
if (annotatedTy)
addConstraint(scope, local->location, SubtypeConstraint{rhsType, *annotatedTy});

if (TypeIds* localDomain = localTypes.find(*ty))
localDomain->insert(rhsType);
// This is vestigial.
if (!FFlag::LuauDoNotAddUpvalueTypesToLocalType)
if (TypeIds* localDomain = localTypes.find(*ty))
localDomain->insert(rhsType);
}

void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprGlobal* global, TypeId rhsType)
Expand Down Expand Up @@ -3410,13 +3413,22 @@ ConstraintGenerator::FunctionSignature ConstraintGenerator::checkFunctionSignatu
bodyScope->varargPack = std::nullopt;
}

LUAU_ASSERT(nullptr != varargPack);

if (FFlag::DebugLuauGreedyGeneralization)
{
genericTypes = argTypes;
// Some of the types in argTypes will eventually be generics, and some
// will not. The ones that are not generic will be pruned when
// GeneralizationConstraint dispatches.
genericTypes.insert(genericTypes.begin(), argTypes.begin(), argTypes.end());
varargPack = follow(varargPack);
returnType = follow(returnType);
if (varargPack == returnType)
genericTypePacks = {varargPack};
else
genericTypePacks = {varargPack, returnType};
}

LUAU_ASSERT(nullptr != varargPack);

// If there is both an annotation and an expected type, the annotation wins.
// Type checking will sort out any discrepancies later.
if (FFlag::LuauStoreReturnTypesAsPackOnAst && fn->returnAnnotation)
Expand Down
77 changes: 63 additions & 14 deletions Analysis/src/ConstraintSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,6 @@ void ConstraintSolver::initFreeTypeTracking()
}
maybeMutatedFreeTypes.emplace(c, maybeMutatedTypesPerConstraint);


for (NotNull<const Constraint> dep : c->dependencies)
{
block(dep, c);
Expand Down Expand Up @@ -2082,24 +2081,61 @@ bool ConstraintSolver::tryDispatch(const AssignPropConstraint& c, NotNull<const
if (auto lhsFree = getMutable<FreeType>(lhsType))
{
auto lhsFreeUpperBound = follow(lhsFree->upperBound);
if (get<TableType>(lhsFreeUpperBound) || get<MetatableType>(lhsFreeUpperBound))
lhsType = lhsFreeUpperBound;

if (FFlag::DebugLuauGreedyGeneralization)
{
const auto [blocked, maybeTy, isIndex] = lookupTableProp(constraint, lhsType, propName, ValueContext::LValue);
if (!blocked.empty())
{
for (TypeId t : blocked)
block(t, constraint);
return false;
}
else if (maybeTy)
{
bind(constraint, c.propType, isIndex ? arena->addType(UnionType{{*maybeTy, builtinTypes->nilType}}) : *maybeTy);
unify(constraint, rhsType, *maybeTy);
return true;
}
else
{
TypeId newUpperBound = arena->addType(TableType{TableState::Free, TypeLevel{}, constraint->scope});

trackInteriorFreeType(constraint->scope, newUpperBound);

TableType* upperTable = getMutable<TableType>(newUpperBound);
LUAU_ASSERT(upperTable);

upperTable->props[c.propName] = rhsType;

// Food for thought: Could we block if simplification encounters a blocked type?
lhsFree->upperBound = simplifyIntersection(constraint->scope, constraint->location, lhsFreeUpperBound, newUpperBound);

bind(constraint, c.propType, rhsType);
return true;
}
}
else
{
TypeId newUpperBound = arena->addType(TableType{TableState::Free, TypeLevel{}, constraint->scope});
if (get<TableType>(lhsFreeUpperBound) || get<MetatableType>(lhsFreeUpperBound))
lhsType = lhsFreeUpperBound;
else
{
TypeId newUpperBound = arena->addType(TableType{TableState::Free, TypeLevel{}, constraint->scope});

trackInteriorFreeType(constraint->scope, newUpperBound);
trackInteriorFreeType(constraint->scope, newUpperBound);

TableType* upperTable = getMutable<TableType>(newUpperBound);
LUAU_ASSERT(upperTable);
TableType* upperTable = getMutable<TableType>(newUpperBound);
LUAU_ASSERT(upperTable);

upperTable->props[c.propName] = rhsType;
upperTable->props[c.propName] = rhsType;

// Food for thought: Could we block if simplification encounters a blocked type?
lhsFree->upperBound = simplifyIntersection(constraint->scope, constraint->location, lhsFreeUpperBound, newUpperBound);
// Food for thought: Could we block if simplification encounters a blocked type?
lhsFree->upperBound = simplifyIntersection(constraint->scope, constraint->location, lhsFreeUpperBound, newUpperBound);

bind(constraint, c.propType, rhsType);
return true;
bind(constraint, c.propType, rhsType);
return true;
}
}
}

Expand Down Expand Up @@ -2873,8 +2909,21 @@ TablePropLookupResult ConstraintSolver::lookupTableProp(
{
const TypeId upperBound = follow(ft->upperBound);

if (get<TableType>(upperBound) || get<PrimitiveType>(upperBound))
return lookupTableProp(constraint, upperBound, propName, context, inConditional, suppressSimplification, seen);
if (FFlag::DebugLuauGreedyGeneralization)
{
if (get<TableType>(upperBound) || get<PrimitiveType>(upperBound))
{
TablePropLookupResult res = lookupTableProp(constraint, upperBound, propName, context, inConditional, suppressSimplification, seen);
// If the upper bound is a table that already has the property, we don't need to extend its bounds.
if (res.propType || get<PrimitiveType>(upperBound))
return res;
}
}
else
{
if (get<TableType>(upperBound) || get<PrimitiveType>(upperBound))
return lookupTableProp(constraint, upperBound, propName, context, inConditional, suppressSimplification, seen);
}

// TODO: The upper bound could be an intersection that contains suitable tables or extern types.

Expand Down
31 changes: 23 additions & 8 deletions Analysis/src/DataFlowGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ LUAU_FASTFLAGVARIABLE(LuauPreprocessTypestatedArgument)
LUAU_FASTFLAGVARIABLE(LuauDfgScopeStackTrueReset)
LUAU_FASTFLAGVARIABLE(LuauDfgScopeStackNotNull)
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)

LUAU_FASTFLAGVARIABLE(LuauDoNotAddUpvalueTypesToLocalType)
LUAU_FASTFLAGVARIABLE(LuauDfgIfBlocksShouldRespectControlFlow)
namespace Luau
{

Expand Down Expand Up @@ -501,12 +502,26 @@ ControlFlow DataFlowGraphBuilder::visit(AstStatIf* i)
}

DfgScope* scope = FFlag::LuauDfgScopeStackNotNull ? currentScope() : currentScope_DEPRECATED();
if (thencf != ControlFlow::None && elsecf == ControlFlow::None)
join(scope, scope, elseScope);
else if (thencf == ControlFlow::None && elsecf != ControlFlow::None)
join(scope, thenScope, scope);
else if ((thencf | elsecf) == ControlFlow::None)
join(scope, thenScope, elseScope);
if (FFlag::LuauDfgIfBlocksShouldRespectControlFlow)
{
// If the control flow from the `if` or `else` block is non-linear,
// then we should assume that the _other_ branch is the one taken.
if (thencf != ControlFlow::None && elsecf == ControlFlow::None)
scope->inherit(elseScope);
else if (thencf == ControlFlow::None && elsecf != ControlFlow::None)
scope->inherit(thenScope);
else if ((thencf | elsecf) == ControlFlow::None)
join(scope, thenScope, elseScope);
}
else
{
if (thencf != ControlFlow::None && elsecf == ControlFlow::None)
join(scope, scope, elseScope);
else if (thencf == ControlFlow::None && elsecf != ControlFlow::None)
join(scope, thenScope, scope);
else if ((thencf | elsecf) == ControlFlow::None)
join(scope, thenScope, elseScope);
}

if (thencf == elsecf)
return thencf;
Expand Down Expand Up @@ -1164,7 +1179,7 @@ DefId DataFlowGraphBuilder::visitLValue(AstExprLocal* l, DefId incomingDef)
DfgScope* scope = FFlag::LuauDfgScopeStackNotNull ? currentScope() : currentScope_DEPRECATED();

// In order to avoid alias tracking, we need to clip the reference to the parent def.
if (scope->canUpdateDefinition(l->local))
if (scope->canUpdateDefinition(l->local) && !(FFlag::LuauDoNotAddUpvalueTypesToLocalType && l->upvalue))
{
DefId updated = defArena->freshCell(l->local, l->location, containsSubscriptedDefinition(incomingDef));
scope->bindings[l->local] = updated;
Expand Down
Loading