diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index adb9d18ea6..af887db1bb 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -259,33 +259,34 @@ pub mut: pub struct FnDecl { pub: - name string - mod string - params []table.Param - is_deprecated bool - is_pub bool - is_variadic bool - is_anon bool - receiver Field - receiver_pos token.Position - is_method bool - method_idx int - rec_mut bool // is receiver mutable - rec_share table.ShareType - language table.Language - no_body bool // just a definition `fn C.malloc()` - is_builtin bool // this function is defined in builtin/strconv - pos token.Position - body_pos token.Position - file string - is_generic bool - is_direct_arr bool // direct array access - attrs []table.Attr + name string + mod string + params []table.Param + is_deprecated bool + is_pub bool + is_variadic bool + is_anon bool + receiver Field + receiver_pos token.Position + is_method bool + method_type_pos token.Position + method_idx int + rec_mut bool // is receiver mutable + rec_share table.ShareType + language table.Language + no_body bool // just a definition `fn C.malloc()` + is_builtin bool // this function is defined in builtin/strconv + pos token.Position + body_pos token.Position + file string + is_generic bool + is_direct_arr bool // direct array access + attrs []table.Attr pub mut: - stmts []Stmt - return_type table.Type - comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl - source_file &File = 0 + stmts []Stmt + return_type table.Type + comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl + source_file &File = 0 } // break, continue diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index c4001ad602..1bdadcff4c 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -4573,7 +4573,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { for arg in node.params { sym := c.table.get_type_symbol(arg.typ) if sym.kind == .placeholder { - c.error('unknown type `$sym.name`', node.pos) + c.error('unknown type `$sym.name`', node.method_type_pos) } } } diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 1d77a66147..3edc217a64 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -164,6 +164,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { mut rec_name := '' mut is_method := false mut receiver_pos := token.Position{} + mut rec_type_pos := token.Position{} mut rec_type := table.void_type mut rec_mut := false mut params := []table.Param{} @@ -194,7 +195,9 @@ fn (mut p Parser) fn_decl() ast.FnDecl { // } // TODO: talk to alex, should mut be parsed with the type like this? // or should it be a property of the arg, like this ptr/mut becomes indistinguishable + rec_type_pos = p.tok.position() rec_type = p.parse_type_with_mut(rec_mut) + rec_type_pos = rec_type_pos.extend(p.prev_tok.position()) if is_amp && rec_mut { p.error('use `(mut f Foo)` or `(f &Foo)` instead of `(mut f &Foo)`') return ast.FnDecl{} @@ -273,7 +276,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl { // arrays/maps dont belong to a module only their element types do // we could also check if kind is .array, .array_fixed, .map instead of mod.len if type_sym.mod.len > 0 && type_sym.mod != p.mod && type_sym.language == .v { - p.error('cannot define new methods on non-local type $type_sym.name') + p.error_with_pos('cannot define new methods on non-local type $type_sym.name', + rec_type_pos) return ast.FnDecl{} } // p.warn('reg method $type_sym.name . $name ()') @@ -346,6 +350,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { } receiver_pos: receiver_pos is_method: is_method + method_type_pos: rec_type_pos method_idx: type_sym_method_idx rec_mut: rec_mut language: language