favor return over return _ (void return); newline/closing terminates
This commit is contained in:
+91
-1
@@ -2289,7 +2289,7 @@ return_sink_and_unconsumed_values_have_distinct_hir :: proc(t: ^testing.T) {
|
||||
return 1
|
||||
}
|
||||
done func() void {
|
||||
return _
|
||||
return
|
||||
}
|
||||
main func() void {
|
||||
done()
|
||||
@@ -2327,6 +2327,96 @@ main func() void {
|
||||
testing.expect_value(t, hir_module.statements[main.body[2]].kind, hir.Stmt_Kind.Trap)
|
||||
}
|
||||
|
||||
@(test)
|
||||
bare_returns_and_strict_yields :: proc(t: ^testing.T) {
|
||||
text := `Failure :: enum { bad }
|
||||
noop func() void {}
|
||||
newline_return func() void {
|
||||
return
|
||||
}
|
||||
inline_return func() void { return }
|
||||
fallible_return func() void ! Failure { return }
|
||||
split_return func() i32 {
|
||||
return
|
||||
1
|
||||
}
|
||||
old_return func() void { return _ }
|
||||
missing_yield func() i32 {
|
||||
value :: {
|
||||
yield
|
||||
1
|
||||
}
|
||||
return value
|
||||
}
|
||||
missing_labeled_yield func() i32 {
|
||||
value :: block: {
|
||||
yield :block
|
||||
}
|
||||
return value
|
||||
}
|
||||
void_yield func() i32 {
|
||||
value :: { yield noop() }
|
||||
return value
|
||||
}
|
||||
sink_yield func() i32 {
|
||||
value :: { yield _ }
|
||||
return value
|
||||
}
|
||||
void_context func() void {
|
||||
fallible_return() catch |_| { yield 1 }
|
||||
}
|
||||
bad_comptime :: ${ yield noop() }
|
||||
main func() void {
|
||||
newline_return()
|
||||
inline_return()
|
||||
fallible_return() catch |_| {}
|
||||
_ = split_return()
|
||||
old_return()
|
||||
_ = missing_yield()
|
||||
_ = missing_labeled_yield()
|
||||
_ = void_yield()
|
||||
_ = sink_yield()
|
||||
void_context()
|
||||
}
|
||||
`
|
||||
source_file := source.Source{path="test.bro", text=text}
|
||||
diagnostics := source.init_diagnostics(&source_file)
|
||||
defer source.destroy_diagnostics(&diagnostics)
|
||||
symbols := symbol.init_table()
|
||||
defer symbol.destroy_table(&symbols)
|
||||
stream := lexer.lex(&source_file, &diagnostics, &symbols)
|
||||
defer delete(stream.items)
|
||||
ast_module := parser.parse(&stream, &source_file, &diagnostics)
|
||||
defer ast.destroy_module(&ast_module)
|
||||
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
|
||||
defer hir.destroy_module(&hir_module)
|
||||
|
||||
testing.expect_value(t, ast_module.statements[ast_module.functions[1].body[0]].expr, ast.INVALID_EXPR)
|
||||
testing.expect_value(t, ast_module.statements[ast_module.functions[2].body[0]].expr, ast.INVALID_EXPR)
|
||||
testing.expect_value(t, ast_module.statements[ast_module.functions[3].body[0]].expr, ast.INVALID_EXPR)
|
||||
testing.expect_value(t, len(ast_module.functions[4].body), 2)
|
||||
|
||||
missing_value := false
|
||||
non_void_function := false
|
||||
void_yields := 0
|
||||
sink_read := false
|
||||
void_context := false
|
||||
for diagnostic in diagnostics.items {
|
||||
missing_value = missing_value || strings.contains(diagnostic.message, "'yield' must produce a value")
|
||||
non_void_function = non_void_function || strings.contains(diagnostic.message, "non-void function must return a value")
|
||||
if strings.contains(diagnostic.message, "'yield' expression must produce a non-void value") {
|
||||
void_yields += 1
|
||||
}
|
||||
sink_read = sink_read || strings.contains(diagnostic.message, "'_' is a write-only sink and cannot be read")
|
||||
void_context = void_context || strings.contains(diagnostic.message, "void value context must fall through instead of yielding")
|
||||
}
|
||||
testing.expect(t, missing_value)
|
||||
testing.expect(t, non_void_function)
|
||||
testing.expect(t, void_yields >= 2)
|
||||
testing.expect(t, sink_read)
|
||||
testing.expect(t, void_context)
|
||||
}
|
||||
|
||||
@(test)
|
||||
unused_locals_and_params_warn_without_traps :: proc(t: ^testing.T) {
|
||||
text := `warn_only func(value i32, unused i32) i32 {
|
||||
|
||||
Reference in New Issue
Block a user