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:
parent
241109516f
commit
90941b3b1f
12
CHANGELOG.md
12
CHANGELOG.md
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
22
doc/docs.md
22
doc/docs.md
@ -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{}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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__
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
@ -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'
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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_', ', ', '_', ']', ''])
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -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
|
||||
|
@ -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`.',
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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 `_`
|
||||
|
@ -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)
|
||||
|
6
vlib/v/checker/tests/aliased_option_fn_call_err.out
Normal file
6
vlib/v/checker/tests/aliased_option_fn_call_err.out
Normal 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 | }
|
@ -1,9 +1,9 @@
|
||||
type OptStr = ?string
|
||||
|
||||
fn foo() OptStr{
|
||||
fn foo() OptStr {
|
||||
return 'abc'
|
||||
}
|
||||
|
||||
fn main(){
|
||||
fn main() {
|
||||
println(foo())
|
||||
}
|
@ -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 | }
|
@ -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 | }
|
@ -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 {
|
@ -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 | }
|
6
vlib/v/checker/tests/assert_option_err.out
Normal file
6
vlib/v/checker/tests/assert_option_err.out
Normal 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 | }
|
5
vlib/v/checker/tests/assert_option_err.vv
Normal file
5
vlib/v/checker/tests/assert_option_err.vv
Normal file
@ -0,0 +1,5 @@
|
||||
import os
|
||||
|
||||
fn main() {
|
||||
assert os.truncate('testfile.txt', 6666) or { panic(err) }
|
||||
}
|
@ -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 | }
|
@ -1,5 +0,0 @@
|
||||
import os
|
||||
|
||||
fn main(){
|
||||
assert os.truncate("testfile.txt", 6666) or { panic(err) }
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
optional compitme define works
|
||||
non optional comptime define works
|
||||
comptime option define works
|
||||
comptime non-option define works
|
@ -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')
|
@ -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')
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
@ -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 | }
|
@ -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}')
|
||||
}
|
||||
}
|
||||
|
5
vlib/v/checker/tests/fn_arg_of_option_err.out
Normal file
5
vlib/v/checker/tests/fn_arg_of_option_err.out
Normal 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 | }
|
7
vlib/v/checker/tests/fn_arg_of_option_err.vv
Normal file
7
vlib/v/checker/tests/fn_arg_of_option_err.vv
Normal file
@ -0,0 +1,7 @@
|
||||
fn option_arg(x ?int) {
|
||||
println('int type: ${x}')
|
||||
}
|
||||
|
||||
fn main() {
|
||||
option_arg(1)
|
||||
}
|
@ -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 | }
|
@ -1,7 +0,0 @@
|
||||
fn optional_arg(x ?int) {
|
||||
println('int type: $x')
|
||||
}
|
||||
|
||||
fn main() {
|
||||
optional_arg(1)
|
||||
}
|
@ -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)
|
@ -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)
|
@ -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 |
|
@ -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++
|
7
vlib/v/checker/tests/for_in_index_option.out
Normal file
7
vlib/v/checker/tests/for_in_index_option.out
Normal 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 | }
|
7
vlib/v/checker/tests/for_in_index_option.vv
Normal file
7
vlib/v/checker/tests/for_in_index_option.vv
Normal file
@ -0,0 +1,7 @@
|
||||
import os
|
||||
|
||||
fn main() {
|
||||
for file in os.ls('.') {
|
||||
println(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 | }
|
@ -1,6 +0,0 @@
|
||||
import os
|
||||
fn main() {
|
||||
for file in os.ls('.') {
|
||||
println(file)
|
||||
}
|
||||
}
|
7
vlib/v/checker/tests/go_append_option_to_threads_err.out
Normal file
7
vlib/v/checker/tests/go_append_option_to_threads_err.out
Normal 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 | }
|
@ -2,6 +2,6 @@ fn foo() ! {}
|
||||
|
||||
fn main() {
|
||||
mut ths := []thread{}
|
||||
ths << go foo()
|
||||
ths << spawn foo()
|
||||
ths.wait()
|
||||
}
|
@ -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 | }
|
@ -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 | }
|
7
vlib/v/checker/tests/if_expr_option_err.out
Normal file
7
vlib/v/checker/tests/if_expr_option_err.out
Normal 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 | }
|
@ -4,6 +4,6 @@ fn get_bool() ?bool {
|
||||
|
||||
fn main() {
|
||||
if get_bool() {
|
||||
println("Using plain lists")
|
||||
println('Using plain lists')
|
||||
}
|
||||
}
|
@ -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 | }
|
7
vlib/v/checker/tests/index_of_option_err.out
Normal file
7
vlib/v/checker/tests/index_of_option_err.out
Normal 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 | }
|
@ -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 | }
|
7
vlib/v/checker/tests/infix_compare_option_err.out
Normal file
7
vlib/v/checker/tests/infix_compare_option_err.out
Normal 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 | }
|
8
vlib/v/checker/tests/infix_compare_option_err.vv
Normal file
8
vlib/v/checker/tests/infix_compare_option_err.vv
Normal file
@ -0,0 +1,8 @@
|
||||
fn foo() ?int {
|
||||
return 0
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if foo() > foo() {
|
||||
}
|
||||
}
|
@ -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 | }
|
@ -1,7 +0,0 @@
|
||||
fn foo() ?int{
|
||||
return 0
|
||||
}
|
||||
|
||||
fn main(){
|
||||
if foo() > foo() {}
|
||||
}
|
@ -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
|
||||
| ~~
|
||||
| ~~
|
13
vlib/v/checker/tests/option_fields_addr_err.out
Normal file
13
vlib/v/checker/tests/option_fields_addr_err.out
Normal 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 | }
|
168
vlib/v/checker/tests/option_fn_err.out
Normal file
168
vlib/v/checker/tests/option_fn_err.out
Normal 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 {}
|
@ -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 {}
|
||||
}
|
||||
}
|
6
vlib/v/checker/tests/option_in_dump_err.out
Normal file
6
vlib/v/checker/tests/option_in_dump_err.out
Normal 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 | }
|
6
vlib/v/checker/tests/option_in_println_mismatch.out
Normal file
6
vlib/v/checker/tests/option_in_println_mismatch.out
Normal 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 | }
|
@ -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 | }
|
13
vlib/v/checker/tests/option_or_block_mismatch.out
Normal file
13
vlib/v/checker/tests/option_or_block_mismatch.out
Normal 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 | }
|
7
vlib/v/checker/tests/option_or_block_none_err.out
Normal file
7
vlib/v/checker/tests/option_or_block_none_err.out
Normal 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)
|
@ -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 | }
|
@ -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'
|
||||
}
|
||||
}
|
28
vlib/v/checker/tests/option_propagate_nested.out
Normal file
28
vlib/v/checker/tests/option_propagate_nested.out
Normal 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
|
@ -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 | }
|
5
vlib/v/checker/tests/option_variable_err.out
Normal file
5
vlib/v/checker/tests/option_variable_err.out
Normal 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 | }
|
@ -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
Loading…
Reference in New Issue
Block a user