| 1 | import os |
| 2 | |
| 3 | const vexe = @VEXE |
| 4 | |
| 5 | fn test_skip_unused_prunes_unused_generic_fn_instantiations() { |
| 6 | tmp_dir := os.join_path(os.vtmp_dir(), 'v_issue_26019') |
| 7 | os.mkdir_all(tmp_dir) or { panic(err) } |
| 8 | defer { |
| 9 | os.rmdir_all(tmp_dir) or {} |
| 10 | } |
| 11 | source_path := os.join_path(tmp_dir, 'issue_26019.v') |
| 12 | source := [ |
| 13 | 'module main', |
| 14 | '', |
| 15 | 'fn new[T]() map[u8]T {', |
| 16 | '\tx := map[u8]T{}', |
| 17 | '\treturn x', |
| 18 | '}', |
| 19 | '', |
| 20 | 'fn not_used_fn() map[u8]int {', |
| 21 | '\tx := new[int]()', |
| 22 | '\treturn x', |
| 23 | '}', |
| 24 | '', |
| 25 | 'fn main() {', |
| 26 | '\tx := new[u32]()', |
| 27 | '\tdump(x)', |
| 28 | '}', |
| 29 | ].join('\n') |
| 30 | os.write_file(source_path, source) or { panic(err) } |
| 31 | res := os.execute('${os.quoted_path(vexe)} -o - ${os.quoted_path(source_path)}') |
| 32 | if res.exit_code != 0 { |
| 33 | panic(res.output) |
| 34 | } |
| 35 | assert res.output.contains('VV_LOC Map_u8_u32 main__new_T_u32(void)') |
| 36 | assert !res.output.contains('VV_LOC Map_u8_int main__new_T_int(void)') |
| 37 | } |
| 38 | |
| 39 | fn test_skip_unused_does_not_emit_impl_methods_for_interface_extensions() { |
| 40 | tmp_dir := os.join_path(os.vtmp_dir(), 'v_skip_unused_interface_extension_collision') |
| 41 | os.mkdir_all(tmp_dir) or { panic(err) } |
| 42 | defer { |
| 43 | os.rmdir_all(tmp_dir) or {} |
| 44 | } |
| 45 | source_path := os.join_path(tmp_dir, 'interface_extension_collision.v') |
| 46 | source := [ |
| 47 | 'module main', |
| 48 | '', |
| 49 | 'import crypto.internal.subtle', |
| 50 | '', |
| 51 | 'interface Elem {}', |
| 52 | '', |
| 53 | 'struct Thing {}', |
| 54 | '', |
| 55 | 'struct Holder {', |
| 56 | '\titems []Elem', |
| 57 | '}', |
| 58 | '', |
| 59 | 'fn (el Elem) equal(_ Elem) bool {', |
| 60 | '\treturn true', |
| 61 | '}', |
| 62 | '', |
| 63 | 'fn (t Thing) equal(_ Thing) bool {', |
| 64 | '\treturn subtle.constant_time_compare([u8(1)], [u8(1)]) == 1', |
| 65 | '}', |
| 66 | '', |
| 67 | 'fn (h Holder) ok() bool {', |
| 68 | '\tfor i, item in h.items {', |
| 69 | '\t\tfor j, obj in h.items {', |
| 70 | '\t\t\tif i == j {', |
| 71 | '\t\t\t\treturn item.equal(obj)', |
| 72 | '\t\t\t}', |
| 73 | '\t\t}', |
| 74 | '\t}', |
| 75 | '\treturn false', |
| 76 | '}', |
| 77 | '', |
| 78 | 'fn main() {', |
| 79 | '\th := Holder{items: [Elem(Thing{}), Elem(Thing{})]}', |
| 80 | '\tprintln(h.ok())', |
| 81 | '}', |
| 82 | ].join('\n') |
| 83 | os.write_file(source_path, source) or { panic(err) } |
| 84 | res := os.execute('${os.quoted_path(vexe)} -o - ${os.quoted_path(source_path)}') |
| 85 | if res.exit_code != 0 { |
| 86 | panic(res.output) |
| 87 | } |
| 88 | assert res.output.contains('VV_LOC bool main__Elem_equal(') |
| 89 | assert !res.output.contains('main__Thing_equal(') |
| 90 | } |
| 91 | |
| 92 | fn test_skip_unused_keeps_json2_embedded_struct_decode_helpers() { |
| 93 | tmp_dir := os.join_path(os.vtmp_dir(), 'v_issue_26928') |
| 94 | os.mkdir_all(tmp_dir) or { panic(err) } |
| 95 | defer { |
| 96 | os.rmdir_all(tmp_dir) or {} |
| 97 | } |
| 98 | source_path := os.join_path(tmp_dir, 'issue_26928.v') |
| 99 | source := [ |
| 100 | 'module main', |
| 101 | '', |
| 102 | 'import time', |
| 103 | 'import x.json2', |
| 104 | '', |
| 105 | 'struct Meta {', |
| 106 | '\tcreated_at ?time.Time', |
| 107 | '}', |
| 108 | '', |
| 109 | 'struct Req {', |
| 110 | '\tMeta', |
| 111 | '\tname string', |
| 112 | '}', |
| 113 | '', |
| 114 | 'fn main() {', |
| 115 | '\t_ := json2.decode[Req](\'{"name":"x"}\') or { panic(err) }', |
| 116 | '}', |
| 117 | ].join('\n') |
| 118 | os.write_file(source_path, source) or { panic(err) } |
| 119 | res := os.execute('${os.quoted_path(vexe)} -w -o - ${os.quoted_path(source_path)}') |
| 120 | if res.exit_code != 0 { |
| 121 | panic(res.output) |
| 122 | } |
| 123 | assert res.output.contains('x__json2__decode_struct_key_T_main__Req') |
| 124 | assert res.output.contains('x__json2__check_required_struct_fields_T_main__Req') |
| 125 | assert res.output.contains('x__json2__create_value_from_optional_T_time__Time') |
| 126 | } |
| 127 | |
| 128 | fn test_skip_unused_marks_dependencies_inside_generic_anon_fns() { |
| 129 | tmp_dir := os.join_path(os.vtmp_dir(), 'v_generic_anon_fn_dependencies') |
| 130 | os.mkdir_all(tmp_dir) or { panic(err) } |
| 131 | defer { |
| 132 | os.rmdir_all(tmp_dir) or {} |
| 133 | } |
| 134 | source_path := os.join_path(tmp_dir, 'generic_anon_fn_dependencies.v') |
| 135 | binary_path := os.join_path(tmp_dir, 'generic_anon_fn_dependencies') |
| 136 | source := [ |
| 137 | 'module main', |
| 138 | '', |
| 139 | 'struct Holder[T] {', |
| 140 | '\tdata []T', |
| 141 | '}', |
| 142 | '', |
| 143 | 'fn (h &Holder[T]) nmap[T](others []&Holder[T], f fn ([]T) T) T {', |
| 144 | '\treturn f([h.data[0], others[0].data[0]])', |
| 145 | '}', |
| 146 | '', |
| 147 | 'fn (a &Holder[T]) subtract[T](b &Holder[T]) T {', |
| 148 | '\treturn a.nmap([b], fn [T] (xs []T) T {', |
| 149 | '\t\tx := xs[0]', |
| 150 | '\t\ty := xs[1]', |
| 151 | '\t\t$if T is string {', |
| 152 | "\t\t\treturn x.replace(y, '')", |
| 153 | '\t\t} $else {', |
| 154 | '\t\t\treturn x - y', |
| 155 | '\t\t}', |
| 156 | '\t})', |
| 157 | '}', |
| 158 | '', |
| 159 | 'fn unused_string() {', |
| 160 | "\ta := &Holder[string]{data: ['abc']}", |
| 161 | "\tb := &Holder[string]{data: ['b']}", |
| 162 | '\tprintln(a.subtract(b))', |
| 163 | '}', |
| 164 | '', |
| 165 | 'fn main() {', |
| 166 | '\ta := &Holder[int]{data: [1]}', |
| 167 | '\tb := &Holder[int]{data: [2]}', |
| 168 | '\tprintln(a.subtract(b))', |
| 169 | '}', |
| 170 | ].join('\n') |
| 171 | os.write_file(source_path, source) or { panic(err) } |
| 172 | res := |
| 173 | os.execute('${os.quoted_path(vexe)} -d no_backtrace -o ${os.quoted_path(binary_path)} ${os.quoted_path(source_path)}') |
| 174 | if res.exit_code != 0 { |
| 175 | panic(res.output) |
| 176 | } |
| 177 | } |
| 178 | |