checker: fix "unregistered" variadic interface call arguments (#12525)
parent
90ba856107
commit
82010e729d
|
@ -2173,12 +2173,14 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
||||||
arg.pos)
|
arg.pos)
|
||||||
}
|
}
|
||||||
mut final_arg_sym := exp_arg_sym
|
mut final_arg_sym := exp_arg_sym
|
||||||
|
mut final_arg_typ := exp_arg_typ
|
||||||
if method.is_variadic && exp_arg_sym.info is ast.Array {
|
if method.is_variadic && exp_arg_sym.info is ast.Array {
|
||||||
final_arg_sym = c.table.get_type_symbol(exp_arg_sym.array_info().elem_type)
|
final_arg_typ = exp_arg_sym.array_info().elem_type
|
||||||
|
final_arg_sym = c.table.get_type_symbol(final_arg_typ)
|
||||||
}
|
}
|
||||||
// Handle expected interface
|
// Handle expected interface
|
||||||
if final_arg_sym.kind == .interface_ {
|
if final_arg_sym.kind == .interface_ {
|
||||||
if c.type_implements(got_arg_typ, exp_arg_typ, arg.expr.position()) {
|
if c.type_implements(got_arg_typ, final_arg_typ, arg.expr.position()) {
|
||||||
if !got_arg_typ.is_ptr() && !got_arg_typ.is_pointer() && !c.inside_unsafe {
|
if !got_arg_typ.is_ptr() && !got_arg_typ.is_pointer() && !c.inside_unsafe {
|
||||||
got_arg_typ_sym := c.table.get_type_symbol(got_arg_typ)
|
got_arg_typ_sym := c.table.get_type_symbol(got_arg_typ)
|
||||||
if got_arg_typ_sym.kind != .interface_ {
|
if got_arg_typ_sym.kind != .interface_ {
|
||||||
|
@ -2849,8 +2851,10 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut final_param_sym := param_typ_sym
|
mut final_param_sym := param_typ_sym
|
||||||
|
mut final_param_typ := param.typ
|
||||||
if func.is_variadic && param_typ_sym.info is ast.Array {
|
if func.is_variadic && param_typ_sym.info is ast.Array {
|
||||||
final_param_sym = c.table.get_type_symbol(param_typ_sym.array_info().elem_type)
|
final_param_typ = param_typ_sym.array_info().elem_type
|
||||||
|
final_param_sym = c.table.get_type_symbol(final_param_typ)
|
||||||
}
|
}
|
||||||
// NB: Casting to voidptr is used as an escape mechanism, so:
|
// NB: Casting to voidptr is used as an escape mechanism, so:
|
||||||
// 1. allow passing *explicit* voidptr (native or through cast) to functions
|
// 1. allow passing *explicit* voidptr (native or through cast) to functions
|
||||||
|
@ -2867,7 +2871,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
||||||
}
|
}
|
||||||
// Handle expected interface
|
// Handle expected interface
|
||||||
if final_param_sym.kind == .interface_ {
|
if final_param_sym.kind == .interface_ {
|
||||||
if c.type_implements(typ, param.typ, call_arg.expr.position()) {
|
if c.type_implements(typ, final_param_typ, call_arg.expr.position()) {
|
||||||
if !typ.is_ptr() && !typ.is_pointer() && !c.inside_unsafe
|
if !typ.is_ptr() && !typ.is_pointer() && !c.inside_unsafe
|
||||||
&& typ_sym.kind != .interface_ {
|
&& typ_sym.kind != .interface_ {
|
||||||
c.mark_as_referenced(mut &call_arg.expr, true)
|
c.mark_as_referenced(mut &call_arg.expr, true)
|
||||||
|
|
|
@ -366,3 +366,23 @@ fn main() {
|
||||||
println(dog.name)
|
println(dog.name)
|
||||||
println(get_animal_name(mut dog))
|
println(get_animal_name(mut dog))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Text = string
|
||||||
|
|
||||||
|
fn (t Text) display() string {
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Displayable {
|
||||||
|
display() string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_displayable(ds ...Displayable) {
|
||||||
|
for d in ds {
|
||||||
|
println(d.display())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_variadic_interface() {
|
||||||
|
print_displayable(Text('test'), Text('hehe'))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue