From 773f9617363ef56e327d2fcd8226d08cff45d92b Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 30 Sep 2023 16:40:26 +0300 Subject: [PATCH] checker: turn the option/result split warning into an error; readme: better wording --- README.md | 20 ++++++++++--------- vlib/v/checker/return.v | 4 ++-- .../checker/tests/option_fn_return_error.out | 2 +- .../tests/void_fn_multiple_ret_err.out | 11 ++-------- vlib/v/gen/c/testdata/for_in.vv | 12 ++++++----- vlib/v/gen/js/tests/js.v | 2 +- vlib/v/slow_tests/inout/option_fn_arg.vv | 4 ++-- .../valgrind/1.strings_and_arrays.v | 6 +++--- vlib/v/tests/option_test.v | 18 ++++++++--------- 9 files changed, 38 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 7757abed02..d833f6ce33 100644 --- a/README.md +++ b/README.md @@ -41,20 +41,22 @@ - C and JavaScript backends - Great for writing low-level software ([Vinix OS](https://github.com/vlang/vinix)) -## Stability guarantee and future changes +## Stability, future changes, post 1.0 freeze -Despite being at an early development stage, the V language is relatively stable and has -backwards compatibility guarantee, meaning that the code you write today is guaranteed -to work a month, a year, or five years from now. +Despite being at an early development stage, the V language is relatively stable, and doesn't +change often. But there will bechanges before 1.0. +Most changes in the syntax are handled via vfmt automatically. -There still may be minor syntax changes before the 1.0 release, but they will be handled -automatically via `vfmt`, as has been done in the past. - -The V core APIs (primarily the `os` module) will still have minor changes until +The V core APIs (primarily the `os` module) will also have minor changes until they are stabilized in V 1.0. Of course the APIs will grow after that, but without breaking existing code. -Unlike many other languages, V is not going to be always changing, with new features +After the 1.0 release V is going to be in the "feature freeze" mode. That means no breaking changes +in the language, only bug fixes and performance improvements. Similar to Go. + +Will there be V 2.0? Not within a decade after 1.0, perhaps not ever. + +To sum it up, unlike many other languages, V is not going to be always changing, with new features being introduced and old features modified. It is always going to be a small and simple language, very similar to the way it is right now. diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index fb9a19f213..8cf609f6ea 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -121,10 +121,10 @@ fn (mut c Checker) return_stmt(mut node ast.Return) { result_type_idx := c.table.type_idxs['_result'] got_types_0_idx := got_types[0].idx() if exp_is_option && got_types_0_idx == ast.error_type_idx { - c.warn('Option and Result types have been split, use `!Foo` to return errors', + c.error('Option and Result types have been split, use `!Foo` to return errors', node.pos) } else if exp_is_result && got_types_0_idx == ast.none_type_idx { - c.warn('Option and Result types have been split, use `?` to return none', node.pos) + c.error('Option and Result types have been split, use `?` to return none', node.pos) } if (exp_is_option && got_types_0_idx in [ast.none_type_idx, ast.error_type_idx, option_type_idx]) diff --git a/vlib/v/checker/tests/option_fn_return_error.out b/vlib/v/checker/tests/option_fn_return_error.out index 180b0ae3f7..14d880bd98 100644 --- a/vlib/v/checker/tests/option_fn_return_error.out +++ b/vlib/v/checker/tests/option_fn_return_error.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/option_fn_return_error.vv:2:2: warning: Option and Result types have been split, use `!Foo` to return errors +vlib/v/checker/tests/option_fn_return_error.vv:2:2: error: Option and Result types have been split, use `!Foo` to return errors 1 | fn func() ?int { 2 | return error('Some error') | ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/vlib/v/checker/tests/void_fn_multiple_ret_err.out b/vlib/v/checker/tests/void_fn_multiple_ret_err.out index d70977021e..24af8247e0 100644 --- a/vlib/v/checker/tests/void_fn_multiple_ret_err.out +++ b/vlib/v/checker/tests/void_fn_multiple_ret_err.out @@ -1,21 +1,14 @@ -vlib/v/checker/tests/void_fn_multiple_ret_err.vv:6:2: warning: Option and Result types have been split, use `?` to return none - 4 | - 5 | fn foo_result_2() ! { - 6 | return none - | ~~~~~~~~~~~ - 7 | } - 8 | vlib/v/checker/tests/void_fn_multiple_ret_err.vv:2:9: error: functions with Result-only return types can only return an error 1 | fn foo_result_1() ! { 2 | return none, 100 | ~~~~ 3 | } 4 | -vlib/v/checker/tests/void_fn_multiple_ret_err.vv:6:9: error: cannot use `none` as Result type in return argument +vlib/v/checker/tests/void_fn_multiple_ret_err.vv:6:2: error: Option and Result types have been split, use `?` to return none 4 | 5 | fn foo_result_2() ! { 6 | return none - | ~~~~ + | ~~~~~~~~~~~ 7 | } 8 | vlib/v/checker/tests/void_fn_multiple_ret_err.vv:14:9: error: cannot use `int literal` as Result type in return argument diff --git a/vlib/v/gen/c/testdata/for_in.vv b/vlib/v/gen/c/testdata/for_in.vv index 2f210e1351..ee42a3d5d2 100644 --- a/vlib/v/gen/c/testdata/for_in.vv +++ b/vlib/v/gen/c/testdata/for_in.vv @@ -1,15 +1,17 @@ struct CustomIter { mut: - idx int + idx int } fn new_custom_iter() CustomIter { - return CustomIter{ idx: 0 } + return CustomIter{ + idx: 0 + } } fn (mut a CustomIter) next() ?int { if a.idx == 4 { - return error('') + return none } else { a.idx++ return a.idx * 2 @@ -18,10 +20,10 @@ fn (mut a CustomIter) next() ?int { fn main() { for x in new_custom_iter() { - println('a.$x') + println('a.${x}') } for ix, val in new_custom_iter() { - println('b.$ix=$val') + println('b.${ix}=${val}') } println('end') } diff --git a/vlib/v/gen/js/tests/js.v b/vlib/v/gen/js/tests/js.v index d729956156..4aac31f859 100644 --- a/vlib/v/gen/js/tests/js.v +++ b/vlib/v/gen/js/tests/js.v @@ -139,7 +139,7 @@ fn (it Companies) method() int { return 0 } -fn error_if_even(num int) ?int { +fn error_if_even(num int) !int { if num % 2 == 0 { return error('number is even') } diff --git a/vlib/v/slow_tests/inout/option_fn_arg.vv b/vlib/v/slow_tests/inout/option_fn_arg.vv index 1ddd18e82a..6b919be785 100644 --- a/vlib/v/slow_tests/inout/option_fn_arg.vv +++ b/vlib/v/slow_tests/inout/option_fn_arg.vv @@ -1,10 +1,10 @@ module main -fn test(f fn () ?) ? { +fn test(f fn () !) ! { return error('test') } -fn test1() ? { +fn test1() ! { return error('test1') } diff --git a/vlib/v/slow_tests/valgrind/1.strings_and_arrays.v b/vlib/v/slow_tests/valgrind/1.strings_and_arrays.v index 0b98ef0338..e4e1f8261d 100644 --- a/vlib/v/slow_tests/valgrind/1.strings_and_arrays.v +++ b/vlib/v/slow_tests/valgrind/1.strings_and_arrays.v @@ -175,7 +175,7 @@ fn option_str() { } } -fn return_error_with_freed_expr() ?string { +fn return_error_with_freed_expr() !string { if true { msg := 'oops' return error('hm ${msg}') @@ -357,7 +357,7 @@ fn return_sb_str() string { return sb.str() // sb should be freed, but only after .str() is called } -fn parse_header0(s string) ?string { +fn parse_header0(s string) !string { if !s.contains(':') { return error('missing colon in header') } @@ -366,7 +366,7 @@ fn parse_header0(s string) ?string { return x } -fn parse_header1(s string) ?string { +fn parse_header1(s string) !string { if !s.contains(':') { return error('missing colon in header') } diff --git a/vlib/v/tests/option_test.v b/vlib/v/tests/option_test.v index f5689a379b..4620cbc6e0 100644 --- a/vlib/v/tests/option_test.v +++ b/vlib/v/tests/option_test.v @@ -1,5 +1,5 @@ // TODO: remove this after the deprecation period for `?Type` representing both Result and Option passes. -fn opt_err_with_code(code int) ?string { +fn opt_err_with_code(code int) !string { return error_with_code('hi', code) } @@ -20,7 +20,7 @@ fn test_err_with_code() { _ := v } -fn opt_err() ?string { +fn opt_err() !string { return error('hi') } @@ -33,7 +33,7 @@ fn test_err() { println(v) // suppress not used error } -fn err_call(ok bool) ?int { +fn err_call(ok bool) !int { if !ok { return error('Not ok!') } @@ -79,7 +79,7 @@ fn test_if_else_opt() { } } -fn for_opt_default() ?string { +fn for_opt_default() !string { return error('awww') } @@ -137,7 +137,7 @@ fn or_return_val() int { return a } -fn or_return_error() ?int { +fn or_return_error() !int { a := ret_none() or { return error('Nope') } return a } @@ -282,7 +282,7 @@ fn test_option_val_with_empty_or() { } fn test_option_void_return_types_of_anon_fn() { - f := fn (i int) ? { + f := fn (i int) ! { if i == 0 { return error('0') } @@ -297,12 +297,12 @@ fn test_option_void_return_types_of_anon_fn() { } struct Foo { - f fn (int) ? + f fn (int) ! } fn test_option_void_return_types_of_anon_fn_in_struct() { foo := Foo{ - f: fn (i int) ? { + f: fn (i int) ! { if i == 0 { return error('0') } @@ -327,7 +327,7 @@ struct CC { str string } -fn option_sum_type(a int) ?AA { +fn option_sum_type(a int) !AA { match a { 1 { return BB{'Test'}