Skip to content

Commit b47c118

Browse files
author
Kevin Stenerson
committed
v3: fix -autofree on literal-only programs
1 parent bbbfb33 commit b47c118

4 files changed

Lines changed: 50 additions & 0 deletions

File tree

.github/workflows/macos_ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ jobs:
206206
run: v run ci/macos_ci.vsh self_tests
207207
- name: Build examples
208208
run: v run ci/macos_ci.vsh build_examples
209+
- name: Build hello_world with -autofree
210+
run: v run ci/macos_ci.vsh build_hello_world_autofree
209211
- name: Build tetris with -autofree
210212
run: v run ci/macos_ci.vsh build_tetris_autofree
211213
- name: Build blog tutorial with -autofree

ci/macos_ci.vsh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ fn build_examples_v_compiled_with_tcc() {
7777
}
7878
}
7979
80+
fn build_hello_world_autofree() {
81+
// The smallest possible program. Its body is only literal `println` calls, which
82+
// is its own code path through markused, so the larger `-autofree` builds below
83+
// do not cover it.
84+
exec('v -autofree -o hello_world examples/hello_world.v')
85+
exec('./hello_world')
86+
}
87+
8088
fn build_tetris_autofree() {
8189
exec('v -autofree -o tetris examples/tetris/tetris.v')
8290
}
@@ -149,6 +157,7 @@ const all_tasks = {
149157
'test_pure_v_math_module': Task{test_pure_v_math_module, 'Test pure V math module'}
150158
'self_tests': Task{self_tests, 'Self tests'}
151159
'build_examples': Task{build_examples, 'Build examples'}
160+
'build_hello_world_autofree': Task{build_hello_world_autofree, 'Build hello_world with -autofree'}
152161
'build_tetris_autofree': Task{build_tetris_autofree, 'Build tetris with -autofree'}
153162
'build_blog_autofree': Task{build_blog_autofree, 'Build blog tutorial with -autofree'}
154163
'build_examples_prod': Task{build_examples_prod, 'Build examples with -prod'}

vlib/v3/markused/markused.v

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,20 @@ fn mark_used_with_test_files(a &flat.FlatAst, tc &types.TypeChecker, test_files
445445
for seed in ['builtin.none__', 'builtin.error_sentinel'] {
446446
enqueue(seed, mut used, mut queue)
447447
}
448+
// The synthesized `_result` destructor releases the concrete object behind a
449+
// failed result's IError, so it names the destructor of every IError
450+
// implementer. Cgen emits that helper for every ownership build, and those
451+
// calls have no source-AST call site either, so root them beside the
452+
// sentinels. This must stay outside the `trivial_literal_output` fast path
453+
// below: the helper is emitted there too, and `MessageError.free` is what a
454+
// `-autofree` build of a literal-only program would otherwise call without a
455+
// definition.
456+
ierror_destructor := if tc.autofree_mode { 'free' } else { 'drop' }
457+
for impl in tc.ierror_impl_names() {
458+
for alias in interface_implementer_method_aliases(impl, ierror_destructor, tc) {
459+
enqueue(alias, mut used, mut queue)
460+
}
461+
}
448462
}
449463
enqueue_main_module_roots(fn_decls, mut used, mut queue)
450464
if use_prepared {

vlib/v3/tests/ownership/ownership_test.v

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3563,3 +3563,28 @@ fn main() {
35633563
')
35643564
assert ok.exit_code == 0, ok.output
35653565
}
3566+
3567+
// A program whose body is only literal `println` calls takes markused's
3568+
// trivial-literal-output fast path, which skips the ownership destructor seeds.
3569+
// Cgen still emits the `_result` destructor there, and in `-autofree` mode that
3570+
// helper calls `MessageError.free`, so the fast path has to root the IError
3571+
// implementers' destructors too. Without that, `hello world` fails to build with
3572+
// `use of undeclared identifier 'MessageError__free'`.
3573+
fn test_autofree_literal_only_program_keeps_ierror_destructors() {
3574+
v3_bin := ownership_build_v3()
3575+
ok := run_autofree_check(v3_bin, 'literal_only_println', "
3576+
fn main() {
3577+
println('hello')
3578+
}
3579+
")
3580+
assert ok.exit_code == 0, ok.output
3581+
3582+
ok_multi := run_autofree_check(v3_bin, 'literal_only_mixed_output', "
3583+
fn main() {
3584+
print('a')
3585+
eprintln('b')
3586+
println('c')
3587+
}
3588+
")
3589+
assert ok_multi.exit_code == 0, ok_multi.output
3590+
}

0 commit comments

Comments
 (0)