Skip to content

Commit 3c4ead4

Browse files
committed
fix: Nonempty returns require nonempty bodies
Functions that return a non-unit value require bodies with a final expression that is not terminated via semicolon (that would be a statement). Blocks that are empty or that consist exclusively out of statements are not allowed. Assert correctness in a unit test.
1 parent 1d9d545 commit 3c4ead4

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

src/ast.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -667,10 +667,17 @@ impl AbstractSyntaxTree for Expression {
667667
.iter()
668668
.map(|s| Statement::analyze(s, &ResolvedType::unit(), scope))
669669
.collect::<Result<Arc<[Statement]>, RichError>>()?;
670-
let ast_expression = expression
671-
.as_ref()
672-
.map(|expr| Expression::analyze(expr, ty, scope).map(Arc::new))
673-
.transpose()?;
670+
let ast_expression = match expression {
671+
Some(expression) => Expression::analyze(expression, ty, scope)
672+
.map(Arc::new)
673+
.map(Some),
674+
None if ty.is_unit() => Ok(None),
675+
None => Err(Error::ExpressionTypeMismatch(
676+
ty.clone(),
677+
ResolvedType::unit(),
678+
))
679+
.with_span(from),
680+
}?;
674681
scope.pop_scope();
675682

676683
Ok(Self {

src/lib.rs

+28
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,18 @@ mod tests {
136136
assert_success(prog_text, &witness)
137137
}
138138

139+
fn assert_satisfy_error_empty_witness(prog_text: &str, expected_error: &str) {
140+
let witness = WitnessValues::empty();
141+
match satisfy(prog_text, &witness) {
142+
Ok(_) => panic!("Accepted faulty program"),
143+
Err(error) => {
144+
if !error.contains(expected_error) {
145+
panic!("Unexpected error: {error}")
146+
}
147+
}
148+
}
149+
}
150+
139151
#[test]
140152
fn redefined_variable() {
141153
let prog_text = r#"fn main() {
@@ -145,4 +157,20 @@ mod tests {
145157
"#;
146158
assert_success_empty_witness(prog_text);
147159
}
160+
161+
#[test]
162+
fn empty_function_body_nonempty_return() {
163+
let prog_text = r#"fn my_true() -> bool {
164+
// function body is empty, although function must return `bool`
165+
}
166+
167+
fn main() {
168+
jet_verify(my_true());
169+
}
170+
"#;
171+
assert_satisfy_error_empty_witness(
172+
prog_text,
173+
"Expected expression of type `bool`, found type `()`",
174+
);
175+
}
148176
}

0 commit comments

Comments
 (0)