checker: fix interface checking of array arguments; closes #2377
parent
3b94a2b77a
commit
8caf3829d7
|
@ -1575,12 +1575,6 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
c.type_implements(typ, arg.typ, call_arg.expr.position())
|
||||
continue
|
||||
}
|
||||
// Handle expected interface array
|
||||
/*
|
||||
if exp_type_sym.kind == .array && t.get_type_symbol(t.value_type(exp_idx)).kind == .interface_ {
|
||||
return true
|
||||
}
|
||||
*/
|
||||
c.check_expected(typ, arg.typ) or {
|
||||
// str method, allow type with str method if fn arg is string
|
||||
// Passing an int or a string array produces a c error here
|
||||
|
@ -1631,6 +1625,9 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
}
|
||||
|
||||
fn (mut c Checker) type_implements(typ table.Type, inter_typ table.Type, pos token.Position) bool {
|
||||
$if debug_interface_type_implements ? {
|
||||
eprintln('> type_implements typ: $typ.debug() | inter_typ: $inter_typ.debug()')
|
||||
}
|
||||
typ_sym := c.table.get_type_symbol(typ)
|
||||
mut inter_sym := c.table.get_type_symbol(inter_typ)
|
||||
styp := c.table.type_to_str(typ)
|
||||
|
@ -2388,6 +2385,7 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
|
|||
if i == 0 {
|
||||
elem_type = expected_value_type
|
||||
c.expected_type = elem_type
|
||||
c.type_implements(typ, elem_type, expr.position())
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -5638,6 +5638,10 @@ fn (mut g Gen) interface_table() string {
|
|||
// cctype is the Cleaned Concrete Type name, *without ptr*,
|
||||
// i.e. cctype is always just Cat, not Cat_ptr:
|
||||
cctype := g.cc_type(st)
|
||||
$if debug_interface_table ? {
|
||||
eprintln('>> interface name: $ityp.name | concrete type: $st.debug() | st symname: ' +
|
||||
g.table.get_type_symbol(st).name)
|
||||
}
|
||||
// Speaker_Cat_index = 0
|
||||
interface_index_name := '_${interface_name}_${cctype}_index'
|
||||
if already_generated_mwrappers[interface_index_name] > 0 {
|
||||
|
|
|
@ -324,6 +324,9 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||
mut receiver_type_name := util.no_dots(g.cc_type2(g.unwrap_generic(node.receiver_type)))
|
||||
if typ_sym.kind == .interface_ {
|
||||
// Speaker_name_table[s._interface_idx].speak(s._object)
|
||||
$if debug_interface_method_call ? {
|
||||
eprintln('>>> interface typ_sym.name: $typ_sym.name | receiver_type_name: $receiver_type_name')
|
||||
}
|
||||
g.write('${c_name(receiver_type_name)}_name_table[')
|
||||
g.expr(node.left)
|
||||
dot := if node.left_type.is_ptr() { '->' } else { '.' }
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
struct Dog {
|
||||
breed string
|
||||
}
|
||||
|
||||
fn (d Dog) name() string {
|
||||
return 'Dog'
|
||||
}
|
||||
|
||||
// Utility helper function, to force interface _name_table generation
|
||||
fn get_name(s Speaker) {
|
||||
}
|
||||
|
||||
//
|
||||
fn test_an_array_of_interfaces_works() {
|
||||
dog := Dog{}
|
||||
// get_name(dog) // uncommenting this line fixes the example
|
||||
get_names([dog, dog])
|
||||
}
|
||||
|
||||
fn get_names(speakers []Speaker) {
|
||||
for s in speakers {
|
||||
println(s.name())
|
||||
}
|
||||
}
|
||||
|
||||
interface Speaker {
|
||||
name() string
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
struct Dog {
|
||||
breed string
|
||||
}
|
||||
|
||||
fn (d Dog) name() string {
|
||||
return 'Dog'
|
||||
}
|
||||
|
||||
// Utility helper function, to force interface _name_table generation
|
||||
fn get_name(s Speaker) {
|
||||
}
|
||||
|
||||
//
|
||||
fn test_an_array_of_interfaces_works() {
|
||||
dog := Dog{}
|
||||
get_name(dog) // NB: this line does nothing, but forces interface _name_table generation
|
||||
get_names([dog, dog])
|
||||
}
|
||||
|
||||
fn get_names(speakers []Speaker) {
|
||||
for s in speakers {
|
||||
println(s.name())
|
||||
}
|
||||
}
|
||||
|
||||
interface Speaker {
|
||||
name() string
|
||||
}
|
Loading…
Reference in New Issue