mirror of
https://github.com/luau-lang/luau.git
synced 2025-05-04 10:33:46 +01:00
Fold in my review.
This commit is contained in:
parent
94dc9d40c1
commit
5b953e0681
4 changed files with 20 additions and 67 deletions
|
@ -16,22 +16,7 @@ enum class ControlFlow
|
||||||
Throws = 0b00100,
|
Throws = 0b00100,
|
||||||
Breaks = 0b01000,
|
Breaks = 0b01000,
|
||||||
Continues = 0b10000,
|
Continues = 0b10000,
|
||||||
|
|
||||||
// Returns OR Throws (e.g. if predicate then return else error() end)
|
|
||||||
MixedFunctionExit = 0b100000,
|
|
||||||
|
|
||||||
// Breaks OR Continues (e.g. if predicate then break else continue end)
|
|
||||||
MixedLoopExit = 0b1000000,
|
|
||||||
|
|
||||||
// Exits a loop OR function (e.g. if prediate then continue else return end)
|
|
||||||
MixedExit = 0b10000000,
|
|
||||||
};
|
};
|
||||||
// Bitmask of all control flows which exit the nearest function scope
|
|
||||||
#define FunctionExitControlFlows ControlFlow::Returns | ControlFlow::Throws | ControlFlow::MixedFunctionExit
|
|
||||||
// Bitmask of all control flows which exit the nearest loop scope
|
|
||||||
#define LoopExitControlFlows ControlFlow::Breaks | ControlFlow::Continues | ControlFlow::MixedLoopExit
|
|
||||||
// Bitmask of all control flows which exit the nearest function or loop scopes
|
|
||||||
#define ExitingControlFlows ControlFlow::Returns | ControlFlow::Throws | ControlFlow::Breaks | ControlFlow::Continues | ControlFlow::MixedFunctionExit | ControlFlow::MixedLoopExit | ControlFlow::MixedExit
|
|
||||||
|
|
||||||
inline ControlFlow operator&(ControlFlow a, ControlFlow b)
|
inline ControlFlow operator&(ControlFlow a, ControlFlow b)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1067,38 +1067,22 @@ ControlFlow ConstraintGraphBuilder::visit(const ScopePtr& scope, AstStatIf* ifSt
|
||||||
ScopePtr elseScope = childScope(ifStatement->elsebody ? ifStatement->elsebody : ifStatement, scope);
|
ScopePtr elseScope = childScope(ifStatement->elsebody ? ifStatement->elsebody : ifStatement, scope);
|
||||||
applyRefinements(elseScope, ifStatement->elseLocation.value_or(ifStatement->condition->location), refinementArena.negation(refinement));
|
applyRefinements(elseScope, ifStatement->elseLocation.value_or(ifStatement->condition->location), refinementArena.negation(refinement));
|
||||||
|
|
||||||
const ControlFlow guardClauseFlows = FFlag::LuauLoopControlFlowAnalysis ? ExitingControlFlows : ControlFlow::Returns | ControlFlow::Throws;
|
|
||||||
|
|
||||||
ControlFlow thencf = visit(thenScope, ifStatement->thenbody);
|
ControlFlow thencf = visit(thenScope, ifStatement->thenbody);
|
||||||
ControlFlow elsecf = ControlFlow::None;
|
ControlFlow elsecf = ControlFlow::None;
|
||||||
if (ifStatement->elsebody)
|
if (ifStatement->elsebody)
|
||||||
elsecf = visit(elseScope, ifStatement->elsebody);
|
elsecf = visit(elseScope, ifStatement->elsebody);
|
||||||
|
|
||||||
if (matches(thencf, guardClauseFlows) && elsecf == ControlFlow::None)
|
if (thencf != ControlFlow::None && elsecf == ControlFlow::None)
|
||||||
scope->inheritRefinements(elseScope);
|
scope->inheritRefinements(elseScope);
|
||||||
else if (thencf == ControlFlow::None && matches(elsecf, guardClauseFlows))
|
else if (thencf == ControlFlow::None && elsecf != ControlFlow::None)
|
||||||
scope->inheritRefinements(thenScope);
|
scope->inheritRefinements(thenScope);
|
||||||
|
|
||||||
if (FFlag::LuauLoopControlFlowAnalysis)
|
if (FFlag::LuauLoopControlFlowAnalysis && thencf == elsecf)
|
||||||
{
|
|
||||||
if (thencf == elsecf)
|
|
||||||
return thencf;
|
return thencf;
|
||||||
else if (matches(thencf, FunctionExitControlFlows) && matches(elsecf, FunctionExitControlFlows))
|
else if (matches(thencf, ControlFlow::Returns | ControlFlow::Throws) && matches(elsecf, ControlFlow::Returns | ControlFlow::Throws))
|
||||||
return ControlFlow::MixedFunctionExit;
|
|
||||||
else if (matches(thencf, LoopExitControlFlows) && matches(elsecf, LoopExitControlFlows))
|
|
||||||
return ControlFlow::MixedLoopExit;
|
|
||||||
else if (matches(thencf, ExitingControlFlows) && matches(elsecf, ExitingControlFlows))
|
|
||||||
return ControlFlow::MixedExit;
|
|
||||||
else
|
|
||||||
return ControlFlow::None;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (matches(thencf, ControlFlow::Returns | ControlFlow::Throws) && matches(elsecf, ControlFlow::Returns | ControlFlow::Throws))
|
|
||||||
return ControlFlow::Returns;
|
return ControlFlow::Returns;
|
||||||
else
|
else
|
||||||
return ControlFlow::None;
|
return ControlFlow::None;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool occursCheck(TypeId needle, TypeId haystack)
|
static bool occursCheck(TypeId needle, TypeId haystack)
|
||||||
|
|
|
@ -747,39 +747,23 @@ ControlFlow TypeChecker::check(const ScopePtr& scope, const AstStatIf& statement
|
||||||
ScopePtr elseScope = childScope(scope, statement.elsebody ? statement.elsebody->location : statement.location);
|
ScopePtr elseScope = childScope(scope, statement.elsebody ? statement.elsebody->location : statement.location);
|
||||||
resolve(result.predicates, elseScope, false);
|
resolve(result.predicates, elseScope, false);
|
||||||
|
|
||||||
const ControlFlow guardClauseFlows = FFlag::LuauLoopControlFlowAnalysis ? ExitingControlFlows : ControlFlow::Returns | ControlFlow::Throws;
|
|
||||||
|
|
||||||
ControlFlow thencf = check(thenScope, *statement.thenbody);
|
ControlFlow thencf = check(thenScope, *statement.thenbody);
|
||||||
ControlFlow elsecf = ControlFlow::None;
|
ControlFlow elsecf = ControlFlow::None;
|
||||||
if (statement.elsebody)
|
if (statement.elsebody)
|
||||||
elsecf = check(elseScope, *statement.elsebody);
|
elsecf = check(elseScope, *statement.elsebody);
|
||||||
|
|
||||||
if (matches(thencf, guardClauseFlows) && elsecf == ControlFlow::None)
|
if (thencf != ControlFlow::None && elsecf == ControlFlow::None)
|
||||||
scope->inheritRefinements(elseScope);
|
scope->inheritRefinements(elseScope);
|
||||||
else if (thencf == ControlFlow::None && matches(elsecf, guardClauseFlows))
|
else if (thencf == ControlFlow::None && elsecf != ControlFlow::None)
|
||||||
scope->inheritRefinements(thenScope);
|
scope->inheritRefinements(thenScope);
|
||||||
|
|
||||||
if (FFlag::LuauLoopControlFlowAnalysis)
|
if (FFlag::LuauLoopControlFlowAnalysis && thencf == elsecf)
|
||||||
{
|
|
||||||
if (thencf == elsecf)
|
|
||||||
return thencf;
|
return thencf;
|
||||||
else if (matches(thencf, FunctionExitControlFlows) && matches(elsecf, FunctionExitControlFlows))
|
else if (matches(thencf, ControlFlow::Returns | ControlFlow::Throws) && matches(elsecf, ControlFlow::Returns | ControlFlow::Throws))
|
||||||
return ControlFlow::MixedFunctionExit;
|
|
||||||
else if (matches(thencf, LoopExitControlFlows) && matches(elsecf, LoopExitControlFlows))
|
|
||||||
return ControlFlow::MixedLoopExit;
|
|
||||||
else if (matches(thencf, ExitingControlFlows) && matches(elsecf, ExitingControlFlows))
|
|
||||||
return ControlFlow::MixedExit;
|
|
||||||
else
|
|
||||||
return ControlFlow::None;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (matches(thencf, ControlFlow::Returns | ControlFlow::Throws) && matches(elsecf, ControlFlow::Returns | ControlFlow::Throws))
|
|
||||||
return ControlFlow::Returns;
|
return ControlFlow::Returns;
|
||||||
else
|
else
|
||||||
return ControlFlow::None;
|
return ControlFlow::None;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
check(thenScope, *statement.thenbody);
|
check(thenScope, *statement.thenbody);
|
||||||
|
|
Loading…
Add table
Reference in a new issue