Skip to content

Commit

Permalink
Fix parse tree regression handling while loop body implicit returns. (F…
Browse files Browse the repository at this point in the history
…uelLabs#2414)

Take the following code as an example:

```rust
fn main() -> u64 {
    while true {
        true
    }
}
```

We were converting the body of the while to:

`CodeBlock { contents: [Expression(Literal { value: Boolean(true) })]}`

After these changes, we now convert this to:

`CodeBlock { contents: [ImplicitReturnExpression(Literal { value:
Boolean(true) })]}`

After which the existing sema checking code can correctly issue errors.

Closes FuelLabs#2401.
  • Loading branch information
tritao authored Jul 30, 2022
1 parent 7e71344 commit 376010e
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 16 deletions.
25 changes: 9 additions & 16 deletions sway-core/src/convert_parse_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ fn item_fn_to_function_declaration(
purity: get_attributed_purity(ec, attributes)?,
name: item_fn.fn_signature.name,
visibility: pub_token_opt_to_visibility(item_fn.fn_signature.visibility),
body: braced_code_block_contents_to_code_block(ec, item_fn.body, false)?,
body: braced_code_block_contents_to_code_block(ec, item_fn.body)?,
parameters: fn_args_to_function_parameters(
ec,
item_fn.fn_signature.arguments.into_inner(),
Expand Down Expand Up @@ -919,7 +919,6 @@ fn type_field_to_enum_variant(
fn braced_code_block_contents_to_code_block(
ec: &mut ErrorContext,
braced_code_block_contents: Braces<CodeBlockContents>,
is_while_loop_body: bool,
) -> Result<CodeBlock, ErrorEmitted> {
let whole_block_span = braced_code_block_contents.span();
let code_block_contents = braced_code_block_contents.into_inner();
Expand All @@ -930,11 +929,7 @@ fn braced_code_block_contents_to_code_block(
contents.extend(ast_nodes);
}
if let Some(expr) = code_block_contents.final_expr_opt {
let final_ast_node = expr_to_ast_node(
ec,
*expr,
!is_while_loop_body, // end_of_non_while_loop_body_block
)?;
let final_ast_node = expr_to_ast_node(ec, *expr, false)?;
contents.push(final_ast_node);
}
contents
Expand Down Expand Up @@ -1119,7 +1114,7 @@ fn path_type_to_call_path(
fn expr_to_ast_node(
ec: &mut ErrorContext,
expr: Expr,
end_of_non_while_loop_body_block: bool,
is_statement: bool,
) -> Result<AstNode, ErrorEmitted> {
let span = expr.span();
let ast_node = match expr {
Expand All @@ -1141,9 +1136,7 @@ fn expr_to_ast_node(
} => AstNode {
content: AstNodeContent::WhileLoop(WhileLoop {
condition: expr_to_expression(ec, *condition)?,
body: braced_code_block_contents_to_code_block(
ec, block, true, // is_while_loop_body
)?,
body: braced_code_block_contents_to_code_block(ec, block)?,
}),
span,
},
Expand Down Expand Up @@ -1184,7 +1177,7 @@ fn expr_to_ast_node(
},
expr => {
let expression = expr_to_expression(ec, expr)?;
if end_of_non_while_loop_body_block {
if !is_statement {
AstNode {
content: AstNodeContent::ImplicitReturnExpression(expression),
span,
Expand Down Expand Up @@ -1903,7 +1896,7 @@ fn statement_to_ast_nodes(
let ast_nodes = match statement {
Statement::Let(statement_let) => statement_let_to_ast_nodes(ec, statement_let)?,
Statement::Item(item) => item_to_ast_nodes(ec, item)?,
Statement::Expr { expr, .. } => vec![expr_to_ast_node(ec, expr, false)?],
Statement::Expr { expr, .. } => vec![expr_to_ast_node(ec, expr, true)?],
};
Ok(ast_nodes)
}
Expand Down Expand Up @@ -2169,7 +2162,7 @@ fn braced_code_block_contents_to_expression(
) -> Result<Expression, ErrorEmitted> {
let span = braced_code_block_contents.span();
Ok(Expression::CodeBlock {
contents: braced_code_block_contents_to_code_block(ec, braced_code_block_contents, false)?,
contents: braced_code_block_contents_to_code_block(ec, braced_code_block_contents)?,
span,
})
}
Expand All @@ -2187,7 +2180,7 @@ fn if_expr_to_expression(
} = if_expr;
let then_block_span = then_block.span();
let then_block = Expression::CodeBlock {
contents: braced_code_block_contents_to_code_block(ec, then_block, false)?,
contents: braced_code_block_contents_to_code_block(ec, then_block)?,
span: then_block_span.clone(),
};
let else_block = match else_opt {
Expand Down Expand Up @@ -2578,7 +2571,7 @@ fn match_branch_to_match_branch(
MatchBranchKind::Block { block, .. } => {
let span = block.span();
Expression::CodeBlock {
contents: braced_code_block_contents_to_code_block(ec, block, false)?,
contents: braced_code_block_contents_to_code_block(ec, block)?,
span,
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[[package]]
name = 'while_implicit_ret'
source = 'root'
dependencies = []
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "while_implicit_ret"
implicit-std = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
script;

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

# unordered: $()Implicit return must match up with block's type.
# unordered: $()A while loop's loop body cannot implicitly return a value. Try assigning it to a mutable variable declared outside of the loop instead.

0 comments on commit 376010e

Please sign in to comment.