Skip to content

Commit

Permalink
Revert changes to while loop handling in analyze_return_paths (FuelLa…
Browse files Browse the repository at this point in the history
…bs#3433)

Revert changes to while loop handling in `analyze_return_paths`.
  • Loading branch information
mohammadfawaz authored Nov 28, 2022
1 parent 47423bf commit 943b355
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 53 deletions.
71 changes: 18 additions & 53 deletions sway-core/src/control_flow_analysis/analyze_return_paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl ControlFlowGraph {
// do a depth first traversal and cover individual inner ast nodes
let mut leaves = vec![];
for ast_entrypoint in module_nodes {
let l_leaves = connect_node(type_engine, ast_entrypoint, &mut graph, &leaves)?.0;
let l_leaves = connect_node(type_engine, ast_entrypoint, &mut graph, &leaves)?;
if let NodeConnection::NextStep(nodes) = l_leaves {
leaves = nodes;
}
Expand Down Expand Up @@ -126,7 +126,7 @@ fn connect_node(
node: &ty::TyAstNode,
graph: &mut ControlFlowGraph,
leaves: &[NodeIndex],
) -> Result<(NodeConnection, ReturnStatementNodes), CompileError> {
) -> Result<NodeConnection, CompileError> {
let span = node.span.clone();
match &node.content {
ty::TyAstNodeContent::Expression(ty::TyExpression {
Expand All @@ -138,46 +138,20 @@ fn connect_node(
for leaf_ix in leaves {
graph.add_edge(*leaf_ix, this_index, "".into());
}
Ok((NodeConnection::Return(this_index), vec![]))
Ok(NodeConnection::Return(this_index))
}
ty::TyAstNodeContent::Expression(ty::TyExpression {
expression: ty::TyExpressionVariant::WhileLoop { body, .. },
expression: ty::TyExpressionVariant::WhileLoop { .. },
..
}) => {
// This is very similar to the dead code analysis for a while loop.
let entry = graph.add_node(node.into());
let while_loop_exit = graph.add_node("while loop exit".to_string().into());
for leaf in leaves {
graph.add_edge(*leaf, entry, "".into());
}
// it is possible for a whole while loop to be skipped so add edge from
// beginning of while loop straight to exit
graph.add_edge(
entry,
while_loop_exit,
"condition is initially false".into(),
);
let mut leaves = vec![entry];

// We need to dig into the body of the while loop in case there is a break or a
// continue at some level.
let (l_leaves, inner_returns) =
depth_first_insertion_code_block(type_engine, body, graph, &leaves)?;

// insert edges from end of block back to beginning of it
for leaf in &l_leaves {
graph.add_edge(*leaf, entry, "loop repeats".into());
}

leaves = l_leaves;
// An abridged version of the dead code analysis for a while loop
// since we don't really care about what the loop body contains when detecting
// divergent paths
let node = graph.add_node(node.into());
for leaf in leaves {
graph.add_edge(leaf, while_loop_exit, "".into());
graph.add_edge(*leaf, node, "while loop entry".into());
}

Ok((
NodeConnection::NextStep(vec![while_loop_exit]),
inner_returns,
))
Ok(NodeConnection::NextStep(vec![node]))
}
ty::TyAstNodeContent::Expression(ty::TyExpression { .. }) => {
let entry = graph.add_node(node.into());
Expand All @@ -186,19 +160,11 @@ fn connect_node(
for leaf in leaves {
graph.add_edge(*leaf, entry, "".into());
}
Ok((NodeConnection::NextStep(vec![entry]), vec![]))
Ok(NodeConnection::NextStep(vec![entry]))
}
ty::TyAstNodeContent::SideEffect => Ok((NodeConnection::NextStep(leaves.to_vec()), vec![])),
ty::TyAstNodeContent::Declaration(decl) => Ok((
NodeConnection::NextStep(connect_declaration(
type_engine,
node,
decl,
graph,
span,
leaves,
)?),
vec![],
ty::TyAstNodeContent::SideEffect => Ok(NodeConnection::NextStep(leaves.to_vec())),
ty::TyAstNodeContent::Declaration(decl) => Ok(NodeConnection::NextStep(
connect_declaration(type_engine, node, decl, graph, span, leaves)?,
)),
}
}
Expand Down Expand Up @@ -318,7 +284,7 @@ fn connect_typed_fn_decl(
) -> Result<(), CompileError> {
let fn_exit_node = graph.add_node(format!("\"{}\" fn exit", fn_decl.name.as_str()).into());
let return_nodes =
depth_first_insertion_code_block(type_engine, &fn_decl.body, graph, &[entry_node])?.0;
depth_first_insertion_code_block(type_engine, &fn_decl.body, graph, &[entry_node])?;
for node in return_nodes {
graph.add_edge(node, fn_exit_node, "return".into());
}
Expand All @@ -343,18 +309,17 @@ fn depth_first_insertion_code_block(
node_content: &ty::TyCodeBlock,
graph: &mut ControlFlowGraph,
leaves: &[NodeIndex],
) -> Result<(ReturnStatementNodes, Vec<NodeIndex>), CompileError> {
) -> Result<ReturnStatementNodes, CompileError> {
let mut leaves = leaves.to_vec();
let mut return_nodes = vec![];
for node in node_content.contents.iter() {
let (this_node, inner_returns) = connect_node(type_engine, node, graph, &leaves)?;
let this_node = connect_node(type_engine, node, graph, &leaves)?;
match this_node {
NodeConnection::NextStep(nodes) => leaves = nodes,
NodeConnection::Return(node) => {
return_nodes.push(node);
}
}
return_nodes.extend(inner_returns);
}
Ok((return_nodes, leaves))
Ok(return_nodes)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[[package]]
name = 'while_explicit_ret_1'
source = 'member'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
implicit-std = false
license = "Apache-2.0"
name = "while_explicit_ret_1"
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
script;

fn main() -> u64 {
while true {
return 0;
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "fail"

# check: $()This path must return a value of type "u64" from function "main", but it does not.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[[package]]
name = 'while_explicit_ret_2'
source = 'member'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
implicit-std = false
license = "Apache-2.0"
name = "while_explicit_ret_2"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
script;

fn main() -> u64 {
while true {
if true { }
return 0;
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "fail"

# check: $()This path must return a value of type "u64" from function "main", but it does not.

0 comments on commit 943b355

Please sign in to comment.