diff --git a/cmd/tools/modules/scripting/scripting.v b/cmd/tools/modules/scripting/scripting.v index 017a4eea54..4d07c56928 100644 --- a/cmd/tools/modules/scripting/scripting.v +++ b/cmd/tools/modules/scripting/scripting.v @@ -95,7 +95,7 @@ pub fn chdir(path string) { } } -pub fn mkdir(path string) ? { +pub fn mkdir(path string) ! { verbose_trace_strong(modfn(@MOD, @FN), 'mkdir ${path}') os.mkdir(path) or { verbose_trace(modfn(@MOD, @FN), '## failed.') @@ -103,7 +103,7 @@ pub fn mkdir(path string) ? { } } -pub fn mkdir_all(path string) ? { +pub fn mkdir_all(path string) ! { verbose_trace_strong(modfn(@MOD, @FN), 'mkdir -p ${path}') os.mkdir_all(path) or { verbose_trace(modfn(@MOD, @FN), '## failed.') @@ -123,7 +123,7 @@ pub fn rmrf(path string) { } // execute a command, and return a result, or an error, if it failed in any way. -pub fn exec(cmd string) ?os.Result { +pub fn exec(cmd string) !os.Result { verbose_trace_strong(modfn(@MOD, @FN), cmd) x := os.execute(cmd) if x.exit_code != 0 { diff --git a/cmd/tools/modules/testing/common.v b/cmd/tools/modules/testing/common.v index bfbbafd971..d053eb08e7 100644 --- a/cmd/tools/modules/testing/common.v +++ b/cmd/tools/modules/testing/common.v @@ -721,7 +721,7 @@ pub fn get_test_details(file string) TestDetails { return res } -pub fn find_started_process(pname string) ?string { +pub fn find_started_process(pname string) !string { for line in testing.all_processes { if line.contains(pname) { return line diff --git a/cmd/tools/vbump.v b/cmd/tools/vbump.v index c47dc704ae..952441e29c 100644 --- a/cmd/tools/vbump.v +++ b/cmd/tools/vbump.v @@ -169,7 +169,7 @@ Try ${tool_name} -h for more help...') } } -fn validate_options(options Options) ? { +fn validate_options(options Options) ! { if options.patch && options.major { return error('Cannot specify both --patch and --major.') } diff --git a/cmd/tools/vfmt.v b/cmd/tools/vfmt.v index f2564208e3..73104ea5f5 100644 --- a/cmd/tools/vfmt.v +++ b/cmd/tools/vfmt.v @@ -213,7 +213,7 @@ fn (mut foptions FormatOptions) find_diff_cmd() string { return foptions.diff_cmd } -fn (mut foptions FormatOptions) post_process_file(file string, formatted_file_path string) ? { +fn (mut foptions FormatOptions) post_process_file(file string, formatted_file_path string) ! { if formatted_file_path.len == 0 { return } @@ -307,7 +307,7 @@ fn file_to_mod_name_and_is_module_file(file string) (string, bool) { return mod_name, is_module_file } -fn read_source_lines(file string) ?[]string { +fn read_source_lines(file string) ![]string { source_lines := os.read_lines(file) or { return error('can not read ${file}') } return source_lines } diff --git a/cmd/tools/vpm.v b/cmd/tools/vpm.v index 839e8b92cc..6523b27c4a 100644 --- a/cmd/tools/vpm.v +++ b/cmd/tools/vpm.v @@ -414,7 +414,7 @@ fn vpm_update(m []string) { } } -fn get_outdated() ?[]string { +fn get_outdated() ![]string { module_names := get_installed_modules() mut outdated := []string{} for name in module_names { @@ -720,7 +720,7 @@ fn verbose_println(s string) { } } -fn get_mod_by_url(name string) ?Mod { +fn get_mod_by_url(name string) !Mod { if purl := urllib.parse(name) { verbose_println('purl: ${purl}') mod := Mod{ @@ -733,7 +733,7 @@ fn get_mod_by_url(name string) ?Mod { return error('invalid url: ${name}') } -fn get_module_meta_info(name string) ?Mod { +fn get_module_meta_info(name string) !Mod { if mod := get_mod_by_url(name) { return mod } diff --git a/cmd/tools/vrepl.v b/cmd/tools/vrepl.v index 370d96b1e9..d55160e431 100644 --- a/cmd/tools/vrepl.v +++ b/cmd/tools/vrepl.v @@ -576,7 +576,7 @@ fn cleanup_files(file string) { } } -fn repl_run_vfile(file string) ?os.Result { +fn repl_run_vfile(file string) !os.Result { $if trace_repl_temp_files ? { eprintln('>> repl_run_vfile file: ${file}') } diff --git a/cmd/tools/vsymlink.v b/cmd/tools/vsymlink.v index e41bbd7c84..199605d1bc 100644 --- a/cmd/tools/vsymlink.v +++ b/cmd/tools/vsymlink.v @@ -152,7 +152,7 @@ fn warn_and_exit(err string) { } // get the system environment registry handle -fn get_reg_sys_env_handle() ?voidptr { +fn get_reg_sys_env_handle() !voidptr { $if windows { // wrap for cross-compile compat // open the registry key reg_key_path := 'Environment' @@ -166,7 +166,7 @@ fn get_reg_sys_env_handle() ?voidptr { } // get a value from a given $key -fn get_reg_value(reg_env_key voidptr, key string) ?string { +fn get_reg_value(reg_env_key voidptr, key string) !string { $if windows { // query the value (shortcut the sizing step) reg_value_size := u32(4095) // this is the max length (not for the registry, but for the system %PATH%) @@ -180,7 +180,7 @@ fn get_reg_value(reg_env_key voidptr, key string) ?string { } // sets the value for the given $key to the given $value -fn set_reg_value(reg_key voidptr, key string, value string) ?bool { +fn set_reg_value(reg_key voidptr, key string, value string) !bool { $if windows { if C.RegSetValueExW(reg_key, key.to_wide(), 0, C.REG_EXPAND_SZ, value.to_wide(), value.len * 2) != 0 { @@ -193,7 +193,7 @@ fn set_reg_value(reg_key voidptr, key string, value string) ?bool { // Broadcasts a message to all listening windows (explorer.exe in particular) // letting them know that the system environment has changed and should be reloaded -fn send_setting_change_msg(message_data string) ?bool { +fn send_setting_change_msg(message_data string) !bool { $if windows { if C.SendMessageTimeoutW(os.hwnd_broadcast, os.wm_settingchange, 0, unsafe { &u32(message_data.to_wide()) }, os.smto_abortifhung, 5000, 0) == 0 { diff --git a/examples/js_dom_draw_bechmark_chart/chart/main.v b/examples/js_dom_draw_bechmark_chart/chart/main.v index 6076c4845a..b4ae061322 100644 --- a/examples/js_dom_draw_bechmark_chart/chart/main.v +++ b/examples/js_dom_draw_bechmark_chart/chart/main.v @@ -69,7 +69,7 @@ fn new_app() &App { } ['/'; get] -pub fn (mut app App) controller_get_all_task() ?vweb.Result { +pub fn (mut app App) controller_get_all_task() !vweb.Result { v_version := version.full_v_version(true) orm_stmt_kinds := ['insert', 'select', 'update'] diff --git a/examples/vweb_fullstack/src/product_service.v b/examples/vweb_fullstack/src/product_service.v index e844adcd72..15f55bf4e8 100644 --- a/examples/vweb_fullstack/src/product_service.v +++ b/examples/vweb_fullstack/src/product_service.v @@ -25,7 +25,7 @@ fn (mut app App) service_add_product(product_name string, user_id int) ! { } } -fn (mut app App) service_get_all_products_from(user_id int) ?[]Product { +fn (mut app App) service_get_all_products_from(user_id int) ![]Product { mut db := databases.create_db_connection() or { println(err) return err diff --git a/examples/vweb_fullstack/src/user_services.v b/examples/vweb_fullstack/src/user_services.v index 71d76c91a2..30e675f3ca 100644 --- a/examples/vweb_fullstack/src/user_services.v +++ b/examples/vweb_fullstack/src/user_services.v @@ -30,7 +30,7 @@ fn (mut app App) service_add_user(username string, password string) ! { } } -fn (mut app App) service_get_all_user() ?[]User { +fn (mut app App) service_get_all_user() ![]User { mut db := databases.create_db_connection() or { println(err) return err @@ -47,7 +47,7 @@ fn (mut app App) service_get_all_user() ?[]User { return results } -fn (mut app App) service_get_user(id int) ?User { +fn (mut app App) service_get_user(id int) !User { mut db := databases.create_db_connection() or { println(err) return err diff --git a/examples/vweb_orm_jwt/src/user_services.v b/examples/vweb_orm_jwt/src/user_services.v index 4b6fce98f7..d2006c193f 100644 --- a/examples/vweb_orm_jwt/src/user_services.v +++ b/examples/vweb_orm_jwt/src/user_services.v @@ -3,7 +3,7 @@ module main import crypto.bcrypt import databases -fn (mut app App) service_add_user(username string, password string) ?User { +fn (mut app App) service_add_user(username string, password string) !User { mut db := databases.create_db_connection() or { eprintln(err) return err @@ -38,7 +38,7 @@ fn (mut app App) service_add_user(username string, password string) ?User { return result } -fn (mut app App) service_get_user_by_id(user_id int) ?User { +fn (mut app App) service_get_user_by_id(user_id int) !User { mut db := databases.create_db_connection() or { println(err) return err @@ -55,7 +55,7 @@ fn (mut app App) service_get_user_by_id(user_id int) ?User { return results } -fn (mut app App) service_get_all_user() ?[]User { +fn (mut app App) service_get_all_user() ![]User { mut db := databases.create_db_connection() or { println(err) return err @@ -72,7 +72,7 @@ fn (mut app App) service_get_all_user() ?[]User { return results } -fn (mut app App) service_get_by_username(username string) ?User { +fn (mut app App) service_get_by_username(username string) !User { mut db := databases.create_db_connection() or { println(err) return err diff --git a/vlib/builtin/int.v b/vlib/builtin/int.v index 480570d726..4236d8568d 100644 --- a/vlib/builtin/int.v +++ b/vlib/builtin/int.v @@ -562,8 +562,8 @@ pub fn (b []u8) bytestr() string { // from utf8 to utf32 and return the result as a rune // it will produce an error if there are more than // four bytes in the array. -pub fn (b []u8) byterune() ?rune { - r := b.utf8_to_utf32()? +pub fn (b []u8) byterune() !rune { + r := b.utf8_to_utf32()! return rune(r) } diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 9c50aa800d..02f1d8c833 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -910,7 +910,7 @@ pub fn (s string) substr(start int, end int) string { // version of `substr()` that is used in `a[start..end] or {` // return an error when the index is out of range [direct_array_access] -pub fn (s string) substr_with_check(start int, end int) ?string { +pub fn (s string) substr_with_check(start int, end int) !string { if start > end || start > s.len || end > s.len || start < 0 || end < 0 { return error('substr(${start}, ${end}) out of bounds (len=${s.len})') } @@ -1606,7 +1606,7 @@ fn (s string) at(idx int) byte { // return an error when the index is out of range fn (s string) at_with_check(idx int) ?u8 { if idx < 0 || idx >= s.len { - return error('string index out of range') + return none } unsafe { return s.str[idx] diff --git a/vlib/builtin/utf8.v b/vlib/builtin/utf8.v index 847feb6768..91d38c57b4 100644 --- a/vlib/builtin/utf8.v +++ b/vlib/builtin/utf8.v @@ -98,7 +98,7 @@ pub fn (_rune string) utf32_code() int { // convert array of utf8 bytes to single utf32 value // will error if more than 4 bytes are submitted -pub fn (_bytes []u8) utf8_to_utf32() ?rune { +pub fn (_bytes []u8) utf8_to_utf32() !rune { if _bytes.len == 0 { return 0 } diff --git a/vlib/crypto/bcrypt/bcrypt.v b/vlib/crypto/bcrypt/bcrypt.v index b396552dcf..5d74de215c 100644 --- a/vlib/crypto/bcrypt/bcrypt.v +++ b/vlib/crypto/bcrypt/bcrypt.v @@ -43,14 +43,14 @@ const magic_cipher_data = [u8(0x4f), 0x72, 0x70, 0x68, 0x65, 0x61, 0x6e, 0x42, 0 0x6c, 0x64, 0x65, 0x72, 0x53, 0x63, 0x72, 0x79, 0x44, 0x6f, 0x75, 0x62, 0x74] // generate_from_password return a bcrypt string from Hashed struct. -pub fn generate_from_password(password []u8, cost int) ?string { +pub fn generate_from_password(password []u8, cost int) !string { mut p := new_from_password(password, cost) or { return error('Error: ${err}') } x := p.hash_u8() return x.bytestr() } // compare_hash_and_password compares a bcrypt hashed password with its possible hashed version. -pub fn compare_hash_and_password(password []u8, hashed_password []u8) ? { +pub fn compare_hash_and_password(password []u8, hashed_password []u8) ! { mut p := new_from_hash(hashed_password) or { return error('Error: ${err}') } p.salt << `=` p.salt << `=` @@ -76,7 +76,7 @@ pub fn generate_salt() string { } // new_from_password converting from password to a Hashed struct with bcrypt. -fn new_from_password(password []u8, cost int) ?&Hashed { +fn new_from_password(password []u8, cost int) !&Hashed { mut cost_ := cost if cost < bcrypt.min_cost { cost_ = bcrypt.default_cost @@ -98,7 +98,7 @@ fn new_from_password(password []u8, cost int) ?&Hashed { } // new_from_hash converting from hashed data to a Hashed struct. -fn new_from_hash(hashed_secret []u8) ?&Hashed { +fn new_from_hash(hashed_secret []u8) !&Hashed { mut tmp := hashed_secret.clone() if tmp.len < bcrypt.min_hash_size { return error('hash to short') @@ -118,7 +118,7 @@ fn new_from_hash(hashed_secret []u8) ?&Hashed { } // bcrypt hashing passwords. -fn bcrypt(password []u8, cost int, salt []u8) ?[]u8 { +fn bcrypt(password []u8, cost int, salt []u8) ![]u8 { mut cipher_data := []u8{len: 72 - bcrypt.magic_cipher_data.len, init: 0} cipher_data << bcrypt.magic_cipher_data @@ -135,7 +135,7 @@ fn bcrypt(password []u8, cost int, salt []u8) ?[]u8 { } // expensive_blowfish_setup generate a Blowfish cipher, given key, cost and salt. -fn expensive_blowfish_setup(key []u8, cost u32, salt []u8) ?&blowfish.Blowfish { +fn expensive_blowfish_setup(key []u8, cost u32, salt []u8) !&blowfish.Blowfish { csalt := base64.decode(salt.bytestr()) // Bug compatibility with C bcrypt implementations, which use the trailing NULL in the key string during expansion. // See https://cs.opensource.google/go/x/crypto/+/master:bcrypt/bcrypt.go;l=226 @@ -180,7 +180,7 @@ fn (mut h Hashed) hash_u8() []u8 { } // decode_version decode bcrypt version. -fn (mut h Hashed) decode_version(sbytes []u8) ?int { +fn (mut h Hashed) decode_version(sbytes []u8) !int { if sbytes[0] != `$` { return error("bcrypt hashes must start with '$'") } @@ -197,7 +197,7 @@ fn (mut h Hashed) decode_version(sbytes []u8) ?int { } // decode_cost extracts the value of cost and returns the next index in the array. -fn (mut h Hashed) decode_cost(sbytes []u8) ?int { +fn (mut h Hashed) decode_cost(sbytes []u8) !int { cost := sbytes[0..2].bytestr().int() check_cost(cost) or { return err } h.cost = cost @@ -205,7 +205,7 @@ fn (mut h Hashed) decode_cost(sbytes []u8) ?int { } // check_cost check for reasonable quantities. -fn check_cost(cost int) ? { +fn check_cost(cost int) ! { if cost < bcrypt.min_cost || cost > bcrypt.max_cost { return error('invalid cost') } diff --git a/vlib/crypto/blowfish/blowfish.v b/vlib/crypto/blowfish/blowfish.v index af1ea99849..c1e7650055 100644 --- a/vlib/crypto/blowfish/blowfish.v +++ b/vlib/crypto/blowfish/blowfish.v @@ -8,7 +8,7 @@ pub mut: // new_cipher creates and returns a new Blowfish cipher. // The key argument should be the Blowfish key, from 1 to 56 bytes. -pub fn new_cipher(key []u8) ?Blowfish { +pub fn new_cipher(key []u8) !Blowfish { mut bf := Blowfish{} unsafe { vmemcpy(&bf.p[0], &p[0], int(sizeof(bf.p))) } unsafe { vmemcpy(&bf.s[0], &s[0], int(sizeof(bf.s))) } @@ -21,7 +21,7 @@ pub fn new_cipher(key []u8) ?Blowfish { } // new_salted_cipher returns a new Blowfish cipher that folds a salt into its key schedule. -pub fn new_salted_cipher(key []u8, salt []u8) ?Blowfish { +pub fn new_salted_cipher(key []u8, salt []u8) !Blowfish { if salt.len == 0 { return new_cipher(key) } diff --git a/vlib/io/util/util.v b/vlib/io/util/util.v index f8252cf6bb..d6ae7a40e0 100644 --- a/vlib/io/util/util.v +++ b/vlib/io/util/util.v @@ -76,7 +76,7 @@ fn random_number() string { return s.substr(1, s.len) } -fn prefix_and_suffix(pattern string) ?(string, string) { +fn prefix_and_suffix(pattern string) !(string, string) { mut pat := pattern if pat.contains(os.path_separator) { return error('pattern cannot contain path separators (${os.path_separator}).') diff --git a/vlib/os/filepath.v b/vlib/os/filepath.v index d617354486..06c2308e6b 100644 --- a/vlib/os/filepath.v +++ b/vlib/os/filepath.v @@ -131,7 +131,7 @@ pub fn norm_path(path string) string { // existing_path returns the existing part of the given `path`. // An error is returned if there is no existing part of the given `path`. -pub fn existing_path(path string) ?string { +pub fn existing_path(path string) !string { err := error('path does not exist') if path.len == 0 { return err diff --git a/vlib/picoev/picoev.v b/vlib/picoev/picoev.v index 993904f65e..bfb63b3921 100644 --- a/vlib/picoev/picoev.v +++ b/vlib/picoev/picoev.v @@ -77,7 +77,7 @@ mut: } [inline] -fn setup_sock(fd int) ? { +fn setup_sock(fd int) ! { flag := 1 if C.setsockopt(fd, C.IPPROTO_TCP, C.TCP_NODELAY, &flag, sizeof(int)) < 0 { return error('setup_sock.setup_sock failed') diff --git a/vlib/regex/regex_opt.v b/vlib/regex/regex_opt.v index 3e366f517e..e686a0a595 100644 --- a/vlib/regex/regex_opt.v +++ b/vlib/regex/regex_opt.v @@ -3,7 +3,7 @@ module regex import strings // compile_opt compile RE pattern string -pub fn (mut re RE) compile_opt(pattern string) ? { +pub fn (mut re RE) compile_opt(pattern string) ! { re_err, err_pos := re.impl_compile(pattern) if re_err != compile_ok { @@ -34,7 +34,7 @@ pub fn new() RE { } // regex_opt create new RE object from RE pattern string -pub fn regex_opt(pattern string) ?RE { +pub fn regex_opt(pattern string) !RE { // init regex mut re := RE{} re.prog = []Token{len: pattern.len + 1} // max program length, can not be longer then the pattern @@ -47,7 +47,7 @@ pub fn regex_opt(pattern string) ?RE { re.group_data = []int{len: re.group_max, init: -1} // compile the pattern - re.compile_opt(pattern)? + re.compile_opt(pattern)! return re } diff --git a/vlib/semver/parse.v b/vlib/semver/parse.v index 0b2c6b1527..3db05fd636 100644 --- a/vlib/semver/parse.v +++ b/vlib/semver/parse.v @@ -53,7 +53,7 @@ fn (ver RawVersion) is_missing(typ int) bool { return typ >= ver.raw_ints.len - 1 } -fn (raw_ver RawVersion) coerce() ?Version { +fn (raw_ver RawVersion) coerce() !Version { ver := raw_ver.complete() if !is_valid_number(ver.raw_ints[semver.ver_major]) { return error('Invalid major version: ${ver.raw_ints}[ver_major]') diff --git a/vlib/semver/range.v b/vlib/semver/range.v index 2d2c398976..71e328ea1a 100644 --- a/vlib/semver/range.v +++ b/vlib/semver/range.v @@ -69,7 +69,7 @@ fn (c Comparator) satisfies(ver Version) bool { return false } -fn parse_range(input string) ?Range { +fn parse_range(input string) !Range { raw_comparator_sets := input.split(semver.comparator_set_sep) mut comparator_sets := []ComparatorSet{} for raw_comp_set in raw_comparator_sets { @@ -84,7 +84,7 @@ fn parse_range(input string) ?Range { return Range{comparator_sets} } -fn parse_comparator_set(input string) ?ComparatorSet { +fn parse_comparator_set(input string) !ComparatorSet { raw_comparators := input.split(semver.comparator_sep) if raw_comparators.len > 2 { return &InvalidComparatorFormatError{ diff --git a/vlib/semver/semver.v b/vlib/semver/semver.v index b7bdba123b..aa121ad6cd 100644 --- a/vlib/semver/semver.v +++ b/vlib/semver/semver.v @@ -38,7 +38,7 @@ pub fn (err InvalidVersionFormatError) msg() string { // * Constructor. // from returns a `Version` structure parsed from `input` `string`. -pub fn from(input string) ?Version { +pub fn from(input string) !Version { if input.len == 0 { return &EmptyInputError{} } @@ -114,7 +114,7 @@ import semver v := semver.coerce('1.3-RC1-b2') or { semver.Version{} } assert v.satisfies('>1.0 <2.0') == true // 1.3.0 */ -pub fn coerce(input string) ?Version { +pub fn coerce(input string) !Version { return coerce_version(input) } diff --git a/vlib/semver/util.v b/vlib/semver/util.v index ebaa172b82..8cab5ef7dc 100644 --- a/vlib/semver/util.v +++ b/vlib/semver/util.v @@ -8,7 +8,7 @@ fn is_version_valid(input string) bool { } [inline] -fn coerce_version(input string) ?Version { +fn coerce_version(input string) !Version { raw_ver := parse(input) ver := raw_ver.coerce() or { return error('Invalid version for input "${input}"') } return ver diff --git a/vlib/time/time.v b/vlib/time/time.v index cba513f97c..329dd59f30 100644 --- a/vlib/time/time.v +++ b/vlib/time/time.v @@ -285,7 +285,7 @@ pub fn is_leap_year(year int) bool { } // days_in_month returns a number of days in a given month. -pub fn days_in_month(month int, year int) ?int { +pub fn days_in_month(month int, year int) !int { if month > 12 || month < 1 { return error('Invalid month: ${month}') } diff --git a/vlib/v/builder/builder.v b/vlib/v/builder/builder.v index d20b6bee47..a3dc5c4efc 100644 --- a/vlib/v/builder/builder.v +++ b/vlib/v/builder/builder.v @@ -368,7 +368,7 @@ pub fn module_path(mod string) string { // TODO: try to merge this & util.module functions to create a // reliable multi use function. see comments in util/module.v -pub fn (b &Builder) find_module_path(mod string, fpath string) ?string { +pub fn (b &Builder) find_module_path(mod string, fpath string) !string { // support @VROOT/v.mod relative paths: mut mcache := vmod.get_cache() vmod_file_location := mcache.get_by_file(fpath) diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 0138804100..a555f30ffd 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -194,7 +194,7 @@ fn (c Checker) check_multiple_ptr_match(got ast.Type, expected ast.Type, param a return true } -fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, language ast.Language, arg ast.CallArg) ? { +fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, language ast.Language, arg ast.CallArg) ! { if got == 0 { return error('unexpected 0 type') } diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index 9d17312fb4..bf4c2d16aa 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -96,6 +96,12 @@ fn (mut c Checker) return_stmt(mut node ast.Return) { 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_option && got_types_0_idx == ast.error_type_idx { + c.warn('Option and Result types have been split, use `!Foo` to return errors', + node.pos) + } else if exp_is_result && got_types_0_idx == ast.none_type_idx { + c.warn('Option and Result types have been split, use `?Foo` to return none', node.pos) + } if (exp_is_option && got_types_0_idx in [ast.none_type_idx, ast.error_type_idx, option_type_idx]) || (exp_is_result && got_types_0_idx in [ast.error_type_idx, result_type_idx]) { diff --git a/vlib/v/checker/tests/error_fn_with_0_args.out b/vlib/v/checker/tests/error_fn_with_0_args.out index c4aceee5d7..df6b2375d8 100644 --- a/vlib/v/checker/tests/error_fn_with_0_args.out +++ b/vlib/v/checker/tests/error_fn_with_0_args.out @@ -1,5 +1,5 @@ vlib/v/checker/tests/error_fn_with_0_args.vv:2:9: error: expected 1 arguments, but got 0 - 1 | fn abc() ? { + 1 | fn abc() ! { 2 | return error() | ~~~~~~~ 3 | } diff --git a/vlib/v/checker/tests/error_fn_with_0_args.vv b/vlib/v/checker/tests/error_fn_with_0_args.vv index ebbfe4715b..e5a8a82e54 100644 --- a/vlib/v/checker/tests/error_fn_with_0_args.vv +++ b/vlib/v/checker/tests/error_fn_with_0_args.vv @@ -1,3 +1,3 @@ -fn abc() ? { +fn abc() ! { return error() } diff --git a/vlib/v/checker/tests/expression_should_return_an_option.vv b/vlib/v/checker/tests/expression_should_return_an_option.vv index 05ad45a39e..334a2be55b 100644 --- a/vlib/v/checker/tests/expression_should_return_an_option.vv +++ b/vlib/v/checker/tests/expression_should_return_an_option.vv @@ -1,4 +1,4 @@ -fn return_option(fail bool) ?string { +fn return_option(fail bool) !string { if fail { return error('nope') } diff --git a/vlib/v/checker/tests/invalid_parameter_name_err.out b/vlib/v/checker/tests/invalid_parameter_name_err.out index b8940b18fc..db6ec6fa05 100644 --- a/vlib/v/checker/tests/invalid_parameter_name_err.out +++ b/vlib/v/checker/tests/invalid_parameter_name_err.out @@ -1,14 +1,14 @@ vlib/v/checker/tests/invalid_parameter_name_err.vv:4:24: error: invalid use of reserved type `char` as a parameter name 2 | } 3 | - 4 | fn (mut b Buffer) put8(char u8) ? { + 4 | fn (mut b Buffer) put8(char u8) ! { | ~~~~ 5 | return error('-') 6 | } vlib/v/checker/tests/invalid_parameter_name_err.vv:10:6: error: invalid use of reserved type `char` as a parameter name 8 | interface Writer { 9 | mut: - 10 | put(char u8)? + 10 | put(char u8) ! | ~~~~ 11 | } 12 | diff --git a/vlib/v/checker/tests/invalid_parameter_name_err.vv b/vlib/v/checker/tests/invalid_parameter_name_err.vv index 39054879a1..a74b41c601 100644 --- a/vlib/v/checker/tests/invalid_parameter_name_err.vv +++ b/vlib/v/checker/tests/invalid_parameter_name_err.vv @@ -1,13 +1,13 @@ struct Buffer { } -fn (mut b Buffer) put8(char u8) ? { +fn (mut b Buffer) put8(char u8) ! { return error('-') } interface Writer { mut: - put(char u8)? + put(char u8) ! } fn main() { diff --git a/vlib/v/checker/tests/option_fn_return_error.out b/vlib/v/checker/tests/option_fn_return_error.out new file mode 100644 index 0000000000..180b0ae3f7 --- /dev/null +++ b/vlib/v/checker/tests/option_fn_return_error.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/option_fn_return_error.vv:2:2: warning: Option and Result types have been split, use `!Foo` to return errors + 1 | fn func() ?int { + 2 | return error('Some error') + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + 3 | } + 4 | diff --git a/vlib/v/checker/tests/option_fn_return_error.vv b/vlib/v/checker/tests/option_fn_return_error.vv new file mode 100644 index 0000000000..a7be95cd02 --- /dev/null +++ b/vlib/v/checker/tests/option_fn_return_error.vv @@ -0,0 +1,11 @@ +fn func() ?int { + return error('Some error') +} + +fn main() { + mut a := ?int(5) + a = 1 + a = none + a = func() + println(a) +} diff --git a/vlib/v/checker/tests/option_or_block_returns_value_of_incompatible_type.vv b/vlib/v/checker/tests/option_or_block_returns_value_of_incompatible_type.vv index ec75da47f1..11cf1f0e27 100644 --- a/vlib/v/checker/tests/option_or_block_returns_value_of_incompatible_type.vv +++ b/vlib/v/checker/tests/option_or_block_returns_value_of_incompatible_type.vv @@ -1,4 +1,4 @@ -fn test_option(fail bool) ?string { +fn test_option(fail bool) !string { if fail { return error('false') } diff --git a/vlib/v/checker/tests/option_propagate_nested.out b/vlib/v/checker/tests/option_propagate_nested.out index 3174c43a10..ecd4a02f72 100644 --- a/vlib/v/checker/tests/option_propagate_nested.out +++ b/vlib/v/checker/tests/option_propagate_nested.out @@ -12,17 +12,17 @@ Details: vlib/v/checker/tests/option_propagate_nested.vv:9:14: details: prepend | ~~~~~~ 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 +vlib/v/checker/tests/option_propagate_nested.vv:28:21: error: to propagate the result call, `aa_propagate` must return a result 26 | 27 | fn (mut s St) aa_propagate() { - 28 | f := retf(s.raise()?) + 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` +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 \ No newline at end of file + 28 | f := retf(s.raise()!) + 29 | s.z = 7.5 diff --git a/vlib/v/checker/tests/option_propagate_nested.vv b/vlib/v/checker/tests/option_propagate_nested.vv index 07c299b55a..b320d4d4ea 100644 --- a/vlib/v/checker/tests/option_propagate_nested.vv +++ b/vlib/v/checker/tests/option_propagate_nested.vv @@ -16,7 +16,7 @@ mut: z f64 } -fn (mut s St) raise() ?f64 { +fn (mut s St) raise() !f64 { return error('some error') } @@ -25,7 +25,7 @@ fn retf(f f64) f64 { } fn (mut s St) aa_propagate() { - f := retf(s.raise()?) + f := retf(s.raise()!) s.z = 7.5 println(f) } diff --git a/vlib/v/checker/tests/run/noreturn_fn_can_be_used_instead_of_panic.vv b/vlib/v/checker/tests/run/noreturn_fn_can_be_used_instead_of_panic.vv index 10cf22c37d..901c3c97f0 100644 --- a/vlib/v/checker/tests/run/noreturn_fn_can_be_used_instead_of_panic.vv +++ b/vlib/v/checker/tests/run/noreturn_fn_can_be_used_instead_of_panic.vv @@ -1,4 +1,4 @@ -fn abc() ?int { +fn abc() !int { return error('oh no') } diff --git a/vlib/v/checker/tests/run/noreturn_method_can_be_used_instead_of_panic.vv b/vlib/v/checker/tests/run/noreturn_method_can_be_used_instead_of_panic.vv index 9b6b7bcab6..10cdcb1fad 100644 --- a/vlib/v/checker/tests/run/noreturn_method_can_be_used_instead_of_panic.vv +++ b/vlib/v/checker/tests/run/noreturn_method_can_be_used_instead_of_panic.vv @@ -7,7 +7,7 @@ fn (mut t Test) zz_exit() { exit(0) } -fn option() ?int { +fn option() !int { return error('oh no') } diff --git a/vlib/v/checker/tests/store_string_err.vv b/vlib/v/checker/tests/store_string_err.vv index 7f8b3ff29a..22dabdded6 100644 --- a/vlib/v/checker/tests/store_string_err.vv +++ b/vlib/v/checker/tests/store_string_err.vv @@ -1,4 +1,4 @@ -fn return_err() ?int { +fn return_err() !int { return error('') } diff --git a/vlib/v/doc/doc.v b/vlib/v/doc/doc.v index a5bc7835b2..33b691cd2b 100644 --- a/vlib/v/doc/doc.v +++ b/vlib/v/doc/doc.v @@ -49,7 +49,7 @@ pub enum Platform { } // copy of pref.os_from_string -pub fn platform_from_string(platform_str string) ?Platform { +pub fn platform_from_string(platform_str string) !Platform { match platform_str { 'all', 'cross' { return .cross } 'linux' { return .linux } @@ -177,7 +177,7 @@ pub fn new(input_path string) Doc { // stmt reads the data of an `ast.Stmt` node and returns a `DocNode`. // An option error is thrown if the symbol is not exposed to the public // (when `pub_only` is enabled) or the content's of the AST node is empty. -pub fn (mut d Doc) stmt(stmt ast.Stmt, filename string) ?DocNode { +pub fn (mut d Doc) stmt(stmt ast.Stmt, filename string) !DocNode { mut name := d.stmt_name(stmt) if name in d.common_symbols { return error('already documented') @@ -421,7 +421,7 @@ pub fn (mut d Doc) file_ast_with_pos(file_ast ast.File, pos int) map[string]DocN // generate is a `Doc` method that will start documentation // process based on a file path provided. -pub fn (mut d Doc) generate() ? { +pub fn (mut d Doc) generate() ! { // get all files d.base_path = if os.is_dir(d.base_path) { d.base_path @@ -451,7 +451,7 @@ pub fn (mut d Doc) generate() ? { // file_asts has the same function as the `file_ast` function but // accepts an array of `ast.File` and throws an error if necessary. -pub fn (mut d Doc) file_asts(file_asts []ast.File) ? { +pub fn (mut d Doc) file_asts(file_asts []ast.File) ! { mut fname_has_set := false d.orig_mod_name = file_asts[0].mod.name for i, file_ast in file_asts { @@ -506,7 +506,7 @@ pub fn (mut d Doc) file_asts(file_asts []ast.File) ? { // generate documents a certain file directory and returns an // instance of `Doc` if it is successful. Otherwise, it will throw an error. -pub fn generate(input_path string, pub_only bool, with_comments bool, platform Platform, filter_symbol_names ...string) ?Doc { +pub fn generate(input_path string, pub_only bool, with_comments bool, platform Platform, filter_symbol_names ...string) !Doc { if platform == .js { return error('vdoc: Platform `${platform}` is not supported.') } @@ -519,19 +519,19 @@ pub fn generate(input_path string, pub_only bool, with_comments bool, platform P } else { unsafe { pref.OS(int(platform)) } } - doc.generate()? + doc.generate()! return doc } // generate_with_pos has the same function as the `generate` function but // accepts an offset-based position and enables the comments by default. -pub fn generate_with_pos(input_path string, filename string, pos int) ?Doc { +pub fn generate_with_pos(input_path string, filename string, pos int) !Doc { mut doc := new(input_path) doc.pub_only = false doc.with_comments = true doc.with_pos = true doc.filename = filename doc.pos = pos - doc.generate()? + doc.generate()! return doc } diff --git a/vlib/v/doc/module.v b/vlib/v/doc/module.v index f6e4151698..72176a0d9e 100644 --- a/vlib/v/doc/module.v +++ b/vlib/v/doc/module.v @@ -13,7 +13,7 @@ import v.pref // Note: calling this is expensive, so keep the result, instead of recomputing it. // TODO: turn this to a Doc method, so that the new_vdoc_preferences call here can // be removed. -fn get_parent_mod(input_dir string) ?string { +fn get_parent_mod(input_dir string) !string { // windows root path is C: or D: if input_dir.len == 2 && input_dir[1] == `:` { return error('root folder reached') @@ -56,7 +56,7 @@ fn get_parent_mod(input_dir string) ?string { // lookup_module_with_path looks up the path of a given module name. // Throws an error if the module was not found. -pub fn lookup_module_with_path(mod string, base_path string) ?string { +pub fn lookup_module_with_path(mod string, base_path string) !string { vexe := pref.vexe_path() vroot := os.dir(vexe) mod_path := mod.replace('.', os.path_separator) @@ -79,12 +79,12 @@ pub fn lookup_module_with_path(mod string, base_path string) ?string { // lookup_module returns the result of the `lookup_module_with_path` // but with the current directory as the provided base lookup path. -pub fn lookup_module(mod string) ?string { +pub fn lookup_module(mod string) !string { return lookup_module_with_path(mod, os.dir('.')) } // generate_from_mod generates a documentation from a specific module. -pub fn generate_from_mod(module_name string, pub_only bool, with_comments bool) ?Doc { - mod_path := lookup_module(module_name)? +pub fn generate_from_mod(module_name string, pub_only bool, with_comments bool) !Doc { + mod_path := lookup_module(module_name)! return generate(mod_path, pub_only, with_comments, .auto) } diff --git a/vlib/v/doc/node.v b/vlib/v/doc/node.v index 068f2f1f30..954360fb3d 100644 --- a/vlib/v/doc/node.v +++ b/vlib/v/doc/node.v @@ -1,6 +1,6 @@ module doc -pub fn (nodes []DocNode) find(symname string) ?DocNode { +pub fn (nodes []DocNode) find(symname string) !DocNode { for node in nodes { if node.name != symname { continue diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index c5e12c4236..8f462df1bd 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -835,7 +835,7 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) { g.writeln('}// \$for') } -fn (mut g Gen) comptime_if_to_ifdef(name string, is_comptime_option bool) ?string { +fn (mut g Gen) comptime_if_to_ifdef(name string, is_comptime_option bool) !string { match name { // platforms/os-es: 'windows' { @@ -991,5 +991,5 @@ fn (mut g Gen) comptime_if_to_ifdef(name string, is_comptime_option bool) ?strin return error('bad os ifdef name "${name}"') // should never happen, caught in the checker } } - return none + return error('none') } diff --git a/vlib/v/gen/c/index.v b/vlib/v/gen/c/index.v index 09d4bd1b23..99a7f78165 100644 --- a/vlib/v/gen/c/index.v +++ b/vlib/v/gen/c/index.v @@ -72,7 +72,7 @@ fn (mut g Gen) index_range_expr(node ast.IndexExpr, range ast.RangeExpr) { tmp_opt = g.new_tmp_var() cur_line = g.go_before_stmt(0) g.out.write_string(util.tabs(g.indent)) - opt_elem_type := g.typ(ast.string_type.set_flag(.option)) + opt_elem_type := g.typ(ast.string_type.set_flag(.result)) g.write('${opt_elem_type} ${tmp_opt} = string_substr_with_check(') } else { g.write('string_substr(') @@ -165,7 +165,7 @@ fn (mut g Gen) index_range_expr(node ast.IndexExpr, range ast.RangeExpr) { if gen_or { if !node.is_option { - g.or_block(tmp_opt, node.or_expr, ast.string_type) + g.or_block(tmp_opt, node.or_expr, ast.string_type.set_flag(.result)) } g.write('\n${cur_line}*(string*)&${tmp_opt}.data') diff --git a/vlib/v/pkgconfig/main.v b/vlib/v/pkgconfig/main.v index 267a2e7f48..5c3f5a253d 100644 --- a/vlib/v/pkgconfig/main.v +++ b/vlib/v/pkgconfig/main.v @@ -34,7 +34,7 @@ struct MainOptions { args []string } -fn desc(mod string) ?string { +fn desc(mod string) !string { options := Options{ only_description: true } @@ -42,7 +42,7 @@ fn desc(mod string) ?string { return pc.description } -pub fn main(args []string) ?&Main { +pub fn main(args []string) !&Main { mut fp := flag.new_flag_parser(args) fp.application('pkgconfig') fp.version(version) @@ -72,7 +72,7 @@ pub fn main(args []string) ?&Main { return m } -pub fn (mut m Main) run() ?string { +pub fn (mut m Main) run() !string { options := Options{ debug: m.opt.debug } @@ -94,7 +94,7 @@ pub fn (mut m Main) run() ?string { res += pcdep.description } if unsafe { pc != 0 } { - pc.extend(pcdep)? + pc.extend(pcdep)! } else { pc = pcdep } diff --git a/vlib/v/pkgconfig/pkgconfig.v b/vlib/v/pkgconfig/pkgconfig.v index 090b5fae77..7c89b8374e 100644 --- a/vlib/v/pkgconfig/pkgconfig.v +++ b/vlib/v/pkgconfig/pkgconfig.v @@ -140,7 +140,7 @@ fn (mut pc PkgConfig) parse(file string) bool { return true } -fn (mut pc PkgConfig) resolve(pkgname string) ?string { +fn (mut pc PkgConfig) resolve(pkgname string) !string { if pkgname.ends_with('.pc') { if os.exists(pkgname) { return pkgname @@ -171,7 +171,7 @@ pub fn (mut pc PkgConfig) atleast(v string) bool { return v0.gt(v1) } -pub fn (mut pc PkgConfig) extend(pcdep &PkgConfig) ?string { +pub fn (mut pc PkgConfig) extend(pcdep &PkgConfig) !string { for flag in pcdep.cflags { if pc.cflags.index(flag) == -1 { pc.cflags << flag @@ -187,19 +187,19 @@ pub fn (mut pc PkgConfig) extend(pcdep &PkgConfig) ?string { pc.libs_private << lib } } - return none + return error('') } -fn (mut pc PkgConfig) load_requires() ? { +fn (mut pc PkgConfig) load_requires() ! { for dep in pc.requires { - pc.load_require(dep)? + pc.load_require(dep)! } for dep in pc.requires_private { - pc.load_require(dep)? + pc.load_require(dep)! } } -fn (mut pc PkgConfig) load_require(dep string) ? { +fn (mut pc PkgConfig) load_require(dep string) ! { if dep in pc.loaded { return } @@ -218,9 +218,9 @@ fn (mut pc PkgConfig) load_require(dep string) ? { return error('required file "${depfile}" could not be parsed') } if !pc.options.norecurse { - pcdep.load_requires()? + pcdep.load_requires()! } - pc.extend(pcdep)? + pc.extend(pcdep) or {} } fn (mut pc PkgConfig) add_path(path string) { @@ -267,7 +267,7 @@ fn (mut pc PkgConfig) load_paths() { } } -pub fn load(pkgname string, options Options) ?&PkgConfig { +pub fn load(pkgname string, options Options) !&PkgConfig { mut pc := &PkgConfig{ modname: pkgname options: options @@ -278,7 +278,7 @@ pub fn load(pkgname string, options Options) ?&PkgConfig { return error('file "${file}" could not be parsed') } if !options.norecurse { - pc.load_requires()? + pc.load_requires()! } return pc } diff --git a/vlib/v/tests/string_index_or_test.v b/vlib/v/tests/string_index_or_test.v index ed87bd9626..e445e105c9 100644 --- a/vlib/v/tests/string_index_or_test.v +++ b/vlib/v/tests/string_index_or_test.v @@ -48,5 +48,5 @@ fn test_propagation() { x := get_propagate(s, 2) or { '${err}' } y := get_propagate(s, 5) or { '${err}' } assert x == 'got `c`' - assert y == 'string index out of range' + assert y == 'none' }