mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: relax checks on operators done on aliases of primitives like int, u8, string etc.; add tests (#17029)
This commit is contained in:
parent
269833b72c
commit
92c7e3f7ff
@ -553,7 +553,9 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
right_name := c.table.type_to_str(right_type_unwrapped)
|
||||
parent_sym := c.table.final_sym(left_type_unwrapped)
|
||||
if left_sym.kind == .alias && right_sym.kind != .alias {
|
||||
c.error('mismatched types `${left_name}` and `${right_name}`', node.pos)
|
||||
if !parent_sym.is_primitive() {
|
||||
c.error('mismatched types `${left_name}` and `${right_name}`', node.pos)
|
||||
}
|
||||
}
|
||||
extracted_op := match node.op {
|
||||
.plus_assign { '+' }
|
||||
@ -572,15 +574,14 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
node.pos)
|
||||
}
|
||||
} else {
|
||||
if parent_sym.is_primitive() {
|
||||
c.error('cannot use operator methods on type alias for `${parent_sym.name}`',
|
||||
node.pos)
|
||||
}
|
||||
if left_name == right_name {
|
||||
c.error('undefined operation `${left_name}` ${extracted_op} `${right_name}`',
|
||||
node.pos)
|
||||
} else {
|
||||
c.error('mismatched types `${left_name}` and `${right_name}`', node.pos)
|
||||
if !parent_sym.is_primitive() {
|
||||
if left_name == right_name {
|
||||
c.error('undefined operation `${left_name}` ${extracted_op} `${right_name}`',
|
||||
node.pos)
|
||||
} else {
|
||||
c.error('mismatched types `${left_name}` and `${right_name}`',
|
||||
node.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -301,8 +301,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
} else if node.name in ['<', '=='] && node.return_type != ast.bool_type {
|
||||
c.error('operator comparison methods should return `bool`', node.pos)
|
||||
} else if parent_sym.is_primitive() {
|
||||
c.error('cannot define operator methods on type alias for `${parent_sym.name}`',
|
||||
node.pos)
|
||||
// aliases of primitive types are explicitly allowed
|
||||
} else if receiver_type != param_type {
|
||||
srtype := c.table.type_to_str(receiver_type)
|
||||
sptype := c.table.type_to_str(param_type)
|
||||
|
@ -12,14 +12,7 @@ vlib/v/checker/tests/method_op_alias_err.vv:5:17: error: infix expr: cannot use
|
||||
| ~~~~~~
|
||||
6 | }
|
||||
7 |
|
||||
vlib/v/checker/tests/method_op_alias_err.vv:8:1: error: cannot define operator methods on type alias for `string`
|
||||
6 | }
|
||||
7 |
|
||||
8 | fn (f Foo) * (f1 Foo) Foo {
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
9 | return Foo(f + f1)
|
||||
10 | }
|
||||
vlib/v/checker/tests/method_op_alias_err.vv:14:6: error: mismatched types `Foo` and `string`
|
||||
vlib/v/checker/tests/method_op_alias_err.vv:14:6: error: operator `+` must return `Foo` to be used as an assignment operator
|
||||
12 | fn main() {
|
||||
13 | mut f := Foo('fg')
|
||||
14 | f += 'fg'
|
||||
@ -33,10 +26,3 @@ vlib/v/checker/tests/method_op_alias_err.vv:15:9: error: cannot assign to `f`: e
|
||||
| ~~~~~~~~~
|
||||
16 | f -= Foo('fo')
|
||||
17 | println(f)
|
||||
vlib/v/checker/tests/method_op_alias_err.vv:16:6: error: cannot use operator methods on type alias for `string`
|
||||
14 | f += 'fg'
|
||||
15 | f *= Foo2('2')
|
||||
16 | f -= Foo('fo')
|
||||
| ~~
|
||||
17 | println(f)
|
||||
18 | }
|
||||
|
@ -275,7 +275,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
mut op_overloaded := false
|
||||
mut op_expected_left := ast.Type(0)
|
||||
mut op_expected_right := ast.Type(0)
|
||||
if var_type == ast.string_type_idx && node.op == .plus_assign {
|
||||
if node.op == .plus_assign && unaliased_right_sym.kind == .string {
|
||||
if left is ast.IndexExpr {
|
||||
// a[0] += str => `array_set(&a, 0, &(string[]) {string__plus(...))})`
|
||||
g.expr(left)
|
||||
|
@ -4,16 +4,14 @@ type MyInt = int
|
||||
|
||||
type MyString = string
|
||||
|
||||
fn ok() {
|
||||
assert true
|
||||
}
|
||||
type Foo = string
|
||||
|
||||
// bytes
|
||||
fn test_byte_aliasing() {
|
||||
dump(u8(123))
|
||||
dump(MyByte(u8(123)))
|
||||
dump(u8(MyByte(u8(123))))
|
||||
ok()
|
||||
assert true
|
||||
}
|
||||
|
||||
fn test_pbyte_aliasing() {
|
||||
@ -22,7 +20,7 @@ fn test_pbyte_aliasing() {
|
||||
dump(voidptr(&MyByte(&u8(123))))
|
||||
dump(voidptr(&u8(&MyByte(&u8(123)))))
|
||||
}
|
||||
ok()
|
||||
assert true
|
||||
}
|
||||
|
||||
// ints
|
||||
@ -30,7 +28,7 @@ fn test_int_aliasing() {
|
||||
dump(int(123))
|
||||
dump(int(MyInt(123)))
|
||||
dump(MyInt(int(MyInt(123))))
|
||||
ok()
|
||||
assert true
|
||||
}
|
||||
|
||||
fn test_pint_aliasing() {
|
||||
@ -39,7 +37,7 @@ fn test_pint_aliasing() {
|
||||
dump(voidptr(&MyInt(&int(123456))))
|
||||
dump(voidptr(&int(&MyInt(&int(123456)))))
|
||||
}
|
||||
ok()
|
||||
assert true
|
||||
}
|
||||
|
||||
// strings
|
||||
@ -52,7 +50,7 @@ fn test_string_aliasing() {
|
||||
dump(string(MyString('abc')))
|
||||
dump(MyString(string(MyString('abc'))))
|
||||
}
|
||||
ok()
|
||||
assert true
|
||||
}
|
||||
|
||||
fn test_pstring_aliasing() {
|
||||
@ -62,5 +60,55 @@ fn test_pstring_aliasing() {
|
||||
dump(voidptr(&string(&MyString(&s))))
|
||||
dump(voidptr(&MyString(&string(&MyString(&s)))))
|
||||
}
|
||||
ok()
|
||||
assert true
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
struct MyStruct {
|
||||
mut:
|
||||
a MyInt
|
||||
b MyByte
|
||||
c MyString
|
||||
}
|
||||
|
||||
fn test_modifying_a_struct_using_an_alias_to_int() {
|
||||
mut my_struct := MyStruct{}
|
||||
my_struct.a += 5
|
||||
my_struct.b += 10
|
||||
my_struct.c += 'abc'
|
||||
//
|
||||
my_struct.a += 3
|
||||
my_struct.b += 20
|
||||
my_struct.c += 'def'
|
||||
println(my_struct)
|
||||
//
|
||||
assert my_struct.a == 8
|
||||
assert my_struct.b == 30
|
||||
assert my_struct.c == 'abcdef'
|
||||
}
|
||||
|
||||
fn (f Foo) + (f1 Foo) Foo {
|
||||
return '${f} _+_ ${f1}'
|
||||
}
|
||||
|
||||
fn (f Foo) - (f1 Foo) Foo {
|
||||
return '${f} _-_ ${f1}'
|
||||
}
|
||||
|
||||
fn (f Foo) * (f1 Foo) Foo {
|
||||
return '${f} _*_ ${f1}'
|
||||
}
|
||||
|
||||
fn (f Foo) / (f1 Foo) Foo {
|
||||
return '${f} _/_ ${f1}'
|
||||
}
|
||||
|
||||
fn test_op_overrides_for_string_aliases() {
|
||||
a := Foo('abc')
|
||||
b := Foo('def')
|
||||
assert a + b == 'abc _+_ def'
|
||||
assert a - b == 'abc _-_ def'
|
||||
assert a * b == 'abc _*_ def'
|
||||
assert a / b == 'abc _/_ def'
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user