From 9d3276e40ae11b111794138d655a0615ce0e2c54 Mon Sep 17 00:00:00 2001 From: Martin Angers Date: Wed, 19 Feb 2020 13:22:55 -0500 Subject: [PATCH] pkg/semantic: statically check that fn body return in all branches --- pkg/semantic/analysis_pass.go | 10 ++++++++++ .../testdata/static/fn_generic_interface.snow.err | 2 ++ pkg/semantic/testdata/static/fn_invalid_main.snow.err | 1 + pkg/semantic/testdata/static/fn_nested_block.snow.err | 1 + .../testdata/static/interface_satisfied.snow.err | 3 +++ 5 files changed, 17 insertions(+) diff --git a/pkg/semantic/analysis_pass.go b/pkg/semantic/analysis_pass.go index f836e0e..581fb98 100644 --- a/pkg/semantic/analysis_pass.go +++ b/pkg/semantic/analysis_pass.go @@ -42,6 +42,16 @@ func (a *analysisVisitor) Visit(n Node) Visitor { // ************** DECLARATIONS ***************** + case *Fn: + // if the function has a body and does not return void, make sure + // every branch of the function has a return or does not fallthrough + // without returning. + if st := AsSignatureType(n.Type()); n.Body != nil && st != nil && !IsBasicOfKind(st.Return, Void) { + if FallsThrough(n.Body) { + a.errh(n.Pos(), "not all branches of the function body return a value") + } + } + case *Var: if n.Value != nil { aa := a.cloneRHS() diff --git a/pkg/semantic/testdata/static/fn_generic_interface.snow.err b/pkg/semantic/testdata/static/fn_generic_interface.snow.err index 1da078b..43983cd 100644 --- a/pkg/semantic/testdata/static/fn_generic_interface.snow.err +++ b/pkg/semantic/testdata/static/fn_generic_interface.snow.err @@ -1 +1,3 @@ +testdata/fn_generic_interface.snow:6:6: not all branches of the function body return a value +testdata/fn_generic_interface.snow:10:6: not all branches of the function body return a value testdata/fn_generic_interface.snow:23:14: cannot assign type struct G[bool] to variable of type interface I[int] diff --git a/pkg/semantic/testdata/static/fn_invalid_main.snow.err b/pkg/semantic/testdata/static/fn_invalid_main.snow.err index f04b976..b29d456 100644 --- a/pkg/semantic/testdata/static/fn_invalid_main.snow.err +++ b/pkg/semantic/testdata/static/fn_invalid_main.snow.err @@ -1 +1,2 @@ testdata/fn_invalid_main.snow:1:4: main function must not have any parameter and return value, is (int) -> string +testdata/fn_invalid_main.snow:1:4: not all branches of the function body return a value diff --git a/pkg/semantic/testdata/static/fn_nested_block.snow.err b/pkg/semantic/testdata/static/fn_nested_block.snow.err index c8bea70..f0b4c4e 100644 --- a/pkg/semantic/testdata/static/fn_nested_block.snow.err +++ b/pkg/semantic/testdata/static/fn_nested_block.snow.err @@ -1 +1,2 @@ main function missing +testdata/fn_nested_block.snow:1:4: not all branches of the function body return a value diff --git a/pkg/semantic/testdata/static/interface_satisfied.snow.err b/pkg/semantic/testdata/static/interface_satisfied.snow.err index 540704b..01d32ed 100644 --- a/pkg/semantic/testdata/static/interface_satisfied.snow.err +++ b/pkg/semantic/testdata/static/interface_satisfied.snow.err @@ -1,3 +1,6 @@ +testdata/interface_satisfied.snow:9:6: not all branches of the function body return a value +testdata/interface_satisfied.snow:19:6: not all branches of the function body return a value +testdata/interface_satisfied.snow:23:10: not all branches of the function body return a value testdata/interface_satisfied.snow:39:11: cannot assign type int to variable of type interface Empty testdata/interface_satisfied.snow:42:7: cannot assign type struct S2 to variable of type interface Foo testdata/interface_satisfied.snow:43:7: cannot assign type struct S3 to variable of type interface Foo -- 2.45.2