1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

all: change optional to option (#16914)

This commit is contained in:
JalonSolov 2023-01-09 01:36:45 -05:00 committed by GitHub
parent 241109516f
commit 90941b3b1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
255 changed files with 1428 additions and 1428 deletions

View File

@ -107,7 +107,7 @@
- `Option` and `Result` are now separate types: `?Foo` and `!Foo` respectively. Old code will continue working for 1 year and will result in a warning/hint.
- Hundreds of new checks in the type checker.
- All V's backends have been split up into separate processes. As the result, building V got 26% faster.
- Maps and arrays can now return optionals: `m[bad_key] or { ... }`, `if x := arr[key] { ... }`.
- Maps and arrays can now return options: `m[bad_key] or { ... }`, `if x := arr[key] { ... }`.
- `ustring` has been replaced with `[]rune` (works just like in Go).
- Maps can now have non-string keys.
- A new compiler pass for transforming the AST (doesn't slow the compiler too much, adds about 25ms to `v self`). It eliminates unreachable branches and performs other simple optimizations and transformations.
@ -447,14 +447,14 @@ used in some industries.
- `fn init()` for module initialization.
- `a in [1, 2, 3]` optimization: no array gets allocated.
- Raw strings: `s := r'hello\nworld'`.
- `if a := func() { }` syntax for handling optionals.
- `if a := func() { }` syntax for handling options.
- f32/f64 comparison now uses machine epsilon by default.
## V 0.1.21
*30 Sep 2019*
- `none` keyword for optionals.
- `none` keyword for options.
- Solaris support.
- All table lookup functions now use `none`.
- varargs: `fn foo(bar int, params ...string) {`.
@ -535,7 +535,7 @@ this backend.
- `libcurl` dependency was removed from the `http` module.
- All function arguments are now immutable by default (previously they could be
modifed inside the function).
- `http` functions now return optionals.
- `http` functions now return options.
- `sync.WaitGroup`.
- `vweb` static files serving.
- `crypto.rand` module.
@ -629,8 +629,8 @@ this backend.
## V 0.1.12
*4 Jul 2019*
- V can finally compile itself on Windows (https://github.com/vlang/v#mingw-w64).
- `os` module now uses optionals in all functions that return `File`.
- Lots of bugs with optionals were fixed.
- `os` module now uses options in all functions that return `File`.
- Lots of bugs with options were fixed.
- `println` was optimized. It no longer results in allocations.
Now it also works correctly with all integer types.
- Lots of `vfmt` fixes, it will be enabled tomorrow.

View File

@ -6,7 +6,7 @@
- [ ] Parallel C compilation
- [ ] `recover()` from panics
- [x] vfmt: add missing imports (like goimports)
- [ ] Recursive structs via optionals: `struct Node { next ?Node }`
- [ ] Recursive structs via options: `struct Node { next ?Node }`
- [ ] Optional function struct fields
- [ ] Handle function pointers safely, remove `if function == 0 {`
- [x] Bundle OpenSSL like GC

View File

@ -614,7 +614,7 @@ fn (t Tree) struct_field(node ast.StructField) &Node {
obj.add_terse('anon_struct_decl', t.struct_decl(node.anon_struct_decl))
obj.add_terse('unaliased_typ', t.type_node(node.unaliased_typ))
obj.add('type_pos', t.pos(node.type_pos))
obj.add('optional_pos', t.pos(node.optional_pos))
obj.add('option_pos', t.pos(node.option_pos))
obj.add_terse('has_default_expr', t.bool_node(node.has_default_expr))
obj.add_terse('default_expr_typ', t.type_node(node.default_expr_typ))
obj.add_terse('default_expr', t.expr(node.default_expr))
@ -1474,7 +1474,7 @@ fn (t Tree) ident_var(node ast.IdentVar) &Node {
obj.add_terse('is_mut', t.bool_node(node.is_mut))
obj.add_terse('is_static', t.bool_node(node.is_static))
obj.add_terse('is_volatile', t.bool_node(node.is_volatile))
obj.add_terse('is_optional', t.bool_node(node.is_optional))
obj.add_terse('is_option', t.bool_node(node.is_option))
obj.add_terse('share', t.enum_node(node.share))
return obj
}

View File

@ -125,7 +125,7 @@ In your terminal, you can:
* [Interfaces](#interfaces)
* [Sum types](#sum-types)
* [Option/Result types & error handling](#optionresult-types-and-error-handling)
* [Handling optionals/results](#handling-optionalsresults)
* [Handling options/results](#handling-optionsresults)
* [Custom error types](#custom-error-types)
* [Generics](#generics)
* [Concurrency](#concurrency)
@ -1344,7 +1344,7 @@ if v := m['abc'] {
}
```
The same optional check applies to arrays:
The same option check applies to arrays:
```v
arr := [1, 2, 3]
@ -3595,7 +3595,7 @@ fn (r Repo) find_user_by_id(id int) !User {
return error('User ${id} not found')
}
// A version of the function using an optional
// A version of the function using an option
fn (r Repo) find_user_by_id2(id int) ?User {
for user in r.users {
if user.id == id {
@ -3622,7 +3622,7 @@ fn main() {
V used to combine `Option` and `Result` into one type, now they are separate.
The amount of work required to "upgrade" a function to an optional/result function is minimal;
The amount of work required to "upgrade" a function to an option/result function is minimal;
you have to add a `?` or `!` to the return type and return an error when something goes wrong.
This is the primary mechanism for error handling in V. They are still values, like in Go,
@ -3639,9 +3639,9 @@ user := repo.find_user_by_id(7) or {
}
```
#### Handling optionals/results
#### Handling options/results
There are four ways of handling an optional/result. The first method is to
There are four ways of handling an option/result. The first method is to
propagate the error:
```v
@ -3655,8 +3655,8 @@ fn f(url string) !string {
`http.get` returns `!http.Response`. Because `!` follows the call, the
error will be propagated to the caller of `f`. When using `?` after a
function call producing an optional, the enclosing function must return
an optional as well. If error propagation is used in the `main()`
function call producing an option, the enclosing function must return
an option as well. If error propagation is used in the `main()`
function it will `panic` instead, since the error cannot be propagated
any further.
@ -3679,7 +3679,7 @@ entire program, or use a control flow statement (`return`, `break`, `continue`,
to break from the current block.
Note that `break` and `continue` can only be used inside a `for` loop.
V does not have a way to forcibly "unwrap" an optional (as other languages do,
V does not have a way to forcibly "unwrap" an option (as other languages do,
for instance Rust's `unwrap()` or Swift's `!`). To do this, use `or { panic(err) }` instead.
---
@ -3708,7 +3708,7 @@ The fourth method is to use `if` unwrapping:
import net.http
if resp := http.get('https://google.com') {
println(resp.body) // resp is a http.Response, not an optional
println(resp.body) // resp is a http.Response, not an option
} else {
println(err)
}
@ -3988,7 +3988,7 @@ A channel can be closed to indicate that no further objects can be pushed. Any a
to do so will then result in a runtime panic (with the exception of `select` and
`try_push()` - see below). Attempts to pop will return immediately if the
associated channel has been closed and the buffer is empty. This situation can be
handled using an `or {}` block (see [Handling optionals/results](#handling-optionalsresults)).
handled using an `or {}` block (see [Handling options/results](#handling-optionsresults)).
```v wip
ch := chan int{}

View File

@ -83,14 +83,14 @@ fn panic_debug(line_no int, file string, mod string, fn_name string, s string) {
vhalt()
}
// panic_optional_not_set is called by V, when you use option error propagation in your main function.
// panic_option_not_set is called by V, when you use option error propagation in your main function.
// It ends the program with a panic.
[noreturn]
pub fn panic_optional_not_set(s string) {
panic('optional not set (${s})')
pub fn panic_option_not_set(s string) {
panic('option not set (${s})')
}
// panic_optional_not_set is called by V, when you use result error propagation in your main function
// panic_result_not_set is called by V, when you use result error propagation in your main function
// It ends the program with a panic.
[noreturn]
pub fn panic_result_not_set(s string) {

View File

@ -118,9 +118,9 @@ pub:
is_pub bool // f is in a `pub:` section
is_mut bool // f is in a `mut:` section
//
is_shared bool // `f shared Abc`
is_atomic bool // `f atomic int` , TODO
is_optional bool // `f ?string` , TODO
is_shared bool // `f shared Abc`
is_atomic bool // `f atomic int` , TODO
is_option bool // `f ?string` , TODO
//
is_array bool // `f []string` , TODO
is_map bool // `f map[string]int` , TODO

View File

@ -107,7 +107,7 @@ pub fn error_with_code(message string, code int) IError {
}
}
// Option is the base of V's internal optional return system.
// Option is the base of V's internal option return system.
struct Option {
state u8
err IError = none__
@ -116,7 +116,7 @@ struct Option {
// derived Option_xxx types
}
// option is the base of V's internal optional return system.
// option is the base of V's internal option return system.
struct _option {
state u8
err IError = none__

View File

@ -84,7 +84,7 @@ pub fn utf8_str_len(s string) int {
// valid utf8 in the string, and could result in
// values greater than the utf32 spec
// it has been replaced by `utf8_to_utf32` which
// has an optional return type.
// has an option return type.
//
// this function is left for backward compatibility
// it is used in vlib/builtin/string.v,

View File

@ -3,7 +3,7 @@ import os
struct DbConfig {}
fn test_json_decode_with_optional_arg() {
fn test_json_decode_with_option_arg() {
if ret := print_info() {
println(ret)
} else {

View File

@ -5,7 +5,7 @@ struct Foo {
num ?int
}
fn test_json_encode_struct_with_optional_field() {
fn test_json_encode_struct_with_option_field() {
f1 := Foo{
name: 'hello'
}

View File

@ -3,7 +3,7 @@ module strconv
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
// TODO: use optionals, or some way to return default with error.
// TODO: use options, or some way to return default with error.
const (
// int_size is the size in bits of an int or uint value.
// int_size = 32 << (~u32(0) >> 63)

View File

@ -662,7 +662,7 @@ fn (mut s Scanner) validate_and_skip_headers() ! {
// NICE-TO-HAVE-TODO Check other types of (UTF-?) headers and yield an error. TOML is UTF-8 only.
// Skip optional UTF-8 heaser, if any.
// Skip optional UTF-8 header, if any.
if s.at() == 0xEF && s.peek(1) == 0xBB && s.peek(2) == 0xBF {
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'skipping UTF-8 byte order mark (BOM)')
s.header_len = 3

View File

@ -296,7 +296,7 @@ pub struct StructField {
pub:
pos token.Pos
type_pos token.Pos
optional_pos token.Pos
option_pos token.Pos
comments []Comment
i int
has_default_expr bool
@ -791,7 +791,7 @@ pub mut:
is_mut bool
is_static bool
is_volatile bool
is_optional bool
is_option bool
share ShareType
}

View File

@ -224,7 +224,7 @@ pub fn (t &Table) fn_type_signature(f &Fn) string {
}
if f.return_type != 0 && f.return_type != void_type {
sym := t.sym(f.return_type)
opt := if f.return_type.has_flag(.optional) { 'option_' } else { '' }
opt := if f.return_type.has_flag(.option) { 'option_' } else { '' }
res := if f.return_type.has_flag(.result) { 'result_' } else { '' }
sig += '__${opt}${res}${sym.cname}'
@ -256,7 +256,7 @@ pub fn (t &Table) fn_type_source_signature(f &Fn) string {
sig += ' !'
} else if f.return_type != void_type {
return_type_sym := t.sym(f.return_type)
if f.return_type.has_flag(.optional) {
if f.return_type.has_flag(.option) {
sig += ' ?${return_type_sym.name}'
} else if f.return_type.has_flag(.result) {
sig += ' !${return_type_sym.name}'
@ -882,7 +882,7 @@ pub fn (t &Table) known_type_idx(typ Type) bool {
pub fn (t &Table) array_name(elem_type Type) string {
elem_type_sym := t.sym(elem_type)
ptr := if elem_type.is_ptr() { '&'.repeat(elem_type.nr_muls()) } else { '' }
opt := if elem_type.has_flag(.optional) { '?' } else { '' }
opt := if elem_type.has_flag(.option) { '?' } else { '' }
res := if elem_type.has_flag(.result) { '!' } else { '' }
return '[]${opt}${res}${ptr}${elem_type_sym.name}'
}
@ -891,7 +891,7 @@ pub fn (t &Table) array_name(elem_type Type) string {
pub fn (t &Table) array_cname(elem_type Type) string {
elem_type_sym := t.sym(elem_type)
suffix := if elem_type.is_ptr() { '_ptr'.repeat(elem_type.nr_muls()) } else { '' }
opt := if elem_type.has_flag(.optional) { '_option_' } else { '' }
opt := if elem_type.has_flag(.option) { '_option_' } else { '' }
res := if elem_type.has_flag(.result) { '_result_' } else { '' }
if elem_type_sym.cname.contains('[') {
type_name := elem_type_sym.cname.replace_each(['[', '_T_', ', ', '_', ']', ''])
@ -907,7 +907,7 @@ pub fn (t &Table) array_cname(elem_type Type) string {
pub fn (t &Table) array_fixed_name(elem_type Type, size int, size_expr Expr) string {
elem_type_sym := t.sym(elem_type)
ptr := if elem_type.is_ptr() { '&'.repeat(elem_type.nr_muls()) } else { '' }
opt := if elem_type.has_flag(.optional) { '?' } else { '' }
opt := if elem_type.has_flag(.option) { '?' } else { '' }
res := if elem_type.has_flag(.result) { '!' } else { '' }
size_str := if size_expr is EmptyExpr || size != 987654321 {
size.str()
@ -921,7 +921,7 @@ pub fn (t &Table) array_fixed_name(elem_type Type, size int, size_expr Expr) str
pub fn (t &Table) array_fixed_cname(elem_type Type, size int) string {
elem_type_sym := t.sym(elem_type)
suffix := if elem_type.is_ptr() { '_ptr${elem_type.nr_muls()}' } else { '' }
opt := if elem_type.has_flag(.optional) { '_option_' } else { '' }
opt := if elem_type.has_flag(.option) { '_option_' } else { '' }
res := if elem_type.has_flag(.result) { '_result_' } else { '' }
if elem_type_sym.cname.contains('[') {
type_name := elem_type_sym.cname.replace_each(['[', '_T_', ', ', '_', ']', ''])
@ -978,7 +978,7 @@ pub fn (t &Table) promise_cname(return_type Type) string {
[inline]
pub fn (t &Table) thread_name(return_type Type) string {
if return_type.idx() == void_type_idx {
if return_type.has_flag(.optional) {
if return_type.has_flag(.option) {
return 'thread ?'
} else if return_type.has_flag(.result) {
return 'thread !'
@ -988,7 +988,7 @@ pub fn (t &Table) thread_name(return_type Type) string {
}
return_type_sym := t.sym(return_type)
ptr := if return_type.is_ptr() { '&' } else { '' }
opt := if return_type.has_flag(.optional) { '?' } else { '' }
opt := if return_type.has_flag(.option) { '?' } else { '' }
res := if return_type.has_flag(.result) { '!' } else { '' }
return 'thread ${opt}${res}${ptr}${return_type_sym.name}'
}
@ -996,7 +996,7 @@ pub fn (t &Table) thread_name(return_type Type) string {
[inline]
pub fn (t &Table) thread_cname(return_type Type) string {
if return_type == void_type {
if return_type.has_flag(.optional) {
if return_type.has_flag(.option) {
return '__v_thread_Option_void'
} else if return_type.has_flag(.result) {
return '__v_thread_Result_void'
@ -1006,7 +1006,7 @@ pub fn (t &Table) thread_cname(return_type Type) string {
}
return_type_sym := t.sym(return_type)
suffix := if return_type.is_ptr() { '_ptr' } else { '' }
opt := if return_type.has_flag(.optional) { '_option_' } else { '' }
opt := if return_type.has_flag(.option) { '_option_' } else { '' }
res := if return_type.has_flag(.result) { '_result_' } else { '' }
return '__v_thread_${opt}${res}${return_type_sym.cname}${suffix}'
}
@ -1018,7 +1018,7 @@ pub fn (t &Table) map_name(key_type Type, value_type Type) string {
key_type_sym := t.sym(key_type)
value_type_sym := t.sym(value_type)
ptr := if value_type.is_ptr() { '&'.repeat(value_type.nr_muls()) } else { '' }
opt := if value_type.has_flag(.optional) { '?' } else { '' }
opt := if value_type.has_flag(.option) { '?' } else { '' }
res := if value_type.has_flag(.result) { '!' } else { '' }
return 'map[${key_type_sym.name}]${opt}${res}${ptr}${value_type_sym.name}'
}
@ -1028,7 +1028,7 @@ pub fn (t &Table) map_cname(key_type Type, value_type Type) string {
key_type_sym := t.sym(key_type)
value_type_sym := t.sym(value_type)
suffix := if value_type.is_ptr() { '_ptr'.repeat(value_type.nr_muls()) } else { '' }
opt := if value_type.has_flag(.optional) { '_option_' } else { '' }
opt := if value_type.has_flag(.option) { '_option_' } else { '' }
res := if value_type.has_flag(.result) { '_result_' } else { '' }
if value_type_sym.cname.contains('[') {
type_name := value_type_sym.cname.replace_each(['[', '_T_', ', ', '_', ']', ''])

View File

@ -105,7 +105,7 @@ pub mut:
// max of 8
pub enum TypeFlag {
optional
option
result
variadic
generic
@ -280,8 +280,8 @@ pub fn (t Type) debug() []string {
res << 'idx: 0x${t.idx().hex():-8}'
res << 'type: 0x${t.hex():-8}'
res << 'nr_muls: ${t.nr_muls()}'
if t.has_flag(.optional) {
res << 'optional'
if t.has_flag(.option) {
res << 'option'
}
if t.has_flag(.result) {
res << 'result'
@ -486,7 +486,7 @@ pub const (
pub const (
void_type = new_type(void_type_idx)
ovoid_type = new_type(void_type_idx).set_flag(.optional) // the return type of `fn ()?`
ovoid_type = new_type(void_type_idx).set_flag(.option) // the return type of `fn ()?`
rvoid_type = new_type(void_type_idx).set_flag(.result) // the return type of `fn () !`
voidptr_type = new_type(voidptr_type_idx)
byteptr_type = new_type(byteptr_type_idx)
@ -569,7 +569,7 @@ pub mut:
// returns TypeSymbol kind only if there are no type modifiers
pub fn (t &Table) type_kind(typ Type) Kind {
if typ.nr_muls() > 0 || typ.has_flag(.optional) || typ.has_flag(.result) {
if typ.nr_muls() > 0 || typ.has_flag(.option) || typ.has_flag(.result) {
return Kind.placeholder
}
return t.sym(typ).kind
@ -866,7 +866,7 @@ pub fn (t &TypeSymbol) is_builtin() bool {
// type_size returns the size and alignment (in bytes) of `typ`, similarly to C's `sizeof()` and `alignof()`.
pub fn (t &Table) type_size(typ Type) (int, int) {
if typ.has_flag(.optional) || typ.has_flag(.result) {
if typ.has_flag(.option) || typ.has_flag(.result) {
return t.type_size(ast.error_type_idx)
}
if typ.nr_muls() > 0 {
@ -1328,7 +1328,7 @@ pub fn (t &Table) type_to_str_using_aliases(typ Type, import_aliases map[string]
res += ']'
}
.void {
if typ.has_flag(.optional) {
if typ.has_flag(.option) {
res = '?'
return res
}
@ -1369,7 +1369,7 @@ pub fn (t &Table) type_to_str_using_aliases(typ Type, import_aliases map[string]
if nr_muls > 0 && !typ.has_flag(.variadic) {
res = strings.repeat(`&`, nr_muls) + res
}
if typ.has_flag(.optional) {
if typ.has_flag(.option) {
res = '?${res}'
}
if typ.has_flag(.result) {

View File

@ -37,30 +37,30 @@ fn test_flags() {
mut t := ast.new_type(ast.void_type_idx)
idx := t.idx()
nr_muls := t.nr_muls()
t = t.set_flag(ast.TypeFlag.optional)
assert t.has_flag(ast.TypeFlag.optional) == true
t = t.set_flag(ast.TypeFlag.option)
assert t.has_flag(ast.TypeFlag.option) == true
assert t.has_flag(ast.TypeFlag.variadic) == false
assert t.has_flag(ast.TypeFlag.generic) == false
t = t.set_flag(ast.TypeFlag.variadic)
assert t.has_flag(ast.TypeFlag.optional) == true
assert t.has_flag(ast.TypeFlag.option) == true
assert t.has_flag(ast.TypeFlag.variadic) == true
assert t.has_flag(ast.TypeFlag.generic) == false
t = t.set_flag(ast.TypeFlag.generic)
assert t.has_flag(ast.TypeFlag.optional) == true
assert t.has_flag(ast.TypeFlag.option) == true
assert t.has_flag(ast.TypeFlag.variadic) == true
assert t.has_flag(ast.TypeFlag.generic) == true
assert t.idx() == idx
assert t.nr_muls() == nr_muls
t = t.clear_flag(ast.TypeFlag.optional)
assert t.has_flag(ast.TypeFlag.optional) == false
t = t.clear_flag(ast.TypeFlag.option)
assert t.has_flag(ast.TypeFlag.option) == false
assert t.has_flag(ast.TypeFlag.variadic) == true
assert t.has_flag(ast.TypeFlag.generic) == true
t = t.clear_flag(ast.TypeFlag.variadic)
assert t.has_flag(ast.TypeFlag.optional) == false
assert t.has_flag(ast.TypeFlag.option) == false
assert t.has_flag(ast.TypeFlag.variadic) == false
assert t.has_flag(ast.TypeFlag.generic) == true
t = t.clear_flag(ast.TypeFlag.generic)
assert t.has_flag(ast.TypeFlag.optional) == false
assert t.has_flag(ast.TypeFlag.option) == false
assert t.has_flag(ast.TypeFlag.variadic) == false
assert t.has_flag(ast.TypeFlag.generic) == false
assert t.idx() == idx
@ -74,7 +74,7 @@ fn test_derive() {
t = t.set_nr_muls(10)
mut t2 := ast.new_type(ast.i16_type_idx)
t2 = t2.derive(t)
assert t2.has_flag(ast.TypeFlag.optional) == false
assert t2.has_flag(ast.TypeFlag.option) == false
assert t2.has_flag(ast.TypeFlag.variadic) == true
assert t2.has_flag(ast.TypeFlag.generic) == true
assert t2.nr_muls() == 10

View File

@ -130,7 +130,7 @@ fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
}
}
// allow direct int-literal assignment for pointers for now
// maybe in the future optionals should be used for that
// maybe in the future options should be used for that
if expected.is_real_pointer() {
if got == ast.int_literal_type {
return true
@ -146,15 +146,15 @@ fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
if expected == ast.charptr_type && got == ast.char_type.ref() {
return true
}
if expected.has_flag(.optional) || expected.has_flag(.result) {
if expected.has_flag(.option) || expected.has_flag(.result) {
sym := c.table.sym(got)
if ((sym.idx == ast.error_type_idx || got in [ast.none_type, ast.error_type])
&& expected.has_flag(.optional))
&& expected.has_flag(.option))
|| ((sym.idx == ast.error_type_idx || got == ast.error_type)
&& expected.has_flag(.result)) {
// IError
return true
} else if !c.check_basic(got, expected.clear_flag(.optional).clear_flag(.result)) {
} else if !c.check_basic(got, expected.clear_flag(.option).clear_flag(.result)) {
return false
}
}
@ -402,7 +402,7 @@ fn (mut c Checker) check_matching_function_symbols(got_type_sym &ast.TypeSymbol,
if got_fn.params.len != exp_fn.params.len {
return false
}
if got_fn.return_type.has_flag(.optional) != exp_fn.return_type.has_flag(.optional) {
if got_fn.return_type.has_flag(.option) != exp_fn.return_type.has_flag(.option) {
return false
}
if got_fn.return_type.has_flag(.result) != exp_fn.return_type.has_flag(.result) {
@ -581,7 +581,7 @@ fn (mut c Checker) promote(left_type ast.Type, right_type ast.Type) ast.Type {
}
if right_type.is_number() && left_type.is_number() {
return c.promote_num(left_type, right_type)
} else if left_type.has_flag(.optional) != right_type.has_flag(.optional) {
} else if left_type.has_flag(.option) != right_type.has_flag(.option) {
// incompatible
return ast.void_type
} else {
@ -645,7 +645,7 @@ fn (c &Checker) expected_msg(got ast.Type, expected ast.Type) string {
fn (mut c Checker) symmetric_check(left ast.Type, right ast.Type) bool {
// allow direct int-literal assignment for pointers for now
// maybe in the future optionals should be used for that
// maybe in the future options should be used for that
if right.is_ptr() || right.is_pointer() {
if left == ast.int_literal_type {
return true

View File

@ -920,23 +920,23 @@ fn (mut c Checker) type_implements(typ ast.Type, interface_type ast.Type, pos to
return true
}
// return the actual type of the expression, once the optional is handled
// return the actual type of the expression, once the option is handled
fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type ast.Type) ast.Type {
if expr is ast.CallExpr {
mut expr_ret_type := expr.return_type
if expr_ret_type != 0 && c.table.sym(expr_ret_type).kind == .alias {
unaliased_ret_type := c.table.unaliased_type(expr_ret_type)
if unaliased_ret_type.has_flag(.optional) || unaliased_ret_type.has_flag(.result) {
if unaliased_ret_type.has_flag(.option) || unaliased_ret_type.has_flag(.result) {
expr_ret_type = unaliased_ret_type
}
}
if expr_ret_type.has_flag(.optional) || expr_ret_type.has_flag(.result) {
return_modifier_kind := if expr_ret_type.has_flag(.optional) {
if expr_ret_type.has_flag(.option) || expr_ret_type.has_flag(.result) {
return_modifier_kind := if expr_ret_type.has_flag(.option) {
'an option'
} else {
'a result'
}
return_modifier := if expr_ret_type.has_flag(.optional) { '?' } else { '!' }
return_modifier := if expr_ret_type.has_flag(.option) { '?' } else { '!' }
if expr.or_block.kind == .absent {
if c.inside_defer {
c.error('${expr.name}() returns ${return_modifier_kind}, so it should have an `or {}` block at the end',
@ -948,25 +948,25 @@ fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type ast.Type) ast.Typ
} else {
c.check_or_expr(expr.or_block, ret_type, expr_ret_type)
}
return ret_type.clear_flag(.optional).clear_flag(.result)
return ret_type.clear_flag(.option).clear_flag(.result)
} else if expr.or_block.kind == .block {
c.error('unexpected `or` block, the function `${expr.name}` does neither return an optional nor a result',
c.error('unexpected `or` block, the function `${expr.name}` does not return an option or a result',
expr.or_block.pos)
} else if expr.or_block.kind == .propagate_option {
c.error('unexpected `?`, the function `${expr.name}` does not return an optional',
c.error('unexpected `?`, the function `${expr.name}` does not return an option',
expr.or_block.pos)
} else if expr.or_block.kind == .propagate_result {
c.error('unexpected `!`, the function `${expr.name}` does not return a result',
expr.or_block.pos)
}
} else if expr is ast.SelectorExpr && c.table.sym(ret_type).kind != .chan {
if expr.typ.has_flag(.optional) || expr.typ.has_flag(.result) {
with_modifier_kind := if expr.typ.has_flag(.optional) {
if expr.typ.has_flag(.option) || expr.typ.has_flag(.result) {
with_modifier_kind := if expr.typ.has_flag(.option) {
'an option'
} else {
'a result'
}
with_modifier := if expr.typ.has_flag(.optional) { '?' } else { '!' }
with_modifier := if expr.typ.has_flag(.option) { '?' } else { '!' }
if expr.or_block.kind == .absent {
if c.inside_defer {
c.error('field `${expr.field_name}` is ${with_modifier_kind}, so it should have an `or {}` block at the end',
@ -978,12 +978,12 @@ fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type ast.Type) ast.Typ
} else {
c.check_or_expr(expr.or_block, ret_type, expr.typ)
}
return ret_type.clear_flag(.optional).clear_flag(.result)
return ret_type.clear_flag(.option).clear_flag(.result)
} else if expr.or_block.kind == .block {
c.error('unexpected `or` block, the field `${expr.field_name}` is neither an optional, nor a result',
c.error('unexpected `or` block, the field `${expr.field_name}` is neither an option, nor a result',
expr.or_block.pos)
} else if expr.or_block.kind == .propagate_option {
c.error('unexpected `?`, the field `${expr.field_name}` is not an optional',
c.error('unexpected `?`, the field `${expr.field_name}` is not an option',
expr.or_block.pos)
} else if expr.or_block.kind == .propagate_result {
c.error('unexpected `!`, result fields are not supported', expr.or_block.pos)
@ -998,18 +998,18 @@ fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type ast.Type) ast.Typ
fn (mut c Checker) check_or_expr(node ast.OrExpr, ret_type ast.Type, expr_return_type ast.Type) {
if node.kind == .propagate_option {
if c.table.cur_fn != unsafe { nil } && !c.table.cur_fn.return_type.has_flag(.optional)
if c.table.cur_fn != unsafe { nil } && !c.table.cur_fn.return_type.has_flag(.option)
&& !c.table.cur_fn.is_main && !c.table.cur_fn.is_test && !c.inside_const {
c.add_instruction_for_optional_type()
c.error('to propagate the call, `${c.table.cur_fn.name}` must return an optional type',
c.add_instruction_for_option_type()
c.error('to propagate the call, `${c.table.cur_fn.name}` must return an option type',
node.pos)
}
if !expr_return_type.has_flag(.optional) {
if !expr_return_type.has_flag(.option) {
if expr_return_type.has_flag(.result) {
c.warn('propagating a result like an option is deprecated, use `foo()!` instead of `foo()?`',
node.pos)
} else {
c.error('to propagate an option, the call must also return an optional type',
c.error('to propagate an option, the call must also return an option type',
node.pos)
}
}
@ -1038,7 +1038,7 @@ fn (mut c Checker) check_or_expr(node ast.OrExpr, ret_type ast.Type, expr_return
return
}
last_stmt := node.stmts.last()
c.check_or_last_stmt(last_stmt, ret_type, expr_return_type.clear_flag(.optional).clear_flag(.result))
c.check_or_last_stmt(last_stmt, ret_type, expr_return_type.clear_flag(.option).clear_flag(.result))
}
fn (mut c Checker) check_or_last_stmt(stmt ast.Stmt, ret_type ast.Type, expr_return_type ast.Type) {
@ -1046,7 +1046,7 @@ fn (mut c Checker) check_or_last_stmt(stmt ast.Stmt, ret_type ast.Type, expr_ret
match stmt {
ast.ExprStmt {
c.expected_type = ret_type
c.expected_or_type = ret_type.clear_flag(.optional).clear_flag(.result)
c.expected_or_type = ret_type.clear_flag(.option).clear_flag(.result)
last_stmt_typ := c.expr(stmt.expr)
c.expected_or_type = ast.void_type
type_fits := c.check_types(last_stmt_typ, ret_type)
@ -1071,7 +1071,7 @@ fn (mut c Checker) check_or_last_stmt(stmt ast.Stmt, ret_type ast.Type, expr_ret
}
return
}
expected_type_name := c.table.type_to_str(ret_type.clear_flag(.optional).clear_flag(.result))
expected_type_name := c.table.type_to_str(ret_type.clear_flag(.option).clear_flag(.result))
c.error('`or` block must provide a default value of type `${expected_type_name}`, or return/continue/break or call a [noreturn] function like panic(err) or exit(1)',
stmt.expr.pos())
} else {
@ -1080,7 +1080,7 @@ fn (mut c Checker) check_or_last_stmt(stmt ast.Stmt, ret_type ast.Type, expr_ret
return
}
type_name := c.table.type_to_str(last_stmt_typ)
expected_type_name := c.table.type_to_str(ret_type.clear_flag(.optional).clear_flag(.result))
expected_type_name := c.table.type_to_str(ret_type.clear_flag(.option).clear_flag(.result))
c.error('wrong return type `${type_name}` in the `or {}` block, expected `${expected_type_name}`',
stmt.expr.pos())
}
@ -1094,7 +1094,7 @@ fn (mut c Checker) check_or_last_stmt(stmt ast.Stmt, ret_type ast.Type, expr_ret
}
ast.Return {}
else {
expected_type_name := c.table.type_to_str(ret_type.clear_flag(.optional).clear_flag(.result))
expected_type_name := c.table.type_to_str(ret_type.clear_flag(.option).clear_flag(.result))
c.error('last statement in the `or {}` block should be an expression of type `${expected_type_name}` or exit parent scope',
stmt.pos)
}
@ -1219,8 +1219,8 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
}
node.expr_type = typ
if !(node.expr is ast.Ident && (node.expr as ast.Ident).kind == .constant) {
if node.expr_type.has_flag(.optional) {
c.error('cannot access fields of an optional, handle the error with `or {...}` or propagate it with `?`',
if node.expr_type.has_flag(.option) {
c.error('cannot access fields of an option, handle the error with `or {...}` or propagate it with `?`',
node.pos)
} else if node.expr_type.has_flag(.result) {
c.error('cannot access fields of a result, handle the error with `or {...}` or propagate it with `!`',
@ -1337,7 +1337,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
}
node.typ = field.typ
if node.or_block.kind == .block {
c.expected_or_type = node.typ.clear_flag(.optional).clear_flag(.result)
c.expected_or_type = node.typ.clear_flag(.option).clear_flag(.result)
c.stmts_ending_with_expression(node.or_block.stmts)
c.expected_or_type = ast.void_type
}
@ -2338,25 +2338,25 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
mut ret_type := c.call_expr(mut node)
if ret_type != 0 && c.table.sym(ret_type).kind == .alias {
unaliased_type := c.table.unaliased_type(ret_type)
if unaliased_type.has_flag(.optional) || unaliased_type.has_flag(.result) {
if unaliased_type.has_flag(.option) || unaliased_type.has_flag(.result) {
ret_type = unaliased_type
}
}
if !ret_type.has_flag(.optional) && !ret_type.has_flag(.result) {
if !ret_type.has_flag(.option) && !ret_type.has_flag(.result) {
if node.or_block.kind == .block {
c.error('unexpected `or` block, the function `${node.name}` does neither return an optional nor a result',
c.error('unexpected `or` block, the function `${node.name}` does not return an option or a result',
node.or_block.pos)
} else if node.or_block.kind == .propagate_option {
c.error('unexpected `?`, the function `${node.name}` does neither return an optional nor a result',
c.error('unexpected `?`, the function `${node.name}` does not return an option or a result',
node.or_block.pos)
} else if node.or_block.kind == .propagate_result {
c.error('unexpected `!`, the function `${node.name}` does neither return an optional nor a result',
c.error('unexpected `!`, the function `${node.name}` does not return an option or a result',
node.or_block.pos)
}
}
if node.or_block.kind != .absent {
if ret_type.has_flag(.optional) {
ret_type = ret_type.clear_flag(.optional)
if ret_type.has_flag(.option) {
ret_type = ret_type.clear_flag(.option)
}
if ret_type.has_flag(.result) {
ret_type = ret_type.clear_flag(.result)
@ -2401,7 +2401,7 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
unwrapped_expr_type := c.unwrap_generic(node.expr_type)
tsym := c.table.sym(unwrapped_expr_type)
c.table.dumps[int(unwrapped_expr_type.clear_flag(.optional).clear_flag(.result))] = tsym.cname
c.table.dumps[int(unwrapped_expr_type.clear_flag(.option).clear_flag(.result))] = tsym.cname
node.cname = tsym.cname
return node.expr_type
}
@ -2425,18 +2425,18 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
c.inside_if_guard = true
node.expr_type = c.expr(node.expr)
c.inside_if_guard = old_inside_if_guard
if !node.expr_type.has_flag(.optional) && !node.expr_type.has_flag(.result) {
if !node.expr_type.has_flag(.option) && !node.expr_type.has_flag(.result) {
mut no_opt_or_res := true
match mut node.expr {
ast.IndexExpr {
no_opt_or_res = false
node.expr_type = node.expr_type.set_flag(.optional)
node.expr_type = node.expr_type.set_flag(.option)
node.expr.is_option = true
}
ast.PrefixExpr {
if node.expr.op == .arrow {
no_opt_or_res = false
node.expr_type = node.expr_type.set_flag(.optional)
node.expr_type = node.expr_type.set_flag(.option)
node.expr.is_option = true
}
}
@ -2519,21 +2519,21 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
return ret_type
}
if !ret_type.has_flag(.optional) && !ret_type.has_flag(.result) {
if !ret_type.has_flag(.option) && !ret_type.has_flag(.result) {
if node.or_block.kind == .block {
c.error('unexpected `or` block, the field `${node.field_name}` is neither an optional, nor a result',
c.error('unexpected `or` block, the field `${node.field_name}` is neither an option, nor a result',
node.or_block.pos)
} else if node.or_block.kind == .propagate_option {
c.error('unexpected `?`, the field `${node.field_name}` is neither an optional, nor a result',
c.error('unexpected `?`, the field `${node.field_name}` is neither an option, nor a result',
node.or_block.pos)
} else if node.or_block.kind == .propagate_result {
c.error('unexpected `!`, the field `${node.field_name}` is neither an optional, nor a result',
c.error('unexpected `!`, the field `${node.field_name}` is neither an option, nor a result',
node.or_block.pos)
}
}
if node.or_block.kind != .absent {
if ret_type.has_flag(.optional) {
ret_type = ret_type.clear_flag(.optional)
if ret_type.has_flag(.option) {
ret_type = ret_type.clear_flag(.option)
}
if ret_type.has_flag(.result) {
ret_type = ret_type.clear_flag(.result)
@ -2641,8 +2641,8 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
mut to_sym := c.table.sym(to_type) // type to be used as cast
mut final_to_sym := c.table.final_sym(to_type)
if to_type.has_flag(.optional) {
c.error('casting to optional type is forbidden', node.pos)
if to_type.has_flag(.option) {
c.error('casting to option type is forbidden', node.pos)
} else if to_type.has_flag(.result) {
c.error('casting to result type is forbidden', node.pos)
}
@ -2674,7 +2674,7 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
node.expr_type = c.promote_num(node.expr_type, xx)
from_type = node.expr_type
}
if !c.table.sumtype_has_variant(to_type, from_type, false) && !to_type.has_flag(.optional)
if !c.table.sumtype_has_variant(to_type, from_type, false) && !to_type.has_flag(.option)
&& !to_type.has_flag(.result) {
ft := c.table.type_to_str(from_type)
tt := c.table.type_to_str(to_type)
@ -2736,8 +2736,7 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
} else if to_type == ast.bool_type && from_type != ast.bool_type && !c.inside_unsafe
&& !c.pref.translated && !c.file.is_translated {
c.error('cannot cast to bool - use e.g. `some_int != 0` instead', node.pos)
} else if from_type == ast.none_type && !to_type.has_flag(.optional)
&& !to_type.has_flag(.result) {
} else if from_type == ast.none_type && !to_type.has_flag(.option) && !to_type.has_flag(.result) {
type_name := c.table.type_to_str(to_type)
c.error('cannot cast `none` to `${type_name}`', node.pos)
} else if from_sym.kind == .struct_ && !from_type.is_ptr() {
@ -2751,11 +2750,11 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
ft := c.table.type_to_str(from_type)
tt := c.table.type_to_str(to_type)
c.error('cannot cast type `${ft}` to `${tt}`', node.pos)
} else if from_type.has_flag(.optional) || from_type.has_flag(.result)
} else if from_type.has_flag(.option) || from_type.has_flag(.result)
|| from_type.has_flag(.variadic) {
// variadic case can happen when arrays are converted into variadic
msg := if from_type.has_flag(.optional) {
'an optional'
msg := if from_type.has_flag(.option) {
'an option'
} else if from_type.has_flag(.result) {
'a result'
} else {
@ -3083,7 +3082,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
}
}
if mut obj.expr is ast.IfGuardExpr {
// new variable from if guard shouldn't have the optional flag for further use
// new variable from if guard shouldn't have the option flag for further use
// a temp variable will be generated which unwraps it
sym := c.table.sym(obj.expr.expr_type)
if sym.kind == .multi_return {
@ -3096,7 +3095,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
}
}
} else {
typ = obj.expr.expr_type.clear_flag(.optional).clear_flag(.result)
typ = obj.expr.expr_type.clear_flag(.option).clear_flag(.result)
}
} else if obj.expr is ast.EmptyExpr {
c.error('invalid variable `${node.name}`', node.pos)
@ -3105,19 +3104,19 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
typ = c.expr(obj.expr)
}
}
is_optional := typ.has_flag(.optional) || typ.has_flag(.result)
is_option := typ.has_flag(.option) || typ.has_flag(.result)
node.kind = .variable
node.info = ast.IdentVar{
typ: typ
is_optional: is_optional
is_option: is_option
}
if !is_sum_type_cast {
obj.typ = typ
}
node.obj = obj
// unwrap optional (`println(x)`)
if is_optional {
return typ.clear_flag(.optional).clear_flag(.result)
// unwrap option (`println(x)`)
if is_option {
return typ.clear_flag(.option).clear_flag(.result)
}
return typ
}
@ -3158,7 +3157,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
if mut obj.expr is ast.CallExpr {
if obj.expr.or_block.kind != .absent {
typ = typ.clear_flag(.optional).clear_flag(.result)
typ = typ.clear_flag(.option).clear_flag(.result)
}
}
}
@ -3613,8 +3612,8 @@ fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type {
node.pos.extend(node.right.pos))
}
if node.right.typ.has_flag(.optional) {
c.error('cannot take the address of an optional field', node.pos.extend(node.right.pos))
if node.right.typ.has_flag(.option) {
c.error('cannot take the address of an option field', node.pos.extend(node.right.pos))
}
}
}
@ -3742,13 +3741,13 @@ fn (mut c Checker) check_index(typ_sym &ast.TypeSymbol, index ast.Expr, index_ty
}
}
}
if index_type.has_flag(.optional) || index_type.has_flag(.result) {
if index_type.has_flag(.option) || index_type.has_flag(.result) {
type_str := if typ_sym.kind == .string {
'(type `${typ_sym.name}`)'
} else {
'(array type `${typ_sym.name}`)'
}
c.error('cannot use optional or result as index ${type_str}', pos)
c.error('cannot use option or result as index ${type_str}', pos)
}
}
}
@ -3789,10 +3788,11 @@ fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
&& typ !in [ast.byteptr_type, ast.charptr_type] && !typ.has_flag(.variadic) {
c.error('type `${typ_sym.name}` does not support indexing', node.pos)
}
if typ.has_flag(.optional) {
c.error('type `?${typ_sym.name}` is optional, it does not support indexing', node.left.pos())
if typ.has_flag(.option) {
c.error('type `?${typ_sym.name}` is an option, it does not support indexing',
node.left.pos())
} else if typ.has_flag(.result) {
c.error('type `!${typ_sym.name}` is result, it does not support indexing', node.left.pos())
c.error('type `!${typ_sym.name}` is a result, it does not support indexing', node.left.pos())
}
if typ_sym.kind == .string && !typ.is_ptr() && node.is_setter {
c.error('cannot assign to s[i] since V strings are immutable\n' +
@ -4004,7 +4004,7 @@ fn (mut c Checker) add_error_detail_with_pos(msg string, pos token.Pos) {
c.add_error_detail(util.formatted_error('details:', msg, c.file.path, pos))
}
fn (mut c Checker) add_instruction_for_optional_type() {
fn (mut c Checker) add_instruction_for_option_type() {
c.add_error_detail_with_pos('prepend ? before the declaration of the return type of `${c.table.cur_fn.name}`',
c.table.cur_fn.return_type_pos)
}

View File

@ -188,7 +188,7 @@ fn (mut c Checker) comptime_for(node ast.ComptimeFor) {
unwrapped_expr_type := c.unwrap_generic(field.typ)
tsym := c.table.sym(unwrapped_expr_type)
c.table.dumps[int(unwrapped_expr_type.clear_flag(.optional).clear_flag(.result).clear_flag(.atomic_f))] = tsym.cname
c.table.dumps[int(unwrapped_expr_type.clear_flag(.option).clear_flag(.result).clear_flag(.atomic_f))] = tsym.cname
}
c.comptime_for_field_var = ''
c.inside_comptime_for_field = false
@ -445,7 +445,7 @@ fn (mut c Checker) evaluate_once_comptime_if_attribute(mut node ast.Attr) bool {
if node.ct_expr is ast.Ident {
if node.ct_opt {
if node.ct_expr.name in constants.valid_comptime_not_user_defined {
c.error('optional `[if expression ?]` tags, can be used only for user defined identifiers',
c.error('option `[if expression ?]` tags, can be used only for user defined identifiers',
node.pos)
node.ct_skip = true
} else {
@ -765,7 +765,7 @@ fn (mut c Checker) check_comptime_is_field_selector(node ast.SelectorExpr) bool
[inline]
fn (mut c Checker) check_comptime_is_field_selector_bool(node ast.SelectorExpr) bool {
if c.check_comptime_is_field_selector(node) {
return node.field_name in ['is_mut', 'is_pub', 'is_shared', 'is_atomic', 'is_optional',
return node.field_name in ['is_mut', 'is_pub', 'is_shared', 'is_atomic', 'is_option',
'is_array', 'is_map', 'is_chan', 'is_struct', 'is_alias']
}
return false
@ -781,7 +781,7 @@ fn (mut c Checker) get_comptime_selector_bool_field(field_name string) bool {
'is_mut' { return field.is_mut }
'is_shared' { return field_typ.has_flag(.shared_f) }
'is_atomic' { return field_typ.has_flag(.atomic_f) }
'is_optional' { return field.typ.has_flag(.optional) }
'is_option' { return field.typ.has_flag(.option) }
'is_array' { return field_sym.kind in [.array, .array_fixed] }
'is_map' { return field_sym.kind == .map }
'is_chan' { return field_sym.kind == .chan }

View File

@ -116,12 +116,12 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
// }
array_info := type_sym.array_info()
node.elem_type = array_info.elem_type
// clear optional flag incase of: `fn opt_arr() ?[]int { return [] }`
// clear option flag incase of: `fn opt_arr() ?[]int { return [] }`
return if c.expected_type.has_flag(.shared_f) {
c.expected_type.clear_flag(.shared_f).deref()
} else {
c.expected_type
}.clear_flag(.optional).clear_flag(.result)
}.clear_flag(.option).clear_flag(.result)
}
// [1,2,3]
if node.exprs.len > 0 && node.elem_type == ast.void_type {
@ -282,7 +282,7 @@ fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
sym := c.table.sym(c.expected_type)
if sym.kind == .map {
info := sym.map_info()
node.typ = c.expected_type.clear_flag(.optional).clear_flag(.result)
node.typ = c.expected_type.clear_flag(.option).clear_flag(.result)
node.key_type = info.key_type
node.value_type = info.value_type
return node.typ

View File

@ -117,7 +117,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
if multi_type == ast.error_type {
c.error('type `IError` cannot be used in multi-return, return an option instead',
node.return_type_pos)
} else if multi_type.has_flag(.optional) {
} else if multi_type.has_flag(.option) {
c.error('option cannot be used in multi-return, return an option instead',
node.return_type_pos)
} else if multi_type.has_flag(.result) {
@ -211,9 +211,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
c.error('invalid use of reserved type `${param.name}` as a parameter name',
param.pos)
}
if param.typ.has_flag(.optional) || param.typ.has_flag(.result) {
c.error('optional or result type argument is not supported currently',
param.type_pos)
if param.typ.has_flag(.option) || param.typ.has_flag(.result) {
c.error('option or result type argument is not supported currently', param.type_pos)
}
arg_typ_sym := c.table.sym(param.typ)
if arg_typ_sym.info is ast.Struct {
@ -333,7 +332,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
}
if node.return_type != ast.void_type_idx
&& node.return_type.clear_flag(.optional) != ast.void_type_idx
&& node.return_type.clear_flag(.option) != ast.void_type_idx
&& node.return_type.clear_flag(.result) != ast.void_type_idx {
c.error('test functions should either return nothing at all, or be marked to return `?` or `!`',
node.pos)
@ -343,7 +342,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
c.table.cur_fn = unsafe { node }
// c.table.cur_fn = node
// Add return if `fn(...) ? {...}` have no return at end
if node.return_type != ast.void_type && node.return_type.has_flag(.optional)
if node.return_type != ast.void_type && node.return_type.has_flag(.option)
&& (node.stmts.len == 0 || node.stmts.last() !is ast.Return) {
sym := c.table.sym(node.return_type)
if sym.kind == .void {
@ -476,7 +475,7 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
c.inside_fn_arg = old_inside_fn_arg
// autofree: mark args that have to be freed (after saving them in tmp exprs)
free_tmp_arg_vars := c.pref.autofree && !c.is_builtin_mod && node.args.len > 0
&& !node.args[0].typ.has_flag(.optional) && !node.args[0].typ.has_flag(.result)
&& !node.args[0].typ.has_flag(.option) && !node.args[0].typ.has_flag(.result)
if free_tmp_arg_vars && !c.inside_const {
for i, arg in node.args {
if arg.typ != ast.string_type {
@ -497,7 +496,7 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
node.free_receiver = true
}
}
c.expected_or_type = node.return_type.clear_flag(.optional).clear_flag(.result)
c.expected_or_type = node.return_type.clear_flag(.option).clear_flag(.result)
c.stmts_ending_with_expression(node.or_block.stmts)
c.expected_or_type = ast.void_type
@ -505,15 +504,14 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
&& !c.table.cur_fn.is_test {
// TODO: use just `if node.or_block.kind == .propagate_result && !c.table.cur_fn.return_type.has_flag(.result) {` after the deprecation for ?!Type
if node.or_block.kind == .propagate_result && !c.table.cur_fn.return_type.has_flag(.result)
&& !c.table.cur_fn.return_type.has_flag(.optional) {
&& !c.table.cur_fn.return_type.has_flag(.option) {
c.add_instruction_for_result_type()
c.error('to propagate the result call, `${c.table.cur_fn.name}` must return a result',
node.or_block.pos)
}
if node.or_block.kind == .propagate_option
&& !c.table.cur_fn.return_type.has_flag(.optional) {
c.add_instruction_for_optional_type()
c.error('to propagate the optional call, `${c.table.cur_fn.name}` must return an optional',
if node.or_block.kind == .propagate_option && !c.table.cur_fn.return_type.has_flag(.option) {
c.add_instruction_for_option_type()
c.error('to propagate the option call, `${c.table.cur_fn.name}` must return an option',
node.or_block.pos)
}
}
@ -611,7 +609,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
match tsym.info {
ast.Struct {
mut ret_type := tsym.info.concrete_types[0]
ret_type = ret_type.set_flag(.optional)
ret_type = ret_type.set_flag(.option)
node.return_type = ret_type
return ret_type
}
@ -1328,8 +1326,8 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
} else {
'unknown method or field: `${left_sym.name}.${method_name}`'
}
if left_type.has_flag(.optional) {
c.error('optional type cannot be called directly', node.left.pos())
if left_type.has_flag(.option) {
c.error('option type cannot be called directly', node.left.pos())
return ast.void_type
} else if left_type.has_flag(.result) {
c.error('result type cannot be called directly', node.left.pos())
@ -1401,7 +1399,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
c.table.cur_fn.has_await = true
}
node.return_type = info.concrete_types[0]
node.return_type.set_flag(.optional)
node.return_type.set_flag(.option)
return node.return_type
} else if left_sym.kind == .thread && method_name == 'wait' {
info := left_sym.info as ast.Thread
@ -1960,7 +1958,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
fn (mut c Checker) go_expr(mut node ast.GoExpr) ast.Type {
ret_type := c.call_expr(mut node.call_expr)
if node.call_expr.or_block.kind != .absent {
c.error('optional handling cannot be done in `go` call. Do it when calling `.wait()`',
c.error('option handling cannot be done in `go` call. Do it when calling `.wait()`',
node.call_expr.or_block.pos)
}
// Make sure there are no mutable arguments
@ -2072,8 +2070,8 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ ast.Type, node ast
arg_expr := node.args[0].expr
match arg_expr {
ast.AnonFn {
if arg_expr.decl.return_type.has_flag(.optional) {
c.error('optional needs to be unwrapped before using it in map/filter',
if arg_expr.decl.return_type.has_flag(.option) {
c.error('option needs to be unwrapped before using it in map/filter',
node.args[0].pos)
}
if arg_expr.decl.params.len > 1 {
@ -2094,8 +2092,8 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ ast.Type, node ast
c.error('${arg_expr.name} does not exist', arg_expr.pos)
return
}
if func.return_type.has_flag(.optional) {
c.error('optional needs to be unwrapped before using it in map/filter',
if func.return_type.has_flag(.option) {
c.error('option needs to be unwrapped before using it in map/filter',
node.pos)
}
if func.params.len > 1 {
@ -2114,8 +2112,8 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ ast.Type, node ast
expr := arg_expr.obj.expr
if expr is ast.AnonFn {
// copied from above
if expr.decl.return_type.has_flag(.optional) {
c.error('optional needs to be unwrapped before using it in map/filter',
if expr.decl.return_type.has_flag(.option) {
c.error('option needs to be unwrapped before using it in map/filter',
arg_expr.pos)
}
if expr.decl.params.len > 1 {
@ -2145,9 +2143,9 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ ast.Type, node ast
c.error('type mismatch, `${arg_expr.name}` does not return anything',
arg_expr.pos)
} else if !is_map && arg_expr.return_type != ast.bool_type {
if arg_expr.or_block.kind != .absent && (arg_expr.return_type.has_flag(.optional)
if arg_expr.or_block.kind != .absent && (arg_expr.return_type.has_flag(.option)
|| arg_expr.return_type.has_flag(.result))
&& arg_expr.return_type.clear_flag(.optional).clear_flag(.result) == ast.bool_type {
&& arg_expr.return_type.clear_flag(.option).clear_flag(.result) == ast.bool_type {
return
}
c.error('type mismatch, `${arg_expr.name}` must return a bool', arg_expr.pos)
@ -2283,8 +2281,8 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
c.error('`.wait()` does not have any arguments', node.args[0].pos)
}
thread_ret_type := elem_sym.thread_info().return_type
if thread_ret_type.has_flag(.optional) {
c.error('`.wait()` cannot be called for an array when thread functions return optionals. Iterate over the arrays elements instead and handle each returned optional with `or`.',
if thread_ret_type.has_flag(.option) {
c.error('`.wait()` cannot be called for an array when thread functions return options. Iterate over the arrays elements instead and handle each returned option with `or`.',
node.pos)
} else if thread_ret_type.has_flag(.result) {
c.error('`.wait()` cannot be called for an array when thread functions return results. Iterate over the arrays elements instead and handle each returned result with `or`.',

View File

@ -17,7 +17,7 @@ fn (mut c Checker) for_c_stmt(node ast.ForCStmt) {
for right in node.inc.right {
if right is ast.CallExpr {
if right.or_block.stmts.len > 0 {
c.error('optionals are not allowed in `for statement increment` (yet)',
c.error('options are not allowed in `for statement increment` (yet)',
right.pos)
}
}
@ -98,8 +98,8 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
c.error('a struct must have a `next()` method to be an iterator', node.cond.pos())
return
}
if !next_fn.return_type.has_flag(.optional) {
c.error('iterator method `next()` must return an optional', node.cond.pos())
if !next_fn.return_type.has_flag(.option) {
c.error('iterator method `next()` must return an option', node.cond.pos())
}
return_sym := c.table.sym(next_fn.return_type)
if return_sym.kind == .multi_return {
@ -109,7 +109,7 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
if next_fn.params.len != 1 {
c.error('iterator method `next()` must have 0 parameters', node.cond.pos())
}
mut val_type := next_fn.return_type.clear_flag(.optional).clear_flag(.result)
mut val_type := next_fn.return_type.clear_flag(.option).clear_flag(.result)
if node.val_is_mut {
val_type = val_type.ref()
}

View File

@ -47,7 +47,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
// check condition type is boolean
c.expected_type = ast.bool_type
cond_typ := c.unwrap_generic(c.expr(branch.cond))
if (cond_typ.idx() != ast.bool_type_idx || cond_typ.has_flag(.optional)
if (cond_typ.idx() != ast.bool_type_idx || cond_typ.has_flag(.option)
|| cond_typ.has_flag(.result)) && !c.pref.translated && !c.file.is_translated {
c.error('non-bool type `${c.table.type_to_str(cond_typ)}` used as if condition',
branch.cond.pos())
@ -202,7 +202,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
node.is_expr = true
node.typ = c.expected_type
}
if c.expected_type.has_flag(.optional) || c.expected_type.has_flag(.result) {
if c.expected_type.has_flag(.option) || c.expected_type.has_flag(.result) {
if node.typ == ast.void_type {
node.is_expr = true
node.typ = c.expected_type

View File

@ -330,7 +330,7 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
left_name := c.table.type_to_str(unwrapped_left_type)
right_name := c.table.type_to_str(unwrapped_right_type)
c.error('mismatched types `${left_name}` and `${right_name}`', left_right_pos)
} else if promoted_type.has_flag(.optional) || promoted_type.has_flag(.result) {
} else if promoted_type.has_flag(.option) || promoted_type.has_flag(.result) {
s := c.table.type_to_str(promoted_type)
c.error('`${node.op}` cannot be used with `${s}`', node.pos)
} else if promoted_type.is_float() {
@ -429,9 +429,9 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
}
}
}
} else if left_type.has_flag(.optional) || right_type.has_flag(.optional) {
opt_comp_pos := if left_type.has_flag(.optional) { left_pos } else { right_pos }
c.error('unwrapped optional cannot be compared in an infix expression',
} else if left_type.has_flag(.option) || right_type.has_flag(.option) {
opt_comp_pos := if left_type.has_flag(.option) { left_pos } else { right_pos }
c.error('unwrapped option cannot be compared in an infix expression',
opt_comp_pos)
}
}
@ -652,11 +652,11 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
c.error('cannot use operator `${node.op}` with `${right_sym.name}`', node.pos)
}
// TODO move this to symmetric_check? Right now it would break `return 0` for `fn()?int `
left_is_optional := left_type.has_flag(.optional)
right_is_optional := right_type.has_flag(.optional)
if left_is_optional || right_is_optional {
opt_infix_pos := if left_is_optional { left_pos } else { right_pos }
c.error('unwrapped optional cannot be used in an infix expression', opt_infix_pos)
left_is_option := left_type.has_flag(.option)
right_is_option := right_type.has_flag(.option)
if left_is_option || right_is_option {
opt_infix_pos := if left_is_option { left_pos } else { right_pos }
c.error('unwrapped option cannot be used in an infix expression', opt_infix_pos)
}
left_is_result := left_type.has_flag(.result)

View File

@ -268,8 +268,8 @@ fn (mut c Checker) resolve_generic_interface(typ ast.Type, interface_type ast.Ty
}
} else if c.table.get_type_name(imethod.return_type) == gt_name {
mut ret_typ := method.return_type
if imethod.return_type.has_flag(.optional) {
ret_typ = ret_typ.clear_flag(.optional)
if imethod.return_type.has_flag(.option) {
ret_typ = ret_typ.clear_flag(.option)
} else if imethod.return_type.has_flag(.result) {
ret_typ = ret_typ.clear_flag(.result)
}

View File

@ -61,7 +61,7 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
expr_type := c.expr(stmt.expr)
stmt.typ = expr_type
if first_iteration {
if node.is_expr && (node.expected_type.has_flag(.optional)
if node.is_expr && (node.expected_type.has_flag(.option)
|| node.expected_type.has_flag(.result)
|| c.table.type_kind(node.expected_type) in [.sum_type, .multi_return]) {
c.check_match_branch_last_stmt(stmt, node.expected_type, expr_type)

View File

@ -14,7 +14,7 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
mut expected_type := c.unwrap_generic(c.expected_type)
if expected_type != 0 && c.table.sym(expected_type).kind == .alias {
unaliased_type := c.table.unaliased_type(expected_type)
if unaliased_type.has_flag(.optional) || unaliased_type.has_flag(.result) {
if unaliased_type.has_flag(.option) || unaliased_type.has_flag(.result) {
expected_type = unaliased_type
}
}
@ -32,7 +32,7 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
if node.exprs.len == 0 {
return
}
exp_is_optional := expected_type.has_flag(.optional)
exp_is_option := expected_type.has_flag(.option)
exp_is_result := expected_type.has_flag(.result)
mut expected_types := [expected_type]
if expected_type_sym.info is ast.MultiReturn {
@ -92,18 +92,18 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
}
}
}
// allow `none` & `error` return types for function that returns optional
// allow `none` & `error` return types for function that returns option
option_type_idx := c.table.type_idxs['_option']
result_type_idx := c.table.type_idxs['_result']
got_types_0_idx := got_types[0].idx()
if (exp_is_optional
if (exp_is_option
&& got_types_0_idx in [ast.none_type_idx, ast.error_type_idx, option_type_idx])
|| (exp_is_result && got_types_0_idx in [ast.error_type_idx, result_type_idx]) {
return
}
if expected_types.len > 0 && expected_types.len != got_types.len {
// `fn foo() !(int, string) { return Err{} }`
if (exp_is_optional || exp_is_result) && node.exprs.len == 1 {
if (exp_is_option || exp_is_result) && node.exprs.len == 1 {
got_typ := c.expr(node.exprs[0])
got_typ_sym := c.table.sym(got_typ)
if got_typ_sym.kind == .struct_ && c.type_implements(got_typ, ast.error_type, node.pos) {
@ -126,7 +126,7 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
}
for i, exp_type in expected_types {
got_typ := c.unwrap_generic(got_types[i])
if got_typ.has_flag(.optional) && (!exp_type.has_flag(.optional)
if got_typ.has_flag(.option) && (!exp_type.has_flag(.option)
|| c.table.type_to_str(got_typ) != c.table.type_to_str(exp_type)) {
pos := node.exprs[expr_idxs[i]].pos()
c.error('cannot use `${c.table.type_to_str(got_typ)}` as type `${c.table.type_to_str(exp_type)}` in return argument',
@ -228,7 +228,7 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
}
}
}
if exp_is_optional && node.exprs.len > 0 {
if exp_is_option && node.exprs.len > 0 {
expr0 := node.exprs[0]
if expr0 is ast.CallExpr {
if expr0.or_block.kind == .propagate_option && node.exprs.len == 1 {

View File

@ -7,7 +7,7 @@ import v.ast
import v.token
fn (mut c Checker) get_default_fmt(ftyp ast.Type, typ ast.Type) u8 {
if ftyp.has_flag(.optional) || ftyp.has_flag(.result) {
if ftyp.has_flag(.option) || ftyp.has_flag(.result) {
return `s`
} else if typ.is_float() {
return `g`
@ -32,7 +32,7 @@ fn (mut c Checker) get_default_fmt(ftyp ast.Type, typ ast.Type) u8 {
}
if ftyp in [ast.string_type, ast.bool_type]
|| sym.kind in [.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type, .interface_, .none_]
|| ftyp.has_flag(.optional) || ftyp.has_flag(.result) || sym.has_method('str') {
|| ftyp.has_flag(.option) || ftyp.has_flag(.result) || sym.has_method('str') {
return `s`
} else {
return `_`

View File

@ -72,7 +72,7 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
for i, field in node.fields {
if field.typ.has_flag(.result) {
c.error('struct field does not support storing result', field.optional_pos)
c.error('struct field does not support storing result', field.option_pos)
}
c.ensure_type_exists(field.typ, field.type_pos) or { return }
c.ensure_generic_type_specify_type_names(field.typ, field.type_pos) or { return }
@ -119,7 +119,7 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
if field.has_default_expr {
c.expected_type = field.typ
default_expr_type := c.expr(field.default_expr)
if !field.typ.has_flag(.optional) && !field.typ.has_flag(.result) {
if !field.typ.has_flag(.option) && !field.typ.has_flag(.result) {
c.check_expr_opt_call(field.default_expr, default_expr_type)
}
struct_sym.info.fields[i].default_expr_typ = default_expr_type
@ -463,7 +463,7 @@ fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
if expr_type == ast.void_type {
c.error('`${field.expr}` (no value) used as value', field.pos)
}
if !field_info.typ.has_flag(.optional) && !field.typ.has_flag(.result) {
if !field_info.typ.has_flag(.option) && !field.typ.has_flag(.result) {
expr_type = c.check_expr_opt_call(field.expr, expr_type)
}
expr_type_sym := c.table.sym(expr_type)

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/aliased_option_fn_call_err.vv:8:10: error: foo() returns an option, so it should have either an `or {}` block, or `?` at the end
6 |
7 | fn main() {
8 | println(foo())
| ~~~~~
9 | }

View File

@ -1,9 +1,9 @@
type OptStr = ?string
fn foo() OptStr{
fn foo() OptStr {
return 'abc'
}
fn main(){
fn main() {
println(foo())
}

View File

@ -1,6 +0,0 @@
vlib/v/checker/tests/aliased_optional_fn_call_err.vv:8:10: error: foo() returns an option, so it should have either an `or {}` block, or `?` at the end
6 |
7 | fn main(){
8 | println(foo())
| ~~~~~
9 | }

View File

@ -0,0 +1,21 @@
vlib/v/checker/tests/array_filter_map_option_function_err.vv:14:25: error: option needs to be unwrapped before using it in map/filter
12 | }
13 |
14 | arr_struct2 := arr.map(option_mapping_struct)
| ~~~~~~~~~~~~~~~~~~~~~
15 | println(arr_struct2)
16 |
vlib/v/checker/tests/array_filter_map_option_function_err.vv:17:18: error: option needs to be unwrapped before using it in map/filter
15 | println(arr_struct2)
16 |
17 | arr_int2 := arr.map(option_mapping_int)
| ~~~~~~~~~~~~~~~~~~~~~~~
18 | println(arr_int2)
19 |
vlib/v/checker/tests/array_filter_map_option_function_err.vv:20:20: error: option needs to be unwrapped before using it in map/filter
18 | println(arr_int2)
19 |
20 | arr_filter := arr.filter(option_mapping_int)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
21 | println(arr_filter)
22 | }

View File

@ -1,7 +1,7 @@
fn main() {
arr := [1, 2, 3, 4, 5]
optional_mapping_struct := fn (n int) ?MyStruct {
option_mapping_struct := fn (n int) ?MyStruct {
if n < 0 {
return none
} else {
@ -11,13 +11,13 @@ fn main() {
}
}
arr_struct2 := arr.map(optional_mapping_struct)
arr_struct2 := arr.map(option_mapping_struct)
println(arr_struct2)
arr_int2 := arr.map(optional_mapping_int)
arr_int2 := arr.map(option_mapping_int)
println(arr_int2)
arr_filter := arr.filter(optional_mapping_int)
arr_filter := arr.filter(option_mapping_int)
println(arr_filter)
}
@ -25,7 +25,7 @@ struct MyStruct {
my_field int
}
fn optional_mapping_int(n int) ?int {
fn option_mapping_int(n int) ?int {
if n < 0 {
return none
} else {

View File

@ -1,21 +0,0 @@
vlib/v/checker/tests/array_filter_map_optional_function_err.vv:14:25: error: optional needs to be unwrapped before using it in map/filter
12 | }
13 |
14 | arr_struct2 := arr.map(optional_mapping_struct)
| ~~~~~~~~~~~~~~~~~~~~~~~
15 | println(arr_struct2)
16 |
vlib/v/checker/tests/array_filter_map_optional_function_err.vv:17:18: error: optional needs to be unwrapped before using it in map/filter
15 | println(arr_struct2)
16 |
17 | arr_int2 := arr.map(optional_mapping_int)
| ~~~~~~~~~~~~~~~~~~~~~~~~~
18 | println(arr_int2)
19 |
vlib/v/checker/tests/array_filter_map_optional_function_err.vv:20:20: error: optional needs to be unwrapped before using it in map/filter
18 | println(arr_int2)
19 |
20 | arr_filter := arr.filter(optional_mapping_int)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 | println(arr_filter)
22 | }

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/assert_option_err.vv:4:9: error: assert can be used only with `bool` expressions, but found `void` instead
2 |
3 | fn main() {
4 | assert os.truncate('testfile.txt', 6666) or { panic(err) }
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 | }

View File

@ -0,0 +1,5 @@
import os
fn main() {
assert os.truncate('testfile.txt', 6666) or { panic(err) }
}

View File

@ -1,6 +0,0 @@
vlib/v/checker/tests/assert_optional_err.vv:4:9: error: assert can be used only with `bool` expressions, but found `void` instead
2 |
3 | fn main(){
4 | assert os.truncate("testfile.txt", 6666) or { panic(err) }
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 | }

View File

@ -1,5 +0,0 @@
import os
fn main(){
assert os.truncate("testfile.txt", 6666) or { panic(err) }
}

View File

@ -1,2 +1,2 @@
optional compitme define works
non optional comptime define works
comptime option define works
comptime non-option define works

View File

@ -1,7 +1,7 @@
vlib/v/checker/tests/custom_comptime_define_error.vv:6:13: error: undefined ident: `mysymbol`
4 | println('optional compitme define works')
5 | }
6 | $if mysymbol {
| ~~~~~~~~
7 | // this will produce a checker error when `-d mysymbol` is not given on the CLI
8 | println('non optional comptime define works')
vlib/v/checker/tests/custom_comptime_define_error.vv:6:6: error: undefined ident: `mysymbol`
4 | println('comptime option define works')
5 | }
6 | $if mysymbol {
| ~~~~~~~~
7 | // this will produce a checker error when `-d mysymbol` is not given on the CLI
8 | println('comptime non-option define works')

View File

@ -1,10 +1,10 @@
fn main() {
$if mysymbol? {
// this should not produce checker errors, but will print only with `-d mysymbol`
println('optional compitme define works')
}
$if mysymbol {
// this will produce a checker error when `-d mysymbol` is not given on the CLI
println('non optional comptime define works')
}
$if mysymbol ? {
// this should not produce checker errors, but will print only with `-d mysymbol`
println('comptime option define works')
}
$if mysymbol {
// this will produce a checker error when `-d mysymbol` is not given on the CLI
println('comptime non-option define works')
}
}

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/defer_optional.vv:5:3: error: opt() returns an option, so it should have an `or {}` block at the end
vlib/v/checker/tests/defer_option.vv:5:3: error: opt() returns an option, so it should have an `or {}` block at the end
3 | fn thing() ?string {
4 | defer {
5 | opt()

View File

@ -1,7 +1,7 @@
vlib/v/checker/tests/expression_should_return_an_option.vv:28:10: error: expression should either return an option or a result
26 | }
27 | // should be an checker error:
28 | if x := return_string() {
vlib/v/checker/tests/expression_should_return_an_option.vv:26:10: error: expression should either return an option or a result
24 | return_option(true) or { println(err) }
25 | // should be an checker error:
26 | if x := return_string() {
| ~~~~~~~~~~~~~~~
29 | println('x: $x')
30 | }
27 | println('x: ${x}')
28 | }

View File

@ -1,4 +1,4 @@
fn return_optional(fail bool) ?string {
fn return_option(fail bool) ?string {
if fail {
return error('nope')
}
@ -11,21 +11,19 @@ fn return_string() string {
fn main() {
// works
if r := return_optional(false) {
if r := return_option(false) {
println(r)
}
// works
if r := return_optional(false) {
if r := return_option(false) {
println(r)
} else {
println(err)
}
// works
return_optional(true) or {
println(err)
}
return_option(true) or { println(err) }
// should be an checker error:
if x := return_string() {
println('x: $x')
println('x: ${x}')
}
}

View File

@ -0,0 +1,5 @@
vlib/v/checker/tests/fn_arg_of_option_err.vv:1:17: error: option or result type argument is not supported currently
1 | fn option_arg(x ?int) {
| ~~~~
2 | println('int type: ${x}')
3 | }

View File

@ -0,0 +1,7 @@
fn option_arg(x ?int) {
println('int type: ${x}')
}
fn main() {
option_arg(1)
}

View File

@ -1,5 +0,0 @@
vlib/v/checker/tests/fn_arg_of_optional_err.vv:1:19: error: optional or result type argument is not supported currently
1 | fn optional_arg(x ?int) {
| ~~~~
2 | println('int type: $x')
3 | }

View File

@ -1,7 +0,0 @@
fn optional_arg(x ?int) {
println('int type: $x')
}
fn main() {
optional_arg(1)
}

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/fn_check_for_matching_option_result_in_fields.vv:7:3: error: cannot assign to field `f`: expected `fn (voidptr)`, not `fn (voidptr) ?`
5 | fn main() {
6 | a := Abc{
7 | f: fn (data voidptr) ? {}
| ~~~~~~~~~~~~~~~~~~~~~~~~~
8 | }
9 | println(a)

View File

@ -1,7 +0,0 @@
vlib/v/checker/tests/fn_check_for_matching_optional_result_in_fields.vv:7:3: error: cannot assign to field `f`: expected `fn (voidptr)`, not `fn (voidptr) ?`
5 | fn main() {
6 | a := Abc{
7 | f: fn (data voidptr) ? {}
| ~~~~~~~~~~~~~~~~~~~~~~~~~
8 | }
9 | println(a)

View File

@ -1,7 +1,7 @@
vlib/v/checker/tests/fn_return_or_err.vv:6:17: error: unexpected `or` block, the function `pop` does neither return an optional nor a result
4 |
vlib/v/checker/tests/fn_return_or_err.vv:6:17: error: unexpected `or` block, the function `pop` does not return an option or a result
4 |
5 | pub fn next(mut v []Typ) Typ {
6 | return v.pop() or { Typ{} }
| ~~~~~~~~~~~~
7 | }
8 |
8 |

View File

@ -1,7 +1,7 @@
vlib/v/checker/tests/for_c_stmt_with_optional_call.vv:15:31: error: optionals are not allowed in `for statement increment` (yet)
vlib/v/checker/tests/for_c_stmt_with_option_call.vv:15:31: error: options are not allowed in `for statement increment` (yet)
13 | for t := 0; t < tests; t++ {
14 | mut v := []bool{len: nmax, init: false}
15 | for x := 0; !v[x]; x = rand.intn(n) or { 0 } {
| ~~~~~~~
16 | v[x] = true
17 | sum++
17 | sum++

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/for_in_index_option.vv:4:17: error: for in: cannot index `![]string`
2 |
3 | fn main() {
4 | for file in os.ls('.') {
| ~~~~~~~
5 | println(file)
6 | }

View File

@ -0,0 +1,7 @@
import os
fn main() {
for file in os.ls('.') {
println(file)
}
}

View File

@ -1,7 +0,0 @@
vlib/v/checker/tests/for_in_index_optional.vv:3:18: error: for in: cannot index `![]string`
1 | import os
2 | fn main() {
3 | for file in os.ls('.') {
| ~~~~~~~
4 | println(file)
5 | }

View File

@ -1,6 +0,0 @@
import os
fn main() {
for file in os.ls('.') {
println(file)
}
}

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/go_append_option_to_threads_err.vv:5:15: error: cannot append `thread !` to `[]thread`
3 | fn main() {
4 | mut ths := []thread{}
5 | ths << spawn foo()
| ~~~~~
6 | ths.wait()
7 | }

View File

@ -2,6 +2,6 @@ fn foo() ! {}
fn main() {
mut ths := []thread{}
ths << go foo()
ths << spawn foo()
ths.wait()
}

View File

@ -1,7 +0,0 @@
vlib/v/checker/tests/go_append_optional_to_threads_err.vv:5:12: error: cannot append `thread !` to `[]thread`
3 | fn main() {
4 | mut ths := []thread{}
5 | ths << go foo()
| ~~~~~
6 | ths.wait()
7 | }

View File

@ -1,32 +1,32 @@
vlib/v/checker/tests/go_wait_or.vv:11:16: error: unexpected `?`, the function `wait` does neither return an optional nor a result
vlib/v/checker/tests/go_wait_or.vv:11:16: error: unexpected `?`, the function `wait` does not return an option or a result
9 | go d(1)
10 | ]
11 | r := tg.wait()?
| ^
12 | println(r)
13 | s := tg[0].wait() or { panic('problem') }
vlib/v/checker/tests/go_wait_or.vv:13:20: error: unexpected `or` block, the function `wait` does neither return an optional nor a result
vlib/v/checker/tests/go_wait_or.vv:13:20: error: unexpected `or` block, the function `wait` does not return an option or a result
11 | r := tg.wait()?
12 | println(r)
13 | s := tg[0].wait() or { panic('problem') }
| ~~~~~~~~~~~~~~~~~~~~~~~
14 | println(s)
15 | tg2 := [
vlib/v/checker/tests/go_wait_or.vv:19:13: error: unexpected `or` block, the function `wait` does neither return an optional nor a result
vlib/v/checker/tests/go_wait_or.vv:19:13: error: unexpected `or` block, the function `wait` does not return an option or a result
17 | go e(1)
18 | ]
19 | tg2.wait() or { panic('problem') }
| ~~~~~~~~~~~~~~~~~~~~~~~
20 | tg2[0].wait()?
21 | tg3 := [
vlib/v/checker/tests/go_wait_or.vv:20:15: error: unexpected `?`, the function `wait` does neither return an optional nor a result
vlib/v/checker/tests/go_wait_or.vv:20:15: error: unexpected `?`, the function `wait` does not return an option or a result
18 | ]
19 | tg2.wait() or { panic('problem') }
20 | tg2[0].wait()?
| ^
21 | tg3 := [
22 | go f(0)
vlib/v/checker/tests/go_wait_or.vv:25:6: error: `.wait()` cannot be called for an array when thread functions return optionals. Iterate over the arrays elements instead and handle each returned optional with `or`.
vlib/v/checker/tests/go_wait_or.vv:25:6: error: `.wait()` cannot be called for an array when thread functions return options. Iterate over the arrays elements instead and handle each returned option with `or`.
23 | go f(1)
24 | ]
25 | tg3.wait() or { panic('problem') }
@ -47,7 +47,7 @@ vlib/v/checker/tests/go_wait_or.vv:31:15: error: wait() returns an option, so it
| ~~~~~~
32 | println(a)
33 | }
vlib/v/checker/tests/go_wait_or.vv:38:6: error: `.wait()` cannot be called for an array when thread functions return optionals. Iterate over the arrays elements instead and handle each returned optional with `or`.
vlib/v/checker/tests/go_wait_or.vv:38:6: error: `.wait()` cannot be called for an array when thread functions return options. Iterate over the arrays elements instead and handle each returned option with `or`.
36 | go g(1)
37 | ]
38 | tg4.wait()
@ -61,9 +61,9 @@ vlib/v/checker/tests/go_wait_or.vv:39:9: error: wait() returns an option, so it
| ~~~~~~
40 | go g(3) or { panic('problem') }
41 | }
vlib/v/checker/tests/go_wait_or.vv:40:10: error: optional handling cannot be done in `go` call. Do it when calling `.wait()`
vlib/v/checker/tests/go_wait_or.vv:40:10: error: option handling cannot be done in `go` call. Do it when calling `.wait()`
38 | tg4.wait()
39 | tg4[0].wait()
40 | go g(3) or { panic('problem') }
| ~~~~~~~~~~~~~~~~~~~~~~~
41 | }
41 | }

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/if_expr_option_err.vv:6:5: error: non-bool type `?bool` used as if condition
4 |
5 | fn main() {
6 | if get_bool() {
| ~~~~~~~~~~
7 | println('Using plain lists')
8 | }

View File

@ -4,6 +4,6 @@ fn get_bool() ?bool {
fn main() {
if get_bool() {
println("Using plain lists")
println('Using plain lists')
}
}

View File

@ -1,7 +0,0 @@
vlib/v/checker/tests/if_expr_optional_err.vv:6:5: error: non-bool type `?bool` used as if condition
4 |
5 | fn main() {
6 | if get_bool() {
| ~~~~~~~~~~
7 | println("Using plain lists")
8 | }

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/index_of_option_err.vv:6:7: error: type `?[]int` is an option, it does not support indexing
4 |
5 | fn main() {
6 | a := abc()[0] or { 5 }
| ~~~~~
7 | dump(a)
8 | }

View File

@ -1,7 +0,0 @@
vlib/v/checker/tests/index_of_optional_err.vv:6:7: error: type `?[]int` is optional, it does not support indexing
4 |
5 | fn main() {
6 | a := abc()[0] or { 5 }
| ~~~~~
7 | dump(a)
8 | }

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/infix_compare_option_err.vv:6:5: error: unwrapped option cannot be compared in an infix expression
4 |
5 | fn main() {
6 | if foo() > foo() {
| ~~~~~
7 | }
8 | }

View File

@ -0,0 +1,8 @@
fn foo() ?int {
return 0
}
fn main() {
if foo() > foo() {
}
}

View File

@ -1,6 +0,0 @@
vlib/v/checker/tests/infix_compare_optional_err.vv:6:5: error: unwrapped optional cannot be compared in an infix expression
4 |
5 | fn main(){
6 | if foo() > foo() {}
| ~~~~~
7 | }

View File

@ -1,7 +0,0 @@
fn foo() ?int{
return 0
}
fn main(){
if foo() > foo() {}
}

View File

@ -17,17 +17,17 @@ vlib/v/checker/tests/infix_err.vv:9:9: error: `+` cannot be used with `?string`
8 | _ = f() + ''
9 | _ = f() + f()
| ^
10 |
10 |
11 | _ = 4 + g()
vlib/v/checker/tests/infix_err.vv:11:7: error: `+` cannot be used with `?int`
9 | _ = f() + f()
10 |
10 |
11 | _ = 4 + g()
| ^
12 | _ = int(0) + g() // FIXME not detected
13 | _ = g() + int(3)
vlib/v/checker/tests/infix_err.vv:12:14: error: unwrapped optional cannot be used in an infix expression
10 |
vlib/v/checker/tests/infix_err.vv:12:14: error: unwrapped option cannot be used in an infix expression
10 |
11 | _ = 4 + g()
12 | _ = int(0) + g() // FIXME not detected
| ~~~
@ -45,10 +45,10 @@ vlib/v/checker/tests/infix_err.vv:14:9: error: `+` cannot be used with `?int`
13 | _ = g() + int(3)
14 | _ = g() + 3
| ^
15 |
15 |
16 | // binary operands
vlib/v/checker/tests/infix_err.vv:17:5: error: left operand for `&&` is not a boolean
15 |
15 |
16 | // binary operands
17 | _ = 1 && 2
| ^
@ -59,10 +59,10 @@ vlib/v/checker/tests/infix_err.vv:18:13: error: right operand for `||` is not a
17 | _ = 1 && 2
18 | _ = true || 2
| ^
19 |
19 |
20 | // boolean expressions
vlib/v/checker/tests/infix_err.vv:21:22: error: ambiguous boolean expression. use `()` to ensure correct order of operations
19 |
19 |
20 | // boolean expressions
21 | _ = 1 == 1 && 2 == 2 || 3 == 3
| ~~
@ -78,4 +78,4 @@ vlib/v/checker/tests/infix_err.vv:24:2: error: ambiguous boolean expression. use
22 | _ = 1 == 1
23 | && 2 == 2 || 3 == 3
24 | && 4 == 4
| ~~
| ~~

View File

@ -0,0 +1,13 @@
vlib/v/checker/tests/option_fields_addr_err.vv:9:10: error: cannot take the address of an option field
7 | fn main() {
8 | x := Wrapper{}
9 | if _ := &x.value {
| ~~~~~~~~
10 | }
11 |
vlib/v/checker/tests/option_fields_addr_err.vv:12:7: error: cannot take the address of an option field
10 | }
11 |
12 | _ := &x.value
| ~~~~~~~~
13 | }

View File

@ -0,0 +1,168 @@
vlib/v/checker/tests/option_fn_err.vv:12:16: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
10 |
11 | const (
12 | const_value = bar(0)
| ~~~~~~
13 | )
14 |
vlib/v/checker/tests/option_fn_err.vv:18:15: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
16 | f fn (int)
17 | mut:
18 | value int = bar(0)
| ~~~~~~
19 | opt ?int = bar(0)
20 | }
vlib/v/checker/tests/option_fn_err.vv:32:2: error: foo() returns an option, so it should have either an `or {}` block, or `?` at the end
30 | fn main() {
31 | // call fn
32 | foo()
| ~~~~~
33 | _ := bar(0)
34 | println(twice(bar(0)))
vlib/v/checker/tests/option_fn_err.vv:33:7: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
31 | // call fn
32 | foo()
33 | _ := bar(0)
| ~~~~~~
34 | println(twice(bar(0)))
35 |
vlib/v/checker/tests/option_fn_err.vv:34:16: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
32 | foo()
33 | _ := bar(0)
34 | println(twice(bar(0)))
| ~~~~~~
35 |
36 | // anon fn
vlib/v/checker/tests/option_fn_err.vv:37:16: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
35 |
36 | // anon fn
37 | fn (_ int) {}(bar(0))
| ~~~~~~
38 |
39 | // assert
vlib/v/checker/tests/option_fn_err.vv:40:9: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
38 |
39 | // assert
40 | assert bar(true)
| ~~~~~~~~~
41 |
42 | // struct
vlib/v/checker/tests/option_fn_err.vv:45:10: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
43 | mut v := Data{
44 | f: fn (_ int) {}
45 | value: bar(0)
| ~~~~~~
46 | opt: bar(0)
47 | }
vlib/v/checker/tests/option_fn_err.vv:48:8: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
46 | opt: bar(0)
47 | }
48 | v.add(bar(0)) // call method
| ~~~~~~
49 | v.f(bar(0)) // call fn field
50 |
vlib/v/checker/tests/option_fn_err.vv:49:6: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
47 | }
48 | v.add(bar(0)) // call method
49 | v.f(bar(0)) // call fn field
| ~~~~~~
50 |
51 | // array
vlib/v/checker/tests/option_fn_err.vv:53:9: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
51 | // array
52 | mut arr := [1, 2]
53 | arr << bar(0)
| ~~~~~~
54 | // init
55 | _ := [bar(0)]
vlib/v/checker/tests/option_fn_err.vv:55:8: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
53 | arr << bar(0)
54 | // init
55 | _ := [bar(0)]
| ~~~~~~
56 | _ := []int{len: 1, init: bar(0)}
57 | _ := [bar(0)]!
vlib/v/checker/tests/option_fn_err.vv:56:27: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
54 | // init
55 | _ := [bar(0)]
56 | _ := []int{len: 1, init: bar(0)}
| ~~~~~~
57 | _ := [bar(0)]!
58 | _ := [1]int{init: bar(0)}
vlib/v/checker/tests/option_fn_err.vv:57:8: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
55 | _ := [bar(0)]
56 | _ := []int{len: 1, init: bar(0)}
57 | _ := [bar(0)]!
| ~~~~~~
58 | _ := [1]int{init: bar(0)}
59 | // index
vlib/v/checker/tests/option_fn_err.vv:60:13: error: cannot use option or result as index (array type `[]int`)
58 | _ := [1]int{init: bar(0)}
59 | // index
60 | println(arr[bar(0)])
| ~~~~~~~~
61 | // array builtin methods
62 | arr.insert(0, bar(0))
vlib/v/checker/tests/option_fn_err.vv:62:16: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
60 | println(arr[bar(0)])
61 | // array builtin methods
62 | arr.insert(0, bar(0))
| ~~~~~~
63 | arr.prepend(bar(0))
64 | arr.contains(bar(0))
vlib/v/checker/tests/option_fn_err.vv:63:14: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
61 | // array builtin methods
62 | arr.insert(0, bar(0))
63 | arr.prepend(bar(0))
| ~~~~~~
64 | arr.contains(bar(0))
65 | arr.index(bar(0))
vlib/v/checker/tests/option_fn_err.vv:64:15: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
62 | arr.insert(0, bar(0))
63 | arr.prepend(bar(0))
64 | arr.contains(bar(0))
| ~~~~~~
65 | arr.index(bar(0))
66 | println(arr.map(bar(0)))
vlib/v/checker/tests/option_fn_err.vv:65:12: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
63 | arr.prepend(bar(0))
64 | arr.contains(bar(0))
65 | arr.index(bar(0))
| ~~~~~~
66 | println(arr.map(bar(0)))
67 | println(arr.filter(bar(true)))
vlib/v/checker/tests/option_fn_err.vv:66:18: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
64 | arr.contains(bar(0))
65 | arr.index(bar(0))
66 | println(arr.map(bar(0)))
| ~~~~~~
67 | println(arr.filter(bar(true)))
68 | println(arr.any(bar(true)))
vlib/v/checker/tests/option_fn_err.vv:67:21: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
65 | arr.index(bar(0))
66 | println(arr.map(bar(0)))
67 | println(arr.filter(bar(true)))
| ~~~~~~~~~
68 | println(arr.any(bar(true)))
69 | println(arr.all(bar(true)))
vlib/v/checker/tests/option_fn_err.vv:68:18: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
66 | println(arr.map(bar(0)))
67 | println(arr.filter(bar(true)))
68 | println(arr.any(bar(true)))
| ~~~~~~~~~
69 | println(arr.all(bar(true)))
70 |
vlib/v/checker/tests/option_fn_err.vv:69:18: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
67 | println(arr.filter(bar(true)))
68 | println(arr.any(bar(true)))
69 | println(arr.all(bar(true)))
| ~~~~~~~~~
70 |
71 | match bar(0) {
vlib/v/checker/tests/option_fn_err.vv:71:8: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
69 | println(arr.all(bar(true)))
70 |
71 | match bar(0) {
| ~~~~~~
72 | 0 {}
73 | else {}

View File

@ -1,5 +1,4 @@
// use optional without ? or an or block in places where it is not allowed
// use option without ? or an or block in places where it is not allowed
fn foo() ? {
println('foo is called')
@ -16,7 +15,7 @@ const (
struct Data {
f fn (int)
mut:
value int = bar(0)
value int = bar(0)
opt ?int = bar(0)
}
@ -42,9 +41,9 @@ fn main() {
// struct
mut v := Data{
f: fn (_ int) {},
value: bar(0),
opt: bar(0),
f: fn (_ int) {}
value: bar(0)
opt: bar(0)
}
v.add(bar(0)) // call method
v.f(bar(0)) // call fn field
@ -70,7 +69,7 @@ fn main() {
println(arr.all(bar(true)))
match bar(0) {
0 { }
else { }
0 {}
else {}
}
}

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/option_in_dump_err.vv:10:7: error: create() returns an option, so it should have either an `or {}` block, or `?` at the end
8 |
9 | fn main() {
10 | dump(create())
| ~~~~~~~~
11 | }

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/option_in_println_mismatch.vv:6:23: error: wrong return type `string` in the `or {}` block, expected `int`
4 |
5 | fn main() {
6 | println(funcy() or { '' })
| ~~
7 | }

View File

@ -1,6 +1,6 @@
vlib/v/checker/tests/optional_interface_mismatch.vv:11:9: error: mismatched types `?MObject` and `string`
vlib/v/checker/tests/option_interface_mismatch.vv:11:9: error: mismatched types `?MObject` and `string`
9 |
10 | fn give_string(line string) ?MObject {
11 | return if true { 'string' } else { 'string' }
| ~~
12 | }
12 | }

View File

@ -0,0 +1,13 @@
vlib/v/checker/tests/option_or_block_mismatch.vv:10:18: error: wrong return type `Bar` in the `or {}` block, expected `&Bar`
8 |
9 | fn main() {
10 | x := foo() or { Bar{} }
| ~~~~~
11 | println(x)
12 |
vlib/v/checker/tests/option_or_block_mismatch.vv:13:13: error: the default expression type in the `or` block should be `&Bar`, instead you gave a value of type `Bar`
11 | println(x)
12 |
13 | foo() or { Bar{} }
| ~~~~~
14 | }

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/option_or_block_none_err.vv:19:32: error: wrong return type `none` in the `or {}` block, expected `Animal`
17 |
18 | fn main() {
19 | mut dog := new_animal(9) or { none }
| ~~~~
20 |
21 | println(dog)

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/option_or_block_returns_value_of_incompatible_type.vv:13:3: error: the default expression type in the `or` block should be `string`, instead you gave a value of type `int literal`
11 | // must be of the same type of the return
12 | // type of the `test_option` function
13 | 123
| ~~~
14 | // 'I break things'
15 | }

View File

@ -0,0 +1,16 @@
fn test_option(fail bool) ?string {
if fail {
return error('false')
}
return 'fff'
}
fn main() {
// a := test_option(false) or { println(err) }
test_option(true) or {
// must be of the same type of the return
// type of the `test_option` function
123
// 'I break things'
}
}

View File

@ -0,0 +1,28 @@
vlib/v/checker/tests/option_propagate_nested.vv:10:18: error: to propagate the option call, `xx_prop` must return an option
8 |
9 | fn xx_prop() string {
10 | s := ret(raise()?)
| ^
11 | return s
12 | }
Details: vlib/v/checker/tests/option_propagate_nested.vv:9:14: details: prepend ? before the declaration of the return type of `xx_prop`
7 | }
8 |
9 | fn xx_prop() string {
| ~~~~~~
10 | s := ret(raise()?)
11 | return s
vlib/v/checker/tests/option_propagate_nested.vv:28:21: error: to propagate the option call, `aa_propagate` must return an option
26 |
27 | fn (mut s St) aa_propagate() {
28 | f := retf(s.raise()?)
| ^
29 | s.z = 7.5
30 | println(f)
Details: vlib/v/checker/tests/option_propagate_nested.vv:27:30: details: prepend ? before the declaration of the return type of `aa_propagate`
25 | }
26 |
27 | fn (mut s St) aa_propagate() {
| ^
28 | f := retf(s.raise()?)
29 | s.z = 7.5

View File

@ -1,6 +1,6 @@
vlib/v/checker/tests/optional_type_call_err.vv:4:5: error: result type cannot be called directly
vlib/v/checker/tests/option_type_call_err.vv:4:5: error: result type cannot be called directly
2 |
3 | fn main() {
4 | os.ls('.').filter(it.ends_with('.v')) or { return }
| ~~~~~~~
5 | }
5 | }

View File

@ -0,0 +1,5 @@
vlib/v/checker/tests/option_variable_err.vv:2:7: error: casting to option type is forbidden
1 | fn main() {
2 | _ := ?bool(false)
| ~~~~~~~~~~~~
3 | }

View File

@ -1,13 +0,0 @@
vlib/v/checker/tests/optional_fields_addr_err.vv:9:10: error: cannot take the address of an optional field
7 | fn main() {
8 | x := Wrapper{}
9 | if _ := &x.value {
| ~~~~~~~~
10 | }
11 |
vlib/v/checker/tests/optional_fields_addr_err.vv:12:7: error: cannot take the address of an optional field
10 | }
11 |
12 | _ := &x.value
| ~~~~~~~~
13 | }

Some files were not shown because too many files have changed in this diff Show More