Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -2052,7 +2052,8 @@ private void visit(Modifiers modifiers) {
private void visit(StmtReturn s) {
if (s.attrNearestExprStatementsBlock() != null) {
ExprStatementsBlock e = s.attrNearestExprStatementsBlock();
if (!isClosureImplementationBlock(e) && e.getReturnStmt() != s) {
boolean closureImplementationBlock = isClosureImplementationBlock(e);
if (!closureImplementationBlock && e.getReturnStmt() != s) {
s.addError("Return in a statements block can only be at the end.");
return;
}
Expand All @@ -2062,7 +2063,9 @@ private void visit(StmtReturn s) {
s.addError("Cannot return void from statements block.");
}
} else {
s.addError("Cannot have empty return statement in statements block.");
if (!closureImplementationBlock || !closureReturnsVoid(e)) {
s.addError("Cannot have empty return statement in statements block.");
}
}
} else {
FunctionImplementation func = s.attrNearestFuncDef();
Expand All @@ -2079,6 +2082,16 @@ private boolean isClosureImplementationBlock(ExprStatementsBlock block) {
return parent instanceof ExprClosure && ((ExprClosure) parent).getImplementation() == block;
}

private boolean closureReturnsVoid(ExprStatementsBlock block) {
Element parent = block.getParent();
if (!(parent instanceof ExprClosure)) {
return false;
}
ExprClosure closure = (ExprClosure) parent;
FuncLink abstractMethod = closure.attrClosureAbstractMethod();
return abstractMethod != null && abstractMethod.getReturnType().isVoid();
}

private void checkReturnInFunc(StmtReturn s, FunctionImplementation func) {
WurstType returnType = func.attrReturnTyp();
if (s.getReturnedObj() instanceof Expr) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,27 @@ public void closure_multipleEarlyReturns_inStatementsBlock() {
);
}

@Test
public void closure_multipleEmptyEarlyReturns_inVoidStatementsBlock() {
testAssertOkLines(true,
"package test",
"native testSuccess()",
"interface FnVoid",
" function run()",
"function call(FnVoid f)",
" f.run()",
"int x = 0",
"init",
" call() ->",
" x = 1",
" if true",
" return",
" x = 2",
" if x == 1",
" testSuccess()"
);
}

@Test
public void statementsBlockOutsideClosure_stillRequiresReturnAtEnd() {
testAssertErrorsLines(false, "Return in a statements block can only be at the end.",
Expand Down
Loading