checker: check method args

pull/4716/head
joe-conigliaro 2020-05-05 01:32:40 +10:00
parent 36bf99ed5a
commit b2157388d9
No known key found for this signature in database
GPG Key ID: C12F7136C08206F1
3 changed files with 25 additions and 7 deletions

View File

@ -28,6 +28,6 @@ fn test_eventbus(){
assert !eb.subscriber.is_subscribed("on_test") assert !eb.subscriber.is_subscribed("on_test")
} }
fn on_test(sender voidptr, ev &EventData) { fn on_test(sender voidptr, ev &EventData, x voidptr) {
assert ev.data == "hello" assert ev.data == "hello"
} }

View File

@ -658,17 +658,28 @@ pub fn (mut c Checker) call_method(call_expr mut ast.CallExpr) table.Type {
// call_expr.args << method.args[0].typ // call_expr.args << method.args[0].typ
// call_expr.exp_arg_types << method.args[0].typ // call_expr.exp_arg_types << method.args[0].typ
for i, arg in call_expr.args { for i, arg in call_expr.args {
c.expected_type = if method.is_variadic && i >= method.args.len - 1 { exp_arg_typ := if method.is_variadic && i >= method.args.len - 1 {
method.args[method.args.len - 1].typ method.args[method.args.len - 1].typ
} else { } else {
method.args[i + 1].typ method.args[i + 1].typ
} }
arg_typ := c.expr(arg.expr) c.expected_type = exp_arg_typ
call_expr.args[i].typ = arg_typ got_arg_typ := c.expr(arg.expr)
if method.is_variadic && arg_typ.flag_is(.variadic) && call_expr.args.len - 1 > call_expr.args[i].typ = got_arg_typ
if method.is_variadic && got_arg_typ.flag_is(.variadic) && call_expr.args.len - 1 >
i { i {
c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos) c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos)
} }
if !c.table.check(got_arg_typ, exp_arg_typ) {
got_arg_sym := c.table.get_type_symbol(got_arg_typ)
exp_arg_sym := c.table.get_type_symbol(exp_arg_typ)
// str method, allow type with str method if fn arg is string
if exp_arg_sym.kind == .string && got_arg_sym.has_method('str') {
continue
}
c.error('cannot use type `$got_arg_sym.str()` as type `$exp_arg_sym.str()` in argument ${i+1} to `${left_type_sym.name}.$method_name`',
call_expr.pos)
}
} }
// TODO: typ optimize.. this node can get processed more than once // TODO: typ optimize.. this node can get processed more than once
if call_expr.expected_arg_types.len == 0 { if call_expr.expected_arg_types.len == 0 {

View File

@ -529,8 +529,15 @@ pub fn (t &Table) check(got, expected Type) bool {
if got_type_sym.kind == .function && exp_type_sym.kind == .function { if got_type_sym.kind == .function && exp_type_sym.kind == .function {
got_info := got_type_sym.info as FnType got_info := got_type_sym.info as FnType
exp_info := exp_type_sym.info as FnType exp_info := exp_type_sym.info as FnType
if got_info.func.signature() == exp_info.func.signature() { if got_info.func.args.len == exp_info.func.args.len {
return true mut matching := false
for i, arg in got_info.func.args {
exp_arg := exp_info.func.args[i]
matching = arg.typ.idx() == exp_arg.typ.idx() || exp_arg.typ == table.voidptr_type
}
if matching {
return true
}
} }
} }
if got_idx != exp_idx { if got_idx != exp_idx {