checker: fix generic fn with assign reference generic struct (fix #10681) (#10695)

pull/10700/head
yuyi 2021-07-08 21:50:25 +08:00 committed by GitHub
parent eac8f77613
commit fb9b2e873c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 1 deletions

View File

@ -3390,6 +3390,7 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
c.expected_type = ast.void_type
}
right_first := node.right[0]
node.left_types = []
mut right_len := node.right.len
mut right_type0 := ast.void_type
for i, right in node.right {
@ -3477,6 +3478,16 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
}
right := if i < node.right.len { node.right[i] } else { node.right[0] }
mut right_type := node.right_types[i]
if right is ast.Ident {
right_sym := c.table.get_type_symbol(right_type)
if right_sym.info is ast.Struct {
if right_sym.info.generic_types.len > 0 {
if obj := right.scope.find(right.name) {
right_type = obj.typ
}
}
}
}
if is_decl {
// check generic struct init and return unwrap generic struct type
if right is ast.StructInit {
@ -3484,6 +3495,10 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
c.expr(right)
right_type = right.typ
}
} else if right is ast.PrefixExpr {
if right.op == .amp && right.right is ast.StructInit {
right_type = c.expr(right)
}
}
if right.is_auto_deref_var() {
left_type = c.table.mktyp(right_type.deref())

View File

@ -2620,8 +2620,27 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
if is_inside_ternary {
g.out.write_string(util.tabs(g.indent - g.inside_ternary))
}
mut is_used_var_styp := false
if ident.name !in g.defer_vars {
g.write('$styp ')
val_sym := g.table.get_type_symbol(val_type)
if val_sym.info is ast.Struct {
if val_sym.info.generic_types.len > 0 {
if val is ast.StructInit {
var_styp := g.typ(val.typ)
g.write('$var_styp ')
is_used_var_styp = true
} else if val is ast.PrefixExpr {
if val.op == .amp && val.right is ast.StructInit {
var_styp := g.typ(val.right.typ.to_ptr())
g.write('$var_styp ')
is_used_var_styp = true
}
}
}
}
if !is_used_var_styp {
g.write('$styp ')
}
if is_auto_heap {
g.write('*')
}

View File

@ -0,0 +1,46 @@
pub struct List<T> {
pub mut:
head &ListNode<T> = 0
}
pub struct ListNode<T> {
pub mut:
value T
next &ListNode<T> = 0
}
pub fn list_new<T>() List<T> {
return List<T>{}
}
pub fn (mut l List<T>) add(value T) {
mut node := &ListNode<T>{value, 0}
if l.head == 0 {
l.head = node
} else {
node.next = l.head
l.head = node
}
}
fn test_generic_assign_reference_generic_struct() {
mut list1 := list_new<string>()
list1.add('hello')
println(list1.head.value)
assert list1.head.value == 'hello'
mut list2 := list_new<int>()
list2.add(100)
println(list2.head.value)
assert list2.head.value == 100
mut list3 := list_new<f64>()
list3.add(22.2)
println(list3.head.value)
assert list3.head.value == 22.2
mut list4 := list_new<bool>()
list4.add(true)
println(list4.head.value)
assert list4.head.value == true
}