diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index e10b6ddcca..ecff92bb35 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1618,10 +1618,10 @@ pub fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type table.Type) t return ret_type } else if expr.or_block.kind == .block { c.error('unexpected `or` block, the function `$expr.name` does not return an optional', - expr.pos) + expr.or_block.pos) } else if expr.or_block.kind == .propagate { c.error('unexpected `?`, the function `$expr.name`, does not return an optional', - expr.pos) + expr.or_block.pos) } } return ret_type diff --git a/vlib/v/checker/tests/or_err.out b/vlib/v/checker/tests/or_err.out index dadafc1cb3..5aaf5f24f1 100644 --- a/vlib/v/checker/tests/or_err.out +++ b/vlib/v/checker/tests/or_err.out @@ -1,8 +1,8 @@ -vlib/v/checker/tests/or_err.vv:4:6: error: last statement in the `or {}` block should be an expression of type `&int` or exit parent scope +vlib/v/checker/tests/or_err.vv:4:10: error: last statement in the `or {}` block should be an expression of type `&int` or exit parent scope 2 | return none 3 | } 4 | a := f() or { - | ~~~ + | ~~~~ 5 | {} 6 | } vlib/v/checker/tests/or_err.vv:11:2: error: wrong return type `rune` in the `or {}` block, expected `&int` diff --git a/vlib/v/checker/tests/unexpected_or.out b/vlib/v/checker/tests/unexpected_or.out index b63edf200b..ab1e077c69 100644 --- a/vlib/v/checker/tests/unexpected_or.out +++ b/vlib/v/checker/tests/unexpected_or.out @@ -1,6 +1,6 @@ -vlib/v/checker/tests/unexpected_or.vv:6:6: error: unexpected `or` block, the function `ret_zero` does not return an optional - 4 | +vlib/v/checker/tests/unexpected_or.vv:6:17: error: unexpected `or` block, the function `ret_zero` does not return an optional + 4 | 5 | fn main() { 6 | _ = ret_zero() or { 1 } - | ~~~~~~~~~~ + | ~~~~~~~~ 7 | } diff --git a/vlib/v/checker/tests/unexpected_or_propagate.out b/vlib/v/checker/tests/unexpected_or_propagate.out index 86ab6c233f..208bf88f81 100644 --- a/vlib/v/checker/tests/unexpected_or_propagate.out +++ b/vlib/v/checker/tests/unexpected_or_propagate.out @@ -1,7 +1,7 @@ -vlib/v/checker/tests/unexpected_or_propagate.vv:6:7: error: unexpected `?`, the function `ret_zero`, does not return an optional - 4 | +vlib/v/checker/tests/unexpected_or_propagate.vv:6:17: error: unexpected `?`, the function `ret_zero`, does not return an optional + 4 | 5 | fn opt_fn() ?int { 6 | a := ret_zero()? - | ~~~~~~~~~~ + | ^ 7 | return a 8 | } diff --git a/vlib/v/checker/tests/wrong_propagate_ret_type.out b/vlib/v/checker/tests/wrong_propagate_ret_type.out index ed4f6ca88c..56f329f351 100644 --- a/vlib/v/checker/tests/wrong_propagate_ret_type.out +++ b/vlib/v/checker/tests/wrong_propagate_ret_type.out @@ -1,7 +1,7 @@ -vlib/v/checker/tests/wrong_propagate_ret_type.vv:6:7: error: to propagate the optional call, `opt_call` must itself return an optional - 4 | +vlib/v/checker/tests/wrong_propagate_ret_type.vv:6:17: error: to propagate the optional call, `opt_call` must itself return an optional + 4 | 5 | fn opt_call() int { 6 | a := ret_none()? - | ~~~~~~~~~~ + | ^ 7 | return a 8 | } diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index a24fb6e91f..13cafe18fc 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -54,6 +54,7 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp len: last_pos.pos - first_pos.pos + last_pos.len } mut or_stmts := []ast.Stmt{} + mut or_pos := p.tok.position() if p.tok.kind == .key_orelse { // `foo() or {}`` was_inside_or_expr := p.inside_or_expr @@ -74,6 +75,7 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp }) or_kind = .block or_stmts = p.parse_block_no_scope(false) + or_pos = or_pos.extend(p.prev_tok.position()) p.close_scope() p.inside_or_expr = was_inside_or_expr } @@ -89,37 +91,18 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp fn_name = registered.name } } - /* - call_expr := ast.CallExpr{ - name: fn_name - args: args - mod: fn_mod - pos: pos - language: language - generic_type: generic_type - } - if or_kind != .absent { - return ast.OrExpr2{ - call_expr: call_expr - stmts: or_stmts - kind: or_kind - pos: pos - } - } - return call_expr - */ return ast.CallExpr{ name: fn_name args: args mod: fn_mod pos: pos language: language + generic_type: generic_type or_block: ast.OrExpr{ stmts: or_stmts kind: or_kind - pos: pos + pos: or_pos } - generic_type: generic_type } } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index dca6afc601..4eee4d451d 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1238,6 +1238,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr { p.check(.rpar) mut or_stmts := []ast.Stmt{} mut or_kind := ast.OrKind.absent + mut or_pos := p.tok.position() if p.tok.kind == .key_orelse { p.next() p.open_scope() @@ -1255,6 +1256,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr { }) or_kind = .block or_stmts = p.parse_block_no_scope(false) + or_pos = or_pos.extend(p.prev_tok.position()) p.close_scope() } // `foo()?` @@ -1278,7 +1280,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr { or_block: ast.OrExpr{ stmts: or_stmts kind: or_kind - pos: pos + pos: or_pos } } if is_filter || field_name == 'sort' { diff --git a/vlib/v/parser/pratt.v b/vlib/v/parser/pratt.v index 084e6b3c73..e321becd2c 100644 --- a/vlib/v/parser/pratt.v +++ b/vlib/v/parser/pratt.v @@ -355,6 +355,7 @@ fn (mut p Parser) prefix_expr() ast.PrefixExpr { } mut or_stmts := []ast.Stmt{} mut or_kind := ast.OrKind.absent + mut or_pos := p.tok.position() // allow `x := <-ch or {...}` to handle closed channel if op == .arrow { if p.tok.kind == .key_orelse { @@ -374,6 +375,7 @@ fn (mut p Parser) prefix_expr() ast.PrefixExpr { }) or_kind = .block or_stmts = p.parse_block_no_scope(false) + or_pos = or_pos.extend(p.prev_tok.position()) p.close_scope() } if p.tok.kind == .question { @@ -388,7 +390,7 @@ fn (mut p Parser) prefix_expr() ast.PrefixExpr { or_block: ast.OrExpr{ stmts: or_stmts kind: or_kind - pos: pos + pos: or_pos } } } diff --git a/vlib/v/parser/tests/prefix_first.out b/vlib/v/parser/tests/prefix_first.out index c5f5b27c35..e91f5a4d86 100644 --- a/vlib/v/parser/tests/prefix_first.out +++ b/vlib/v/parser/tests/prefix_first.out @@ -13,16 +13,16 @@ vlib/v/parser/tests/prefix_first.vv:26:3: warning: move infix `&` operator befor 27 | } 28 | } vlib/v/parser/tests/prefix_first.vv:13:6: error: `if` expression requires an expression as the last statement of every branch - 11 | + 11 | 12 | // later this should compile correctly 13 | _ = if true { | ~~~~~~~ 14 | v = 1 15 | -1 -vlib/v/parser/tests/prefix_first.vv:24:6: error: last statement in the `or {}` block should be an expression of type `&int` or exit parent scope +vlib/v/parser/tests/prefix_first.vv:24:12: error: last statement in the `or {}` block should be an expression of type `&int` or exit parent scope 22 | // later this should compile correctly 23 | v := 3 24 | _ = opt() or { - | ~~~~~ + | ~~~~ 25 | _ = 1 26 | &v