@@ -314,56 +314,7 @@ func (v *visitor) SliceNode(node *ast.SliceNode) reflect.Type {
314
314
func (v * visitor ) FunctionNode (node * ast.FunctionNode ) reflect.Type {
315
315
if f , ok := v .types [node .Name ]; ok {
316
316
if fn , ok := isFuncType (f .Type ); ok {
317
- if isInterface (fn ) {
318
- return interfaceType
319
- }
320
-
321
- if fn .NumOut () == 0 {
322
- panic (v .error (node , "func %v doesn't return value" , node .Name ))
323
- }
324
- if fn .NumOut () != 1 {
325
- panic (v .error (node , "func %v returns more then one value" , node .Name ))
326
- }
327
-
328
- numIn := fn .NumIn ()
329
-
330
- // If func is method on an env, first argument should be a receiver,
331
- // and actual arguments less then numIn by one.
332
- if f .Method {
333
- numIn --
334
- }
335
-
336
- if len (node .Arguments ) > numIn {
337
- panic (v .error (node , "too many arguments to call %v" , node .Name ))
338
- }
339
- if len (node .Arguments ) < numIn {
340
- panic (v .error (node , "not enough arguments to call %v" , node .Name ))
341
- }
342
-
343
- n := 0
344
-
345
- // Skip first argument in case of the receiver.
346
- if f .Method {
347
- n = 1
348
- }
349
-
350
- for _ , arg := range node .Arguments {
351
- t := v .visit (arg )
352
- in := fn .In (n )
353
-
354
- if isIntegerOrArithmeticOperation (arg ) {
355
- t = in
356
- setTypeForIntegers (arg , t )
357
- }
358
-
359
- if ! t .AssignableTo (in ) {
360
- panic (v .error (arg , "cannot use %v as argument (type %v) to call %v " , t , in , node .Name ))
361
- }
362
- n ++
363
- }
364
-
365
- return fn .Out (0 )
366
-
317
+ return v .checkFunc (fn , f .Method , node , node .Name , node .Arguments )
367
318
}
368
319
}
369
320
panic (v .error (node , "unknown func %v" , node .Name ))
@@ -373,59 +324,78 @@ func (v *visitor) MethodNode(node *ast.MethodNode) reflect.Type {
373
324
t := v .visit (node .Node )
374
325
if f , method , ok := methodType (t , node .Method ); ok {
375
326
if fn , ok := isFuncType (f ); ok {
376
- if isInterface (fn ) {
377
- return interfaceType
378
- }
327
+ return v .checkFunc (fn , method , node , node .Method , node .Arguments )
328
+ }
329
+ }
330
+ panic (v .error (node , "type %v has no method %v" , t , node .Method ))
331
+ }
379
332
380
- if fn .NumOut () == 0 {
381
- panic (v .error (node , "method %v doesn't return value" , node .Method ))
382
- }
383
- if fn .NumOut () != 1 {
384
- panic (v .error (node , "method %v returns more then one value" , node .Method ))
385
- }
333
+ // checkFunc checks func arguments and returns "return type" of func or method.
334
+ func (v * visitor ) checkFunc (fn reflect.Type , method bool , node ast.Node , name string , arguments []ast.Node ) reflect.Type {
335
+ if isInterface (fn ) {
336
+ return interfaceType
337
+ }
386
338
387
- numIn := fn .NumIn ()
339
+ if fn .NumOut () == 0 {
340
+ panic (v .error (node , "func %v doesn't return value" , name ))
341
+ }
342
+ if fn .NumOut () != 1 {
343
+ panic (v .error (node , "func %v returns more then one value" , name ))
344
+ }
388
345
389
- // If func is method, first argument should be a receiver,
390
- // and actual arguments less then numIn by one.
391
- if method {
392
- numIn --
393
- }
346
+ numIn := fn .NumIn ()
394
347
395
- if len (node .Arguments ) > numIn {
396
- panic (v .error (node , "too many arguments to call %v" , node .Method ))
397
- }
398
- if len (node .Arguments ) < numIn {
399
- panic (v .error (node , "not enough arguments to call %v" , node .Method ))
400
- }
348
+ // If func is method on an env, first argument should be a receiver,
349
+ // and actual arguments less then numIn by one.
350
+ if method {
351
+ numIn --
352
+ }
401
353
402
- n := 0
354
+ if fn .IsVariadic () {
355
+ if len (arguments ) < numIn - 1 {
356
+ panic (v .error (node , "not enough arguments to call %v" , name ))
357
+ }
358
+ } else {
359
+ if len (arguments ) > numIn {
360
+ panic (v .error (node , "too many arguments to call %v" , name ))
361
+ }
362
+ if len (arguments ) < numIn {
363
+ panic (v .error (node , "not enough arguments to call %v" , name ))
364
+ }
365
+ }
403
366
404
- // Skip first argument in case of the receiver.
405
- if method {
406
- n = 1
407
- }
367
+ n := 0
408
368
409
- for _ , arg := range node .Arguments {
410
- t := v .visit (arg )
411
- in := fn .In (n )
369
+ // Skip first argument in case of the receiver.
370
+ if method {
371
+ n = 1
372
+ }
412
373
413
- if isIntegerOrArithmeticOperation (arg ) {
414
- t = in
415
- setTypeForIntegers (arg , t )
416
- }
374
+ for _ , arg := range arguments {
375
+ t := v .visit (arg )
417
376
418
- if ! t .AssignableTo (in ) {
419
- panic (v .error (arg , "cannot use %v as argument (type %v) to call %v " , t , in , node .Method ))
420
- }
421
- n ++
422
- }
377
+ var in reflect.Type
378
+ if fn .IsVariadic () && n >= numIn {
379
+ // For variadic arguments fn(xs ...int), go replaces type of xs (int) with ([]int).
380
+ // As we compare arguments one by one, we need underling type.
381
+ in , _ = indexType (fn .In (numIn ))
382
+ } else {
383
+ in = fn .In (n )
384
+ }
423
385
424
- return fn .Out (0 )
386
+ if isIntegerOrArithmeticOperation (arg ) {
387
+ t = in
388
+ setTypeForIntegers (arg , t )
389
+ }
425
390
391
+ if ! t .AssignableTo (in ) {
392
+ panic (v .error (arg , "cannot use %v as argument (type %v) to call %v " , t , in , name ))
426
393
}
394
+
395
+ n ++
427
396
}
428
- panic (v .error (node , "type %v has no method %v" , t , node .Method ))
397
+
398
+ return fn .Out (0 )
429
399
}
430
400
431
401
func (v * visitor ) BuiltinNode (node * ast.BuiltinNode ) reflect.Type {
0 commit comments