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

parser: add more precise errors, for fn (p Point) += (q Point) Point { (#17167)

This commit is contained in:
Swastik Baranwal 2023-01-31 13:06:33 +05:30 committed by GitHub
parent 0d04104112
commit b487c9d38e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 75 additions and 3 deletions

View File

@ -280,6 +280,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
p.fn_language = language
}
mut name := ''
mut type_sym := p.table.sym(rec.typ)
name_pos := p.tok.pos()
if p.tok.kind == .name {
// TODO high order fn
@ -292,12 +293,11 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
scope: 0
}
}
type_sym := p.table.sym(rec.typ)
if is_method {
mut is_duplicate := type_sym.has_method(name)
// make sure this is a normal method and not an interface method
if type_sym.kind == .interface_ && is_duplicate {
if type_sym.info is ast.Interface {
if mut type_sym.info is ast.Interface {
// if the method is in info then its an interface method
is_duplicate = !type_sym.info.has_method(name)
}
@ -327,6 +327,19 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
} else if p.tok.kind in [.ne, .gt, .ge, .le] && p.peek_tok.kind == .lpar {
p.error_with_pos('cannot overload `!=`, `>`, `<=` and `>=` as they are auto generated from `==` and`<`',
p.tok.pos())
} else if p.tok.kind in [.plus_assign, .minus_assign, .div_assign, .mult_assign, .mod_assign] {
extracted_op := match p.tok.kind {
.plus_assign { '+' }
.minus_assign { '-' }
.div_assign { '/' }
.mod_assign { '%' }
.mult_assign { '*' }
else { 'unknown op' }
}
if type_sym.has_method(extracted_op) {
p.error('cannot overload `${p.tok.kind}`, operator is implicitly overloaded because the `${extracted_op}` operator is overloaded')
}
p.error('cannot overload `${p.tok.kind}`, overload `${extracted_op}` and `${p.tok.kind}` will be automatically generated')
} else {
p.error_with_pos('expecting method name', p.tok.pos())
return ast.FnDecl{
@ -412,7 +425,6 @@ run them via `v file.v` instead',
}
// Register
if is_method {
mut type_sym := p.table.sym(rec.typ)
// Do not allow to modify / add methods to types from other modules
// 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

View File

@ -0,0 +1,7 @@
vlib/v/parser/tests/argumented_op_overloading_fn_decl_err.vv:10:14: error: cannot overload `+=`, overload `+` and `+=` will be automatically generated
8 | }
9 |
10 | fn (p Point) += (q Point) Point {
| ~~
11 | return Point{p.x + q.x, p.y + q.y}
12 | }

View File

@ -0,0 +1,21 @@
struct Point {
x i64
y i64
}
fn (p Point) foo() {
println(p.x)
}
fn (p Point) += (q Point) Point {
return Point{p.x + q.x, p.y + q.y}
}
fn main() {
mut p := Point{1, 2}
q := Point{3, 4}
p += q
p -= q
println(p)
}

View File

@ -0,0 +1,7 @@
vlib/v/parser/tests/argumented_op_overloading_fn_op_overloaded_decl_err.vv:14:14: error: cannot overload `+=`, operator is implicitly overloaded because the `+` operator is overloaded
12 | }
13 |
14 | fn (p Point) += (q Point) Point {
| ~~
15 | return Point{p.x + q.x, p.y + q.y}
16 | }

View File

@ -0,0 +1,25 @@
struct Point {
x i64
y i64
}
fn (p Point) foo() {
println(p.x)
}
fn (p Point) + (q Point) Point {
return Point{p.x + q.x, p.y + q.y}
}
fn (p Point) += (q Point) Point {
return Point{p.x + q.x, p.y + q.y}
}
fn main() {
mut p := Point{1, 2}
q := Point{3, 4}
p += q
p -= q
println(p)
}