cgen: fix fn return array of interface (#10677)
							parent
							
								
									6dde9f76c6
								
							
						
					
					
						commit
						9f8c3cc159
					
				| 
						 | 
					@ -78,7 +78,7 @@ mut:
 | 
				
			||||||
	is_sql                 bool     // Inside `sql db{}` statement, generating sql instead of C (e.g. `and` instead of `&&` etc)
 | 
						is_sql                 bool     // Inside `sql db{}` statement, generating sql instead of C (e.g. `and` instead of `&&` etc)
 | 
				
			||||||
	is_shared              bool     // for initialization of hidden mutex in `[rw]shared` literals
 | 
						is_shared              bool     // for initialization of hidden mutex in `[rw]shared` literals
 | 
				
			||||||
	is_vlines_enabled      bool     // is it safe to generate #line directives when -g is passed
 | 
						is_vlines_enabled      bool     // is it safe to generate #line directives when -g is passed
 | 
				
			||||||
	is_cast_in_heap        bool     // fn return struct_init to interface type (cannot use stack, should use heap)
 | 
						inside_cast_in_heap    int      // inside cast to interface type in heap (resolve recursive calls)
 | 
				
			||||||
	arraymap_set_pos       int      // map or array set value position
 | 
						arraymap_set_pos       int      // map or array set value position
 | 
				
			||||||
	vlines_path            string   // set to the proper path for generating #line directives
 | 
						vlines_path            string   // set to the proper path for generating #line directives
 | 
				
			||||||
	optionals              []string // to avoid duplicates TODO perf, use map
 | 
						optionals              []string // to avoid duplicates TODO perf, use map
 | 
				
			||||||
| 
						 | 
					@ -1833,11 +1833,21 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if exp_sym.kind == .interface_ && got_type_raw.idx() != expected_type.idx()
 | 
						if exp_sym.kind == .interface_ && got_type_raw.idx() != expected_type.idx()
 | 
				
			||||||
		&& !expected_type.has_flag(.optional) {
 | 
							&& !expected_type.has_flag(.optional) {
 | 
				
			||||||
 | 
							if expr is ast.StructInit && !got_type.is_ptr() {
 | 
				
			||||||
 | 
								g.inside_cast_in_heap++
 | 
				
			||||||
 | 
								got_styp := g.cc_type(got_type.to_ptr(), true)
 | 
				
			||||||
 | 
								exp_styp := g.cc_type(expected_type, true)
 | 
				
			||||||
 | 
								fname := 'I_${got_styp}_to_Interface_$exp_styp'
 | 
				
			||||||
 | 
								g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, true,
 | 
				
			||||||
 | 
									got_styp)
 | 
				
			||||||
 | 
								g.inside_cast_in_heap--
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
			got_styp := g.cc_type(got_type, true)
 | 
								got_styp := g.cc_type(got_type, true)
 | 
				
			||||||
			exp_styp := g.cc_type(expected_type, true)
 | 
								exp_styp := g.cc_type(expected_type, true)
 | 
				
			||||||
			fname := 'I_${got_styp}_to_Interface_$exp_styp'
 | 
								fname := 'I_${got_styp}_to_Interface_$exp_styp'
 | 
				
			||||||
			g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, got_is_ptr,
 | 
								g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, got_is_ptr,
 | 
				
			||||||
				got_styp)
 | 
									got_styp)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// cast to sum type
 | 
						// cast to sum type
 | 
				
			||||||
| 
						 | 
					@ -4732,16 +4742,9 @@ fn (mut g Gen) return_stmt(node ast.Return) {
 | 
				
			||||||
				g.write('*')
 | 
									g.write('*')
 | 
				
			||||||
				g.expr(expr0)
 | 
									g.expr(expr0)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			rs := g.table.get_type_symbol(g.fn_decl.return_type)
 | 
					 | 
				
			||||||
			if node.exprs[0] is ast.StructInit && rs.kind == .interface_ && !node.types[0].is_ptr() {
 | 
					 | 
				
			||||||
				g.is_cast_in_heap = true
 | 
					 | 
				
			||||||
				g.expr_with_cast(node.exprs[0], node.types[0].to_ptr(), g.fn_decl.return_type)
 | 
					 | 
				
			||||||
				g.is_cast_in_heap = false
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
 | 
								g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if use_tmp_var {
 | 
							if use_tmp_var {
 | 
				
			||||||
			g.writeln(';')
 | 
								g.writeln(';')
 | 
				
			||||||
			has_semicolon = true
 | 
								has_semicolon = true
 | 
				
			||||||
| 
						 | 
					@ -4928,7 +4931,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
 | 
				
			||||||
		mut shared_typ := struct_init.typ.set_flag(.shared_f)
 | 
							mut shared_typ := struct_init.typ.set_flag(.shared_f)
 | 
				
			||||||
		shared_styp = g.typ(shared_typ)
 | 
							shared_styp = g.typ(shared_typ)
 | 
				
			||||||
		g.writeln('($shared_styp*)__dup${shared_styp}(&($shared_styp){.mtx = {0}, .val =($styp){')
 | 
							g.writeln('($shared_styp*)__dup${shared_styp}(&($shared_styp){.mtx = {0}, .val =($styp){')
 | 
				
			||||||
	} else if is_amp || g.is_cast_in_heap {
 | 
						} else if is_amp || g.inside_cast_in_heap > 0 {
 | 
				
			||||||
		g.write('($styp*)memdup(&($styp){')
 | 
							g.write('($styp*)memdup(&($styp){')
 | 
				
			||||||
	} else if struct_init.typ.is_ptr() {
 | 
						} else if struct_init.typ.is_ptr() {
 | 
				
			||||||
		basetyp := g.typ(struct_init.typ.set_nr_muls(0))
 | 
							basetyp := g.typ(struct_init.typ.set_nr_muls(0))
 | 
				
			||||||
| 
						 | 
					@ -5118,7 +5121,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
 | 
				
			||||||
	g.write('}')
 | 
						g.write('}')
 | 
				
			||||||
	if g.is_shared && !g.inside_opt_data && !g.is_arraymap_set {
 | 
						if g.is_shared && !g.inside_opt_data && !g.is_arraymap_set {
 | 
				
			||||||
		g.write('}, sizeof($shared_styp))')
 | 
							g.write('}, sizeof($shared_styp))')
 | 
				
			||||||
	} else if is_amp || g.is_cast_in_heap {
 | 
						} else if is_amp || g.inside_cast_in_heap > 0 {
 | 
				
			||||||
		g.write(', sizeof($styp))')
 | 
							g.write(', sizeof($styp))')
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Node {
 | 
				
			||||||
 | 
						name string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct NodeEmpty {
 | 
				
			||||||
 | 
						name string = 'abc'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn pusher(lines []string) []Node {
 | 
				
			||||||
 | 
						mut nodes := []Node{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for line in lines {
 | 
				
			||||||
 | 
							nodes << NodeEmpty{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nodes
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_fn_return_array_of_interface() {
 | 
				
			||||||
 | 
						lines := os.read_lines(@FILE) or { panic(err) }
 | 
				
			||||||
 | 
						pushed := pusher(lines)
 | 
				
			||||||
 | 
						println(pushed)
 | 
				
			||||||
 | 
						assert pushed.len > 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue