From 44d2f2b3029862dfa92c5fa588badbd95d1c3ed3 Mon Sep 17 00:00:00 2001 From: yuyi Date: Wed, 19 Jul 2023 02:12:45 +0800 Subject: [PATCH] checker, cgen: fix closure with inherited sumtype variable (#18894) --- vlib/v/checker/checker.v | 3 + vlib/v/gen/c/cgen.v | 3 + vlib/v/tests/closure_with_sumtype_var_test.v | 75 ++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 vlib/v/tests/closure_with_sumtype_var_test.v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 378d362413..1c01ff3574 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3650,6 +3650,7 @@ fn (mut c Checker) smartcast(mut expr ast.Expr, cur_type ast.Type, to_type_ ast. mut smartcasts := []ast.Type{} mut is_already_casted := false mut orig_type := 0 + mut is_inherited := false if mut expr.obj is ast.Var { is_mut = expr.obj.is_mut smartcasts << expr.obj.smartcasts @@ -3657,6 +3658,7 @@ fn (mut c Checker) smartcast(mut expr ast.Expr, cur_type ast.Type, to_type_ ast. if orig_type == 0 { orig_type = expr.obj.typ } + is_inherited = expr.obj.is_inherited } // smartcast either if the value is immutable or if the mut argument is explicitly given if (!is_mut || expr.is_mut) && !is_already_casted { @@ -3667,6 +3669,7 @@ fn (mut c Checker) smartcast(mut expr ast.Expr, cur_type ast.Type, to_type_ ast. pos: expr.pos is_used: true is_mut: expr.is_mut + is_inherited: is_inherited smartcasts: smartcasts orig_type: orig_type }) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index e7d6d487e4..5efb4f0364 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4348,6 +4348,9 @@ fn (mut g Gen) ident(node ast.Ident) { } else { mut is_ptr := false if i == 0 { + if node.obj.is_inherited { + g.write(closure_ctx + '->') + } g.write(name) if node.obj.orig_type.is_ptr() { is_ptr = true diff --git a/vlib/v/tests/closure_with_sumtype_var_test.v b/vlib/v/tests/closure_with_sumtype_var_test.v new file mode 100644 index 0000000000..cabf96ac04 --- /dev/null +++ b/vlib/v/tests/closure_with_sumtype_var_test.v @@ -0,0 +1,75 @@ +import encoding.binary +import rand + +type DataType = int | string + +struct DataBuilder { +mut: + func fn (mut []u8) + len int +} + +pub fn (mut d DataBuilder) add(v DataType) { + func := d.func + len := d.len + d.func = fn [v, len, func] (mut b []u8) { + if !isnil(func) { + func(mut b) + } + match v { + int { + binary.big_endian_put_u32_at(mut b, u32(v), len) + } + string { + binary.big_endian_put_u16_at(mut b, u16(v.len), len) + for i := 0; i < v.len; i++ { + b[len + 2 + i] = v[i] + } + } + } + } + d.len += match v { + int { 4 } + string { 2 + v.len } + } +} + +pub fn (d &DataBuilder) build() []u8 { + mut b := []u8{len: d.len} + d.func(mut b) + binary.big_endian_put_u16(mut b, u16(d.len - 2)) + unsafe { + d.func = nil + d.len = 2 + } + return b +} + +fn new_data_builder() DataBuilder { + return DataBuilder{ + func: unsafe { nil } + len: 2 + } +} + +fn test_closure_with_sumtype_var() { + mut data := new_data_builder() + data.add(1) + data.add(2) + data.add(3) + data.add(4) + data.add(5) + data.add('1') + data.add('22') + data.add('334455') + data.add(rand.string(rand.int_in_range(10, 100)!)) + data.add('5') + data.add(1) + data.add(2) + data.add(3) + data.add(4) + data.add(5) + ret := data.build() + dump(ret) + assert binary.big_endian_u16_at(ret, 0) == ret[2..].len +}