cgen: fix interface struct field initialization (#7340)
parent
7426544610
commit
604eab7742
|
@ -566,10 +566,13 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inited_fields << field_name
|
inited_fields << field_name
|
||||||
|
field_type_sym := c.table.get_type_symbol(info_field.typ)
|
||||||
c.expected_type = info_field.typ
|
c.expected_type = info_field.typ
|
||||||
expr_type := c.expr(field.expr)
|
expr_type := c.expr(field.expr)
|
||||||
expr_type_sym := c.table.get_type_symbol(expr_type)
|
expr_type_sym := c.table.get_type_symbol(expr_type)
|
||||||
if expr_type != table.void_type && expr_type_sym.kind != .placeholder {
|
if field_type_sym.kind == .interface_ {
|
||||||
|
c.type_implements(expr_type, info_field.typ, field.pos)
|
||||||
|
} else if expr_type != table.void_type && expr_type_sym.kind != .placeholder {
|
||||||
c.check_expected(expr_type, info_field.typ) or {
|
c.check_expected(expr_type, info_field.typ) or {
|
||||||
c.error('cannot assign to field `$info_field.name`: $err', field.pos)
|
c.error('cannot assign to field `$info_field.name`: $err', field.pos)
|
||||||
}
|
}
|
||||||
|
@ -2263,7 +2266,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
if !is_blank_ident && right_sym.kind != .placeholder {
|
if !is_blank_ident && right_sym.kind != .placeholder && left_sym.kind != .interface_ {
|
||||||
// Dual sides check (compatibility check)
|
// Dual sides check (compatibility check)
|
||||||
c.check_expected(right_type_unwrapped, left_type_unwrapped) or {
|
c.check_expected(right_type_unwrapped, left_type_unwrapped) or {
|
||||||
c.error('cannot assign to `$left`: $err', right.position())
|
c.error('cannot assign to `$left`: $err', right.position())
|
||||||
|
|
|
@ -1734,6 +1734,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
// `a := 1` | `a,b := 1,2`
|
// `a := 1` | `a,b := 1,2`
|
||||||
for i, left in assign_stmt.left {
|
for i, left in assign_stmt.left {
|
||||||
|
mut is_interface := false
|
||||||
mut var_type := assign_stmt.left_types[i]
|
mut var_type := assign_stmt.left_types[i]
|
||||||
mut val_type := assign_stmt.right_types[i]
|
mut val_type := assign_stmt.right_types[i]
|
||||||
val := assign_stmt.right[i]
|
val := assign_stmt.right[i]
|
||||||
|
@ -1742,6 +1743,19 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
mut ident := ast.Ident{
|
mut ident := ast.Ident{
|
||||||
scope: 0
|
scope: 0
|
||||||
}
|
}
|
||||||
|
left_sym := g.table.get_type_symbol(var_type)
|
||||||
|
if left_sym.kind == .interface_ {
|
||||||
|
if left is ast.SelectorExpr {
|
||||||
|
ident = left.root_ident()
|
||||||
|
if ident.obj is ast.Var {
|
||||||
|
idobj := ident.obj as ast.Var
|
||||||
|
root_type_sym := g.table.get_type_symbol(idobj.typ)
|
||||||
|
if root_type_sym.kind == .struct_ {
|
||||||
|
is_interface = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if left is ast.Ident {
|
if left is ast.Ident {
|
||||||
ident = left
|
ident = left
|
||||||
// id_info := ident.var_info()
|
// id_info := ident.var_info()
|
||||||
|
@ -1799,6 +1813,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
right_sym := g.table.get_type_symbol(val_type)
|
right_sym := g.table.get_type_symbol(val_type)
|
||||||
g.is_assign_lhs = true
|
g.is_assign_lhs = true
|
||||||
|
if is_interface && right_sym.kind == .interface_ {
|
||||||
|
is_interface = false
|
||||||
|
}
|
||||||
if val_type.has_flag(.optional) {
|
if val_type.has_flag(.optional) {
|
||||||
g.right_is_opt = true
|
g.right_is_opt = true
|
||||||
}
|
}
|
||||||
|
@ -1939,7 +1956,13 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
if assign_stmt.has_cross_var {
|
if assign_stmt.has_cross_var {
|
||||||
g.gen_cross_tmp_variable(assign_stmt.left, val)
|
g.gen_cross_tmp_variable(assign_stmt.left, val)
|
||||||
} else {
|
} else {
|
||||||
|
if is_interface {
|
||||||
|
g.interface_call(val_type, var_type)
|
||||||
|
}
|
||||||
g.expr_with_cast(val, val_type, var_type)
|
g.expr_with_cast(val, val_type, var_type)
|
||||||
|
if is_interface {
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4340,8 +4363,11 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
g.write('.$field_name = ')
|
g.write('.$field_name = ')
|
||||||
|
expected_field_type_sym := g.table.get_type_symbol(sfield.expected_type)
|
||||||
field_type_sym := g.table.get_type_symbol(sfield.typ)
|
field_type_sym := g.table.get_type_symbol(sfield.typ)
|
||||||
mut cloned := false
|
mut cloned := false
|
||||||
|
is_interface := expected_field_type_sym.kind == .interface_ &&
|
||||||
|
field_type_sym.kind != .interface_
|
||||||
if g.autofree && !sfield.typ.is_ptr() && field_type_sym.kind in [.array, .string] {
|
if g.autofree && !sfield.typ.is_ptr() && field_type_sym.kind in [.array, .string] {
|
||||||
g.write('/*clone1*/')
|
g.write('/*clone1*/')
|
||||||
if g.gen_clone_assignment(sfield.expr, field_type_sym, false) {
|
if g.gen_clone_assignment(sfield.expr, field_type_sym, false) {
|
||||||
|
@ -4349,11 +4375,17 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !cloned {
|
if !cloned {
|
||||||
|
if is_interface {
|
||||||
|
g.interface_call(sfield.typ, sfield.expected_type)
|
||||||
|
}
|
||||||
if sfield.expected_type.is_ptr() && !(sfield.typ.is_ptr() || sfield.typ.is_pointer()) &&
|
if sfield.expected_type.is_ptr() && !(sfield.typ.is_ptr() || sfield.typ.is_pointer()) &&
|
||||||
!sfield.typ.is_number() {
|
!sfield.typ.is_number() {
|
||||||
g.write('/* autoref */&')
|
g.write('/* autoref */&')
|
||||||
}
|
}
|
||||||
g.expr_with_cast(sfield.expr, sfield.typ, sfield.expected_type)
|
g.expr_with_cast(sfield.expr, sfield.typ, sfield.expected_type)
|
||||||
|
if is_interface {
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if is_multiline {
|
if is_multiline {
|
||||||
g.writeln(',')
|
g.writeln(',')
|
||||||
|
@ -5706,6 +5738,8 @@ fn (mut g Gen) interface_table() string {
|
||||||
already_generated_mwrappers[interface_index_name] = current_iinidx
|
already_generated_mwrappers[interface_index_name] = current_iinidx
|
||||||
current_iinidx++
|
current_iinidx++
|
||||||
// eprintln('>>> current_iinidx: ${current_iinidx-iinidx_minimum_base} | interface_index_name: $interface_index_name')
|
// eprintln('>>> current_iinidx: ${current_iinidx-iinidx_minimum_base} | interface_index_name: $interface_index_name')
|
||||||
|
sb.writeln('_Interface I_${cctype}_to_Interface_${interface_name}($cctype* x);')
|
||||||
|
sb.writeln('_Interface* I_${cctype}_to_Interface_${interface_name}_ptr($cctype* x);')
|
||||||
cast_functions.writeln('
|
cast_functions.writeln('
|
||||||
_Interface I_${cctype}_to_Interface_${interface_name}($cctype* x) {
|
_Interface I_${cctype}_to_Interface_${interface_name}($cctype* x) {
|
||||||
return (_Interface) {
|
return (_Interface) {
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
interface Speaker {
|
||||||
|
say_hello() string
|
||||||
|
speak(msg string)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Boss {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (b Boss) say_hello() string {
|
||||||
|
return "Hello, My name is $b.name and I\'m the bawz"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (b Boss) speak(msg string) {
|
||||||
|
println(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Cat {
|
||||||
|
name string
|
||||||
|
breed string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c Cat) say_hello() string {
|
||||||
|
return 'Meow meow $c.name the $c.breed meow'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c Cat) speak(msg string) {
|
||||||
|
println('Meow $msg')
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Baz {
|
||||||
|
mut:
|
||||||
|
sp Speaker
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_interface_struct() {
|
||||||
|
bz1 := Baz{
|
||||||
|
sp: Boss{
|
||||||
|
name: 'Richard'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert bz1.sp.say_hello() == "Hello, My name is Richard and I\'m the bawz"
|
||||||
|
print('Test Boss inside Baz struct: ')
|
||||||
|
bz1.sp.speak('Hello world!')
|
||||||
|
bz2 := Baz{
|
||||||
|
sp: Cat{
|
||||||
|
name: 'Grungy'
|
||||||
|
breed: 'Persian Cat'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert bz2.sp.say_hello() == 'Meow meow Grungy the Persian Cat meow'
|
||||||
|
print('Test Cat inside Baz struct: ')
|
||||||
|
bz2.sp.speak('Hello world!')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_interface_mut_struct() {
|
||||||
|
mut mbaz := Baz{
|
||||||
|
sp: Boss{
|
||||||
|
name: 'Derek'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert mbaz.sp.say_hello() == "Hello, My name is Derek and I\'m the bawz"
|
||||||
|
mbaz.sp = Cat{
|
||||||
|
name: 'Dog'
|
||||||
|
breed: 'Not a dog'
|
||||||
|
}
|
||||||
|
assert mbaz.sp.say_hello() == 'Meow meow Dog the Not a dog meow'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_interface_struct_from_array() {
|
||||||
|
bazs := [
|
||||||
|
Baz{
|
||||||
|
sp: Cat{
|
||||||
|
name: 'Kitty'
|
||||||
|
breed: 'Catty Koo'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Baz{
|
||||||
|
sp: Boss{
|
||||||
|
name: 'Bob'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
assert bazs[0].sp.say_hello() == 'Meow meow Kitty the Catty Koo meow'
|
||||||
|
assert bazs[1].sp.say_hello() == "Hello, My name is Bob and I\'m the bawz"
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TODO: fix this too; currently with V 0.1.30 7426544 produces: `V panic: as cast: cannot cast 200 to 197`
|
||||||
|
fn test_interface_struct_from_mut_array() {
|
||||||
|
mut bazs := [
|
||||||
|
Baz{
|
||||||
|
sp: Cat{
|
||||||
|
name: 'Kitty'
|
||||||
|
breed: 'Catty Koo'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Baz{
|
||||||
|
sp: Boss{
|
||||||
|
name: 'Bob'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
bazs[0].sp = Boss{
|
||||||
|
name: 'Ross'
|
||||||
|
}
|
||||||
|
|
||||||
|
bazs[1].sp = Cat{
|
||||||
|
name: 'Doggy'
|
||||||
|
breed: 'Doggy Doo'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert bazs[0].sp.say_hello() == 'Hello, My name is Ross and I\'m the bawz'
|
||||||
|
assert bazs[1].sp.say_hello() == 'Meow meow Doggy the Doggy Doo meow'
|
||||||
|
}
|
||||||
|
*/
|
Loading…
Reference in New Issue