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())
|
c.type_implements(typ, arg.typ, call_arg.expr.position())
|
||||||
continue
|
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 {
|
c.check_expected(typ, arg.typ) or {
|
||||||
// str method, allow type with str method if fn arg is string
|
// str method, allow type with str method if fn arg is string
|
||||||
// Passing an int or a string array produces a c error here
|
// 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 {
|
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)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
mut inter_sym := c.table.get_type_symbol(inter_typ)
|
mut inter_sym := c.table.get_type_symbol(inter_typ)
|
||||||
styp := c.table.type_to_str(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 {
|
if i == 0 {
|
||||||
elem_type = expected_value_type
|
elem_type = expected_value_type
|
||||||
c.expected_type = elem_type
|
c.expected_type = elem_type
|
||||||
|
c.type_implements(typ, elem_type, expr.position())
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -5638,6 +5638,10 @@ fn (mut g Gen) interface_table() string {
|
||||||
// cctype is the Cleaned Concrete Type name, *without ptr*,
|
// cctype is the Cleaned Concrete Type name, *without ptr*,
|
||||||
// i.e. cctype is always just Cat, not Cat_ptr:
|
// i.e. cctype is always just Cat, not Cat_ptr:
|
||||||
cctype := g.cc_type(st)
|
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
|
// Speaker_Cat_index = 0
|
||||||
interface_index_name := '_${interface_name}_${cctype}_index'
|
interface_index_name := '_${interface_name}_${cctype}_index'
|
||||||
if already_generated_mwrappers[interface_index_name] > 0 {
|
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)))
|
mut receiver_type_name := util.no_dots(g.cc_type2(g.unwrap_generic(node.receiver_type)))
|
||||||
if typ_sym.kind == .interface_ {
|
if typ_sym.kind == .interface_ {
|
||||||
// Speaker_name_table[s._interface_idx].speak(s._object)
|
// 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.write('${c_name(receiver_type_name)}_name_table[')
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
dot := if node.left_type.is_ptr() { '->' } else { '.' }
|
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