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_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_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
 | ||||
| 	vlines_path            string   // set to the proper path for generating #line directives
 | ||||
| 	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() | ||||
| 		&& !expected_type.has_flag(.optional) { | ||||
| 		got_styp := g.cc_type(got_type, 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, got_is_ptr, | ||||
| 			got_styp) | ||||
| 		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) | ||||
| 			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, got_is_ptr, | ||||
| 				got_styp) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	// cast to sum type
 | ||||
|  | @ -4733,14 +4743,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { | |||
| 				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 { | ||||
| 				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 { | ||||
| 			g.writeln(';') | ||||
|  | @ -4928,7 +4931,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { | |||
| 		mut shared_typ := struct_init.typ.set_flag(.shared_f) | ||||
| 		shared_styp = g.typ(shared_typ) | ||||
| 		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){') | ||||
| 	} else if struct_init.typ.is_ptr() { | ||||
| 		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('}') | ||||
| 	if g.is_shared && !g.inside_opt_data && !g.is_arraymap_set { | ||||
| 		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))') | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -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