checker: turn the option/result split warning into an error; readme: better wording

This commit is contained in:
Alexander Medvednikov 2023-09-30 16:40:26 +03:00
parent 5b1b2cc7c0
commit 773f961736
9 changed files with 38 additions and 41 deletions

View file

@ -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.

View file

@ -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])

View file

@ -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')
| ~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -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

View file

@ -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')
}

View file

@ -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')
}

View file

@ -1,10 +1,10 @@
module main
fn test(f fn () ?) ? {
fn test(f fn () !) ! {
return error('test')
}
fn test1() ? {
fn test1() ! {
return error('test1')
}

View file

@ -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')
}

View file

@ -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'}