vxx / vlib / v / tests / interfaces / interface_variadic_test.v
160 lines · 134 sloc · 3.5 KB · d0637eb51bc2153560c5bd3b4795b0b5a4f425ba
Raw
1interface Element {
2 method(params ...f64) string
3}
4
5struct Foo {}
6
7fn (f &Foo) method(params ...f64) string {
8 return params.str()
9}
10
11fn test_variadic_array_decompose() {
12 mut a := []Element{}
13 a << Foo{}
14
15 input := [0.0, 1.0]
16 assert a[0].method(...input) == '[0.0, 1.0]'
17 assert a[0].method(...[0.0, 1.0]) == '[0.0, 1.0]'
18}
19
20fn test_variadic_multiple_args() {
21 mut a := []Element{}
22 a << Foo{}
23
24 assert a[0].method(0.0, 1.0) == '[0.0, 1.0]'
25}
26
27interface Animal {}
28
29struct Cat {}
30
31struct Dog {}
32
33fn test_variadic_interface_fn_arg() {
34 c := Cat{}
35 d := Dog{}
36 check_animals(c, d)
37}
38
39// For issue 27326: passing a local variable declared inside a loop to a
40// variadic interface parameter caused a `pointer expected` C error, because
41// the value was promoted to auto-heap at the use site but not at its
42// declaration, producing inconsistent pointer indirection in the generated C.
43interface Value {}
44
45fn collect(params ...Value) int {
46 return params.len
47}
48
49fn test_variadic_interface_arg_declared_in_loop() {
50 mut total := 0
51 for i := 0; i < 3; i++ {
52 id := [u8(1), 2, 3]
53 code := 'hello ${i}'
54 total += collect(id, code)
55 }
56 assert total == 6
57}
58
59type ValueSum = Cat | Dog
60
61// For issue 27326: a variable smartcast via `if x is T` / `match` resolves to a
62// synthetic smartcast scope var, not its real declaration. Promoting that
63// synthetic var to auto-heap instead of the declaration must not desync the
64// pointer indirection when the value is passed to a variadic interface param.
65fn test_variadic_interface_arg_smartcast() {
66 mut total := 0
67 s := ValueSum(Cat{})
68 if s is Cat {
69 total += collect(s)
70 }
71 v := Value(Cat{})
72 if v is Cat {
73 total += collect(v)
74 }
75 match v {
76 Cat { total += collect(v) }
77 else {}
78 }
79
80 assert total == 3
81}
82
83// For issue 27326: a variable that is both declared in a nested scope (a `for`
84// loop body) and smartcast via `if x is T` must still resolve to its real
85// nested declaration, not the synthetic smartcast var nor only the function
86// scope, otherwise the auto-heap promotion desyncs the pointer indirection.
87fn test_variadic_interface_arg_smartcast_in_loop() {
88 mut total := 0
89 for _ in 0 .. 3 {
90 s := ValueSum(Cat{})
91 if s is Cat {
92 total += collect(s)
93 }
94 }
95 for _ in 0 .. 2 {
96 v := Value(Cat{})
97 if v is Cat {
98 total += collect(v)
99 }
100 }
101 assert total == 5
102}
103
104fn maybe_value() ?Cat {
105 return Cat{}
106}
107
108// For issue 27326: an option value unwrapped via an if-guard or `if x != none`
109// and then passed to a variadic interface parameter is auto-heap promoted, so
110// its declaration is emitted as an option pointer. The unwrapped `.data` read
111// at the call site must use the matching pointer indirection (`->data`);
112// previously cgen emitted value-style access and failed C compilation.
113fn test_variadic_interface_arg_option_unwrap() {
114 mut total := 0
115 if x := maybe_value() {
116 total += collect(x)
117 }
118 x := maybe_value()
119 if x != none {
120 total += collect(x)
121 }
122 for _ in 0 .. 2 {
123 y := maybe_value()
124 if y != none {
125 total += collect(y)
126 }
127 }
128 assert total == 4
129}
130
131fn check_animals(animals ...Animal) {
132 assert animals[0] is Cat
133 assert animals[1] is Dog
134}
135
136// For issue: 16286 passing nothing to a variatic parameter on an interface method gives builder error
137interface Bar {
138 get(...int) []int
139}
140
141struct Baz {}
142
143fn (b Baz) get(n ...int) []int {
144 if n.len == 0 {
145 return [-1]
146 } else {
147 return n
148 }
149}
150
151fn test_empty_args_call_interface_methods() {
152 b := Baz{}
153 assert b.get() == [-1]
154
155 b_values := Bar(Baz{})
156 assert b_values.get(1, 2, 3) == [1, 2, 3]
157
158 b_empty := Bar(Baz{})
159 assert b_empty.get() == [-1]
160}
161