mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: allow + operator overrides for type aliases
This commit is contained in:
parent
2a03d22a37
commit
d75c62b806
@ -519,6 +519,13 @@ fn (mut c Checker) check_shift(mut node ast.InfixExpr, left_type_ ast.Type, righ
|
|||||||
return left_type
|
return left_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut c Checker) promote_keeping_aliases(left_type ast.Type, right_type ast.Type, left_kind ast.Kind, right_kind ast.Kind) ast.Type {
|
||||||
|
if left_type == right_type && left_kind == .alias && right_kind == .alias {
|
||||||
|
return left_type
|
||||||
|
}
|
||||||
|
return c.promote(left_type, right_type)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut c Checker) promote(left_type ast.Type, right_type ast.Type) ast.Type {
|
pub fn (mut c Checker) promote(left_type ast.Type, right_type ast.Type) ast.Type {
|
||||||
if left_type.is_any_kind_of_pointer() {
|
if left_type.is_any_kind_of_pointer() {
|
||||||
if right_type.is_int() || c.pref.translated {
|
if right_type.is_int() || c.pref.translated {
|
||||||
|
@ -45,9 +45,15 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||||||
&& node.op in [.plus, .minus, .mul, .div, .mod, .xor, .amp, .pipe] {
|
&& node.op in [.plus, .minus, .mul, .div, .mod, .xor, .amp, .pipe] {
|
||||||
if !c.pref.translated && ((right_type.is_any_kind_of_pointer() && node.op != .minus)
|
if !c.pref.translated && ((right_type.is_any_kind_of_pointer() && node.op != .minus)
|
||||||
|| (!right_type.is_any_kind_of_pointer() && node.op !in [.plus, .minus])) {
|
|| (!right_type.is_any_kind_of_pointer() && node.op !in [.plus, .minus])) {
|
||||||
left_name := c.table.type_to_str(left_type)
|
if _ := left_sym.find_method(node.op.str()) {
|
||||||
right_name := c.table.type_to_str(right_type)
|
if left_sym.kind == .alias && right_sym.kind == .alias {
|
||||||
c.error('invalid operator `$node.op` to `$left_name` and `$right_name`', left_right_pos)
|
// allow an explicit operator override `fn (x &AliasType) OP (y &AliasType) &AliasType {`
|
||||||
|
} else {
|
||||||
|
c.invalid_operator_error(node.op, left_type, right_type, left_right_pos)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.invalid_operator_error(node.op, left_type, right_type, left_right_pos)
|
||||||
|
}
|
||||||
} else if node.op in [.plus, .minus] {
|
} else if node.op in [.plus, .minus] {
|
||||||
if !c.inside_unsafe && !node.left.is_auto_deref_var() && !node.right.is_auto_deref_var() {
|
if !c.inside_unsafe && !node.left.is_auto_deref_var() && !node.right.is_auto_deref_var() {
|
||||||
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', left_right_pos)
|
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', left_right_pos)
|
||||||
@ -89,6 +95,7 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||||||
(left_sym.kind == .alias && right_sym.kind in [.struct_, .array, .sum_type])
|
(left_sym.kind == .alias && right_sym.kind in [.struct_, .array, .sum_type])
|
||||||
|| (right_sym.kind == .alias && left_sym.kind in [.struct_, .array, .sum_type])
|
|| (right_sym.kind == .alias && left_sym.kind in [.struct_, .array, .sum_type])
|
||||||
if is_mismatch {
|
if is_mismatch {
|
||||||
|
c.add_error_detail('left type: `${c.table.type_to_str(left_type)}` vs right type: `${c.table.type_to_str(right_type)}`')
|
||||||
c.error('possible type mismatch of compared values of `$node.op` operation',
|
c.error('possible type mismatch of compared values of `$node.op` operation',
|
||||||
left_right_pos)
|
left_right_pos)
|
||||||
} else if left_type in ast.integer_type_idxs && right_type in ast.integer_type_idxs {
|
} else if left_type in ast.integer_type_idxs && right_type in ast.integer_type_idxs {
|
||||||
@ -274,7 +281,8 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||||||
} else {
|
} else {
|
||||||
unaliased_left_type := c.table.unalias_num_type(left_type)
|
unaliased_left_type := c.table.unalias_num_type(left_type)
|
||||||
unalias_right_type := c.table.unalias_num_type(right_type)
|
unalias_right_type := c.table.unalias_num_type(right_type)
|
||||||
mut promoted_type := c.promote(unaliased_left_type, unalias_right_type)
|
mut promoted_type := c.promote_keeping_aliases(unaliased_left_type, unalias_right_type,
|
||||||
|
left_sym.kind, right_sym.kind)
|
||||||
// substract pointers is allowed in unsafe block
|
// substract pointers is allowed in unsafe block
|
||||||
is_allowed_pointer_arithmetic := left_type.is_any_kind_of_pointer()
|
is_allowed_pointer_arithmetic := left_type.is_any_kind_of_pointer()
|
||||||
&& right_type.is_any_kind_of_pointer() && node.op == .minus
|
&& right_type.is_any_kind_of_pointer() && node.op == .minus
|
||||||
@ -657,3 +665,9 @@ fn (mut c Checker) check_div_mod_by_zero(expr ast.Expr, op_kind token.Kind) {
|
|||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut c Checker) invalid_operator_error(op token.Kind, left_type ast.Type, right_type ast.Type, pos token.Pos) {
|
||||||
|
left_name := c.table.type_to_str(left_type)
|
||||||
|
right_name := c.table.type_to_str(right_type)
|
||||||
|
c.error('invalid operator `$op` to `$left_name` and `$right_name`', pos)
|
||||||
|
}
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
vlib/v/checker/tests/alias_array_possible_type_mismatch.vv:11:7: error: possible type mismatch of compared values of `==` operation
|
||||||
|
9 | mut a := new_vector(12, 4.5, 6.7, 6)
|
||||||
|
10 | dump(a)
|
||||||
|
11 | x := a == []f64{}
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
12 | dump(x)
|
||||||
|
13 | }
|
||||||
|
Details: left type: `main.Vector` vs right type: `[]f64`
|
13
vlib/v/checker/tests/alias_array_possible_type_mismatch.vv
Normal file
13
vlib/v/checker/tests/alias_array_possible_type_mismatch.vv
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
type Vector = []f64
|
||||||
|
type Another = []f64
|
||||||
|
|
||||||
|
fn new_vector(x f64, y f64, z f64, w f64) Vector {
|
||||||
|
return Vector([x, y, z, w])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_alias_array_plus_overload() {
|
||||||
|
mut a := new_vector(12, 4.5, 6.7, 6)
|
||||||
|
dump(a)
|
||||||
|
x := a == []f64{}
|
||||||
|
dump(x)
|
||||||
|
}
|
@ -5,3 +5,4 @@ vlib/v/checker/tests/comparing_typesymbol_to_a_type_should_not_compile.vv:12:7:
|
|||||||
| ~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
13 | println(typeof(isym).name)
|
13 | println(typeof(isym).name)
|
||||||
14 | println(typeof(ast.string_type).name)
|
14 | println(typeof(ast.string_type).name)
|
||||||
|
Details: left type: `&ast.TypeSymbol` vs right type: `ast.Type`
|
||||||
|
@ -33,6 +33,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:17:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~
|
||||||
18 | println(AAaa{0} == Aaa{0})
|
18 | println(AAaa{0} == Aaa{0})
|
||||||
19 | println(AAaa{1} != Aaa{1})
|
19 | println(AAaa{1} != Aaa{1})
|
||||||
|
Details: left type: `main.Aaa` vs right type: `main.AAaa`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:18:10: error: possible type mismatch of compared values of `==` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:18:10: error: possible type mismatch of compared values of `==` operation
|
||||||
16 |
|
16 |
|
||||||
17 | println(Aaa{0} == AAaa{0})
|
17 | println(Aaa{0} == AAaa{0})
|
||||||
@ -40,6 +41,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:18:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~
|
||||||
19 | println(AAaa{1} != Aaa{1})
|
19 | println(AAaa{1} != Aaa{1})
|
||||||
20 | println(Aaa{1} != AAaa{1})
|
20 | println(Aaa{1} != AAaa{1})
|
||||||
|
Details: left type: `main.AAaa` vs right type: `main.Aaa`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:19:10: error: possible type mismatch of compared values of `!=` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:19:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
17 | println(Aaa{0} == AAaa{0})
|
17 | println(Aaa{0} == AAaa{0})
|
||||||
18 | println(AAaa{0} == Aaa{0})
|
18 | println(AAaa{0} == Aaa{0})
|
||||||
@ -47,6 +49,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:19:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~
|
||||||
20 | println(Aaa{1} != AAaa{1})
|
20 | println(Aaa{1} != AAaa{1})
|
||||||
21 |
|
21 |
|
||||||
|
Details: left type: `main.AAaa` vs right type: `main.Aaa`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:20:10: error: possible type mismatch of compared values of `!=` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:20:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
18 | println(AAaa{0} == Aaa{0})
|
18 | println(AAaa{0} == Aaa{0})
|
||||||
19 | println(AAaa{1} != Aaa{1})
|
19 | println(AAaa{1} != Aaa{1})
|
||||||
@ -54,6 +57,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:20:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~
|
||||||
21 |
|
21 |
|
||||||
22 | arr := Arr([0])
|
22 | arr := Arr([0])
|
||||||
|
Details: left type: `main.Aaa` vs right type: `main.AAaa`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:23:10: error: possible type mismatch of compared values of `==` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:23:10: error: possible type mismatch of compared values of `==` operation
|
||||||
21 |
|
21 |
|
||||||
22 | arr := Arr([0])
|
22 | arr := Arr([0])
|
||||||
@ -61,6 +65,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:23:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~
|
| ~~~~~~~~~~
|
||||||
24 | println([1] == arr)
|
24 | println([1] == arr)
|
||||||
25 | println(arr != [0])
|
25 | println(arr != [0])
|
||||||
|
Details: left type: `main.Arr` vs right type: `[]int`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:24:10: error: possible type mismatch of compared values of `==` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:24:10: error: possible type mismatch of compared values of `==` operation
|
||||||
22 | arr := Arr([0])
|
22 | arr := Arr([0])
|
||||||
23 | println(arr == [0])
|
23 | println(arr == [0])
|
||||||
@ -68,6 +73,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:24:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~
|
| ~~~~~~~~~~
|
||||||
25 | println(arr != [0])
|
25 | println(arr != [0])
|
||||||
26 | println([1] != arr)
|
26 | println([1] != arr)
|
||||||
|
Details: left type: `[]int` vs right type: `main.Arr`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:25:10: error: possible type mismatch of compared values of `!=` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:25:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
23 | println(arr == [0])
|
23 | println(arr == [0])
|
||||||
24 | println([1] == arr)
|
24 | println([1] == arr)
|
||||||
@ -75,6 +81,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:25:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~
|
| ~~~~~~~~~~
|
||||||
26 | println([1] != arr)
|
26 | println([1] != arr)
|
||||||
27 |
|
27 |
|
||||||
|
Details: left type: `main.Arr` vs right type: `[]int`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:26:10: error: possible type mismatch of compared values of `!=` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:26:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
24 | println([1] == arr)
|
24 | println([1] == arr)
|
||||||
25 | println(arr != [0])
|
25 | println(arr != [0])
|
||||||
@ -82,6 +89,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:26:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~
|
| ~~~~~~~~~~
|
||||||
27 |
|
27 |
|
||||||
28 | arr_aaa := ArrAaa(arr)
|
28 | arr_aaa := ArrAaa(arr)
|
||||||
|
Details: left type: `[]int` vs right type: `main.Arr`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:29:10: error: possible type mismatch of compared values of `==` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:29:10: error: possible type mismatch of compared values of `==` operation
|
||||||
27 |
|
27 |
|
||||||
28 | arr_aaa := ArrAaa(arr)
|
28 | arr_aaa := ArrAaa(arr)
|
||||||
@ -89,6 +97,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:29:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~
|
||||||
30 | println(arr == arr_aaa)
|
30 | println(arr == arr_aaa)
|
||||||
31 | println(arr_aaa != arr)
|
31 | println(arr_aaa != arr)
|
||||||
|
Details: left type: `main.ArrAaa` vs right type: `main.Arr`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:30:10: error: possible type mismatch of compared values of `==` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:30:10: error: possible type mismatch of compared values of `==` operation
|
||||||
28 | arr_aaa := ArrAaa(arr)
|
28 | arr_aaa := ArrAaa(arr)
|
||||||
29 | println(arr_aaa == arr)
|
29 | println(arr_aaa == arr)
|
||||||
@ -96,6 +105,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:30:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~
|
||||||
31 | println(arr_aaa != arr)
|
31 | println(arr_aaa != arr)
|
||||||
32 | println(arr != arr_aaa)
|
32 | println(arr != arr_aaa)
|
||||||
|
Details: left type: `main.Arr` vs right type: `main.ArrAaa`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:31:10: error: possible type mismatch of compared values of `!=` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:31:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
29 | println(arr_aaa == arr)
|
29 | println(arr_aaa == arr)
|
||||||
30 | println(arr == arr_aaa)
|
30 | println(arr == arr_aaa)
|
||||||
@ -103,6 +113,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:31:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~
|
||||||
32 | println(arr != arr_aaa)
|
32 | println(arr != arr_aaa)
|
||||||
33 |
|
33 |
|
||||||
|
Details: left type: `main.ArrAaa` vs right type: `main.Arr`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:32:10: error: possible type mismatch of compared values of `!=` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:32:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
30 | println(arr == arr_aaa)
|
30 | println(arr == arr_aaa)
|
||||||
31 | println(arr_aaa != arr)
|
31 | println(arr_aaa != arr)
|
||||||
@ -110,6 +121,7 @@ vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:32:10: error: possible type mism
|
|||||||
| ~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~
|
||||||
33 |
|
33 |
|
||||||
34 | println(arr_aaa == [0])
|
34 | println(arr_aaa == [0])
|
||||||
|
Details: left type: `main.Arr` vs right type: `main.ArrAaa`
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:34:10: error: infix expr: cannot use `[]int` (right expression) as `ArrAaa`
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:34:10: error: infix expr: cannot use `[]int` (right expression) as `ArrAaa`
|
||||||
32 | println(arr != arr_aaa)
|
32 | println(arr != arr_aaa)
|
||||||
33 |
|
33 |
|
||||||
|
37
vlib/v/tests/alias_array_plus_operator_test.v
Normal file
37
vlib/v/tests/alias_array_plus_operator_test.v
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
type Vector = []f64
|
||||||
|
|
||||||
|
[heap]
|
||||||
|
struct HeapArray {
|
||||||
|
mut:
|
||||||
|
data []f64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_vector(x f64, y f64, z f64, w f64) &Vector {
|
||||||
|
a := HeapArray{
|
||||||
|
data: [x, y, z, w]
|
||||||
|
}
|
||||||
|
return &Vector(&a.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (a &Vector) + (b &Vector) &Vector {
|
||||||
|
mut res := HeapArray{
|
||||||
|
data: []f64{len: a.len}
|
||||||
|
}
|
||||||
|
for i := 0; i < a.len; i++ {
|
||||||
|
res.data[i] = (*a)[i] + (*b)[i]
|
||||||
|
}
|
||||||
|
return &Vector(&res.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_alias_array_plus_overload() {
|
||||||
|
mut a := new_vector(12, 4.5, 6.7, 6)
|
||||||
|
b := new_vector(12, 4.5, 6.7, 6)
|
||||||
|
dump(a)
|
||||||
|
dump(b)
|
||||||
|
c := a + b
|
||||||
|
dump(c)
|
||||||
|
assert *c == Vector([f64(24), 9, 13.4, 12])
|
||||||
|
a = a + b
|
||||||
|
assert a.str() == c.str()
|
||||||
|
dump(a)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user