1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker, cgen: fix closure with inherited sumtype variable (#18894)

This commit is contained in:
yuyi 2023-07-19 02:12:45 +08:00 committed by GitHub
parent e71370dc40
commit 44d2f2b302
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 0 deletions

View File

@ -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
})

View File

@ -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

View File

@ -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
}