mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
cmd/compile/internal/types2: report types for mismatched call and return statements
Thanks to emmanuel@orijtech.com who wrote the initial version of this change (CL 354490). This change is following CL 354490 in idea but also contains various simplifications, slightly improved printing of signature/type patterns, adjustments for types2, and some fine-tuning of error positions. Also adjusted several ERROR regexp patterns. Fixes #48834. Fixes #48835. Change-Id: I31cf20c81753b1dc84836dbe83a39030ceb9db23 Reviewed-on: https://go-review.googlesource.com/c/go/+/364874 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
This commit is contained in:
parent
9e7600d3fc
commit
c25bf0d959
@ -9,6 +9,7 @@ package types2
|
||||
import (
|
||||
"cmd/compile/internal/syntax"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// assignment reports whether x can be assigned to a variable of type T,
|
||||
@ -241,6 +242,58 @@ func (check *Checker) assignVar(lhs syntax.Expr, x *operand) Type {
|
||||
return x.typ
|
||||
}
|
||||
|
||||
// operandTypes returns the list of types for the given operands.
|
||||
func operandTypes(list []*operand) (res []Type) {
|
||||
for _, x := range list {
|
||||
res = append(res, x.typ)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// varTypes returns the list of types for the given variables.
|
||||
func varTypes(list []*Var) (res []Type) {
|
||||
for _, x := range list {
|
||||
res = append(res, x.typ)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// typesSummary returns a string of the form "(t1, t2, ...)" where the
|
||||
// ti's are user-friendly string representations for the given types.
|
||||
// If variadic is set and the last type is a slice, its string is of
|
||||
// the form "...E" where E is the slice's element type.
|
||||
func (check *Checker) typesSummary(list []Type, variadic bool) string {
|
||||
var res []string
|
||||
for i, t := range list {
|
||||
var s string
|
||||
switch {
|
||||
case t == nil:
|
||||
fallthrough // should not happend but be cautious
|
||||
case t == Typ[Invalid]:
|
||||
s = "<T>"
|
||||
case isUntyped(t):
|
||||
if isNumeric(t) {
|
||||
// Do not imply a specific type requirement:
|
||||
// "have number, want float64" is better than
|
||||
// "have untyped int, want float64" or
|
||||
// "have int, want float64".
|
||||
s = "number"
|
||||
} else {
|
||||
// If we don't have a number, omit the "untyped" qualifier
|
||||
// for compactness.
|
||||
s = strings.Replace(t.(*Basic).name, "untyped ", "", -1)
|
||||
}
|
||||
case variadic && i == len(list)-1:
|
||||
s = check.sprintf("...%s", t.(*Slice).elem)
|
||||
}
|
||||
if s == "" {
|
||||
s = check.sprintf("%s", t)
|
||||
}
|
||||
res = append(res, s)
|
||||
}
|
||||
return "(" + strings.Join(res, ", ") + ")"
|
||||
}
|
||||
|
||||
func (check *Checker) assignError(rhs []syntax.Expr, nvars, nvals int) {
|
||||
measure := func(x int, unit string) string {
|
||||
s := fmt.Sprintf("%d %s", x, unit)
|
||||
@ -263,10 +316,10 @@ func (check *Checker) assignError(rhs []syntax.Expr, nvars, nvals int) {
|
||||
check.errorf(rhs0, "assignment mismatch: %s but %s", vars, vals)
|
||||
}
|
||||
|
||||
// If returnPos is valid, initVars is called to type-check the assignment of
|
||||
// return expressions, and returnPos is the position of the return statement.
|
||||
func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnPos syntax.Pos) {
|
||||
rhs, commaOk := check.exprList(orig_rhs, len(lhs) == 2 && !returnPos.IsKnown())
|
||||
// If returnStmt != nil, initVars is called to type-check the assignment
|
||||
// of return expressions, and returnStmt is the the return statement.
|
||||
func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnStmt syntax.Stmt) {
|
||||
rhs, commaOk := check.exprList(orig_rhs, len(lhs) == 2 && returnStmt == nil)
|
||||
|
||||
if len(lhs) != len(rhs) {
|
||||
// invalidate lhs
|
||||
@ -282,8 +335,20 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnPos syn
|
||||
return
|
||||
}
|
||||
}
|
||||
if returnPos.IsKnown() {
|
||||
check.errorf(returnPos, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs))
|
||||
if returnStmt != nil {
|
||||
var at poser = returnStmt
|
||||
qualifier := "not enough"
|
||||
if len(rhs) > len(lhs) {
|
||||
at = rhs[len(lhs)].expr // report at first extra value
|
||||
qualifier = "too many"
|
||||
} else if len(rhs) > 0 {
|
||||
at = rhs[len(rhs)-1].expr // report at last value
|
||||
}
|
||||
var err error_
|
||||
err.errorf(at, "%s return values", qualifier)
|
||||
err.errorf(nopos, "have %s", check.typesSummary(operandTypes(rhs), false))
|
||||
err.errorf(nopos, "want %s", check.typesSummary(varTypes(lhs), false))
|
||||
check.report(&err)
|
||||
return
|
||||
}
|
||||
if check.conf.CompilerErrorMessages {
|
||||
@ -295,7 +360,7 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnPos syn
|
||||
}
|
||||
|
||||
context := "assignment"
|
||||
if returnPos.IsKnown() {
|
||||
if returnStmt != nil {
|
||||
context = "return statement"
|
||||
}
|
||||
|
||||
@ -449,7 +514,7 @@ func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) {
|
||||
}
|
||||
}
|
||||
|
||||
check.initVars(lhsVars, rhs, nopos)
|
||||
check.initVars(lhsVars, rhs, nil)
|
||||
|
||||
// process function literals in rhs expressions before scope changes
|
||||
check.processDelayed(top)
|
||||
|
@ -350,12 +350,25 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T
|
||||
}
|
||||
|
||||
// check argument count
|
||||
switch {
|
||||
case nargs < npars:
|
||||
check.errorf(call, "not enough arguments in call to %s", call.Fun)
|
||||
return
|
||||
case nargs > npars:
|
||||
check.errorf(args[npars], "too many arguments in call to %s", call.Fun) // report at first extra argument
|
||||
if nargs != npars {
|
||||
var at poser = call
|
||||
qualifier := "not enough"
|
||||
if nargs > npars {
|
||||
at = args[npars].expr // report at first extra argument
|
||||
qualifier = "too many"
|
||||
} else if nargs > 0 {
|
||||
at = args[nargs-1].expr // report at last argument
|
||||
}
|
||||
// take care of empty parameter lists represented by nil tuples
|
||||
var params []*Var
|
||||
if sig.params != nil {
|
||||
params = sig.params.vars
|
||||
}
|
||||
var err error_
|
||||
err.errorf(at, "%s arguments in call to %s", qualifier, call.Fun)
|
||||
err.errorf(nopos, "have %s", check.typesSummary(operandTypes(args), false))
|
||||
err.errorf(nopos, "want %s", check.typesSummary(varTypes(params), sig.variadic))
|
||||
check.report(&err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -549,7 +549,7 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init syntax.Expr) {
|
||||
}
|
||||
}
|
||||
|
||||
check.initVars(lhs, []syntax.Expr{init}, nopos)
|
||||
check.initVars(lhs, []syntax.Expr{init}, nil)
|
||||
}
|
||||
|
||||
// isImportedConstraint reports whether typ is an imported type constraint.
|
||||
|
@ -493,7 +493,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
|
||||
}
|
||||
} else {
|
||||
// return has results or result parameters are unnamed
|
||||
check.initVars(res.vars, results, s.Pos())
|
||||
check.initVars(res.vars, results, s)
|
||||
}
|
||||
} else if len(results) > 0 {
|
||||
check.error(results[0], "no result values expected")
|
||||
|
@ -25,7 +25,7 @@ func append1() {
|
||||
_ = append(s, b)
|
||||
_ = append(s, x /* ERROR cannot use x */ )
|
||||
_ = append(s, s /* ERROR cannot use s */ )
|
||||
_ = append(s... ) /* ERROR not enough arguments */
|
||||
_ = append(s /* ERROR not enough arguments */ ...)
|
||||
_ = append(s, b, s /* ERROR too many arguments */ ... )
|
||||
_ = append(s, 1, 2, 3)
|
||||
_ = append(s, 1, 2, 3, x /* ERROR cannot use x */ , 5, 6, 6)
|
||||
|
@ -8,32 +8,38 @@ package errors
|
||||
// (matching messages are regular expressions, hence the \'s).
|
||||
func f(x int, m map[string]int) {
|
||||
// no values
|
||||
_ = f /* ERROR "f\(0, m\) \(no value\) used as value" */ (0, m)
|
||||
_ = f /* ERROR f\(0, m\) \(no value\) used as value */ (0, m)
|
||||
|
||||
// built-ins
|
||||
_ = println /* ERROR "println \(built-in\) must be called" */
|
||||
_ = println // ERROR println \(built-in\) must be called
|
||||
|
||||
// types
|
||||
_ = complex128 /* ERROR "complex128 \(type\) is not an expression" */
|
||||
_ = complex128 // ERROR complex128 \(type\) is not an expression
|
||||
|
||||
// constants
|
||||
const c1 = 991
|
||||
const c2 float32 = 0.5
|
||||
0 /* ERROR "0 \(untyped int constant\) is not used" */
|
||||
c1 /* ERROR "c1 \(untyped int constant 991\) is not used" */
|
||||
c2 /* ERROR "c2 \(constant 0.5 of type float32\) is not used" */
|
||||
c1 /* ERROR "c1 \+ c2 \(constant 991.5 of type float32\) is not used" */ + c2
|
||||
const c3 = "foo"
|
||||
0 // ERROR 0 \(untyped int constant\) is not used
|
||||
0.5 // ERROR 0.5 \(untyped float constant\) is not used
|
||||
"foo" // ERROR "foo" \(untyped string constant\) is not used
|
||||
c1 // ERROR c1 \(untyped int constant 991\) is not used
|
||||
c2 // ERROR c2 \(constant 0.5 of type float32\) is not used
|
||||
c1 /* ERROR c1 \+ c2 \(constant 991.5 of type float32\) is not used */ + c2
|
||||
c3 // ERROR c3 \(untyped string constant "foo"\) is not used
|
||||
|
||||
// variables
|
||||
x /* ERROR "x \(variable of type int\) is not used" */
|
||||
x // ERROR x \(variable of type int\) is not used
|
||||
|
||||
// values
|
||||
x /* ERROR "x != x \(untyped bool value\) is not used" */ != x
|
||||
x /* ERROR "x \+ x \(value of type int\) is not used" */ + x
|
||||
nil // ERROR nil is not used
|
||||
(*int)(nil) // ERROR \(\*int\)\(nil\) \(value of type \*int\) is not used
|
||||
x /* ERROR x != x \(untyped bool value\) is not used */ != x
|
||||
x /* ERROR x \+ x \(value of type int\) is not used */ + x
|
||||
|
||||
// value, ok's
|
||||
const s = "foo"
|
||||
m /* ERROR "m\[s\] \(map index expression of type int\) is not used" */ [s]
|
||||
m /* ERROR m\[s\] \(map index expression of type int\) is not used */ [s]
|
||||
}
|
||||
|
||||
// Valid ERROR comments can have a variety of forms.
|
||||
|
@ -494,23 +494,23 @@ func _calls() {
|
||||
f1(0)
|
||||
f1(x)
|
||||
f1(10.0)
|
||||
f1() /* ERROR "not enough arguments" */
|
||||
f1(x, y /* ERROR "too many arguments" */ )
|
||||
f1 /* ERROR "not enough arguments in call to f1\n\thave \(\)\n\twant \(int\)" */ ()
|
||||
f1(x, y /* ERROR "too many arguments in call to f1\n\thave \(int, float32\)\n\twant \(int\)" */ )
|
||||
f1(s /* ERROR "cannot use .* in argument" */ )
|
||||
f1(x ... /* ERROR "cannot use ..." */ )
|
||||
f1(g0 /* ERROR "used as value" */ ())
|
||||
f1(g1())
|
||||
f1(g2 /* ERROR "too many arguments" */ ())
|
||||
f1(g2 /* ERROR "too many arguments in call to f1\n\thave \(float32, string\)\n\twant \(int\)" */ ())
|
||||
|
||||
f2() /* ERROR "not enough arguments" */
|
||||
f2(3.14) /* ERROR "not enough arguments" */
|
||||
f2 /* ERROR "not enough arguments in call to f2\n\thave \(\)\n\twant \(float32, string\)" */ ()
|
||||
f2(3.14 /* ERROR "not enough arguments in call to f2\n\thave \(number\)\n\twant \(float32, string\)" */ )
|
||||
f2(3.14, "foo")
|
||||
f2(x /* ERROR "cannot use .* in argument" */ , "foo")
|
||||
f2(g0 /* ERROR "used as value" */ ())
|
||||
f2(g1()) /* ERROR "not enough arguments" */
|
||||
f2(g1 /* ERROR "not enough arguments in call to f2\n\thave \(int\)\n\twant \(float32, string\)" */ ())
|
||||
f2(g2())
|
||||
|
||||
fs() /* ERROR "not enough arguments" */
|
||||
fs /* ERROR "not enough arguments" */ ()
|
||||
fs(g0 /* ERROR "used as value" */ ())
|
||||
fs(g1 /* ERROR "cannot use .* in argument" */ ())
|
||||
fs(g2 /* ERROR "too many arguments" */ ())
|
||||
|
@ -29,10 +29,10 @@ func assignments0() (int, int) {
|
||||
|
||||
a, b, c = <- /* ERROR "cannot assign [1-9]+ values to [1-9]+ variables" */ ch
|
||||
|
||||
return /* ERROR "wrong number of return values" */
|
||||
return /* ERROR "wrong number of return values" */ 1
|
||||
return /* ERROR "not enough return values\n\thave \(\)\n\twant \(int, int\)" */
|
||||
return 1 /* ERROR "not enough return values\n\thave \(number\)\n\twant \(int, int\)" */
|
||||
return 1, 2
|
||||
return /* ERROR "wrong number of return values" */ 1, 2, 3
|
||||
return 1, 2, 3 /* ERROR "too many return values\n\thave \(number, number, number\)\n\twant \(int, int\)" */
|
||||
}
|
||||
|
||||
func assignments1() {
|
||||
@ -81,12 +81,12 @@ func assignments1() {
|
||||
// test cases for issue 5500
|
||||
_ = func() (int, bool) {
|
||||
var m map[int]int
|
||||
return /* ERROR "wrong number of return values" */ m[0]
|
||||
return m /* ERROR "not enough return values" */ [0]
|
||||
}
|
||||
|
||||
g := func(int, bool){}
|
||||
var m map[int]int
|
||||
g(m[0]) /* ERROR "not enough arguments" */
|
||||
g(m /* ERROR "not enough arguments" */ [0])
|
||||
|
||||
// assignments to _
|
||||
_ = nil /* ERROR "use of untyped nil" */
|
||||
@ -380,15 +380,15 @@ func returns0() {
|
||||
|
||||
func returns1(x float64) (int, *float64) {
|
||||
return 0, &x
|
||||
return /* ERROR wrong number of return values */
|
||||
return /* ERROR not enough return values */
|
||||
return "foo" /* ERROR "cannot .* in return statement" */, x /* ERROR "cannot use .* in return statement" */
|
||||
return /* ERROR wrong number of return values */ 0, &x, 1
|
||||
return 0, &x, 1 /* ERROR too many return values */
|
||||
}
|
||||
|
||||
func returns2() (a, b int) {
|
||||
return
|
||||
return 1, "foo" /* ERROR cannot use .* in return statement */
|
||||
return /* ERROR wrong number of return values */ 1, 2, 3
|
||||
return 1, 2, 3 /* ERROR too many return values */
|
||||
{
|
||||
type a int
|
||||
return 1, 2
|
||||
|
@ -312,7 +312,7 @@ var _ = f7(1.2, 3 /* ERROR does not match */ )
|
||||
|
||||
func f8[A, B any](A, B, ...B) int { panic(0) }
|
||||
|
||||
var _ = f8(1) /* ERROR not enough arguments */
|
||||
var _ = f8(1 /* ERROR not enough arguments */ )
|
||||
var _ = f8(1, 2.3)
|
||||
var _ = f8(1, 2.3, 3.4, 4.5)
|
||||
var _ = f8(1, 2.3, 3.4, 4 /* ERROR does not match */ )
|
||||
|
@ -183,7 +183,7 @@ func _() {
|
||||
|
||||
func _() int {
|
||||
var x, y int
|
||||
return /* ERROR wrong number of return values */ x, y
|
||||
return x, y /* ERROR too many return values */
|
||||
}
|
||||
|
||||
// Short variable declarations must declare at least one new non-blank variable.
|
||||
|
@ -19,7 +19,7 @@ func h() (_ int, _ error) {
|
||||
}
|
||||
|
||||
func i() (int, error) {
|
||||
return // ERROR "not enough arguments to return|wrong number of return values"
|
||||
return // ERROR "not enough return values|not enough arguments to return"
|
||||
}
|
||||
|
||||
func f1() (_ int, err error) {
|
||||
|
@ -7,7 +7,7 @@
|
||||
package main
|
||||
|
||||
func foo() (int, int) {
|
||||
return 2.3 // ERROR "not enough arguments to return\n\thave \(number\)\n\twant \(int, int\)|not enough arguments to return|wrong number of return values"
|
||||
return 2.3 // ERROR "not enough return values\n\thave \(number\)\n\twant \(int, int\)|not enough arguments to return"
|
||||
}
|
||||
|
||||
func foo2() {
|
||||
@ -16,19 +16,19 @@ func foo2() {
|
||||
|
||||
func foo3(v int) (a, b, c, d int) {
|
||||
if v >= 0 {
|
||||
return 1 // ERROR "not enough arguments to return\n\thave \(number\)\n\twant \(int, int, int, int\)|not enough arguments to return|wrong number of return values"
|
||||
return 1 // ERROR "not enough return values\n\thave \(number\)\n\twant \(int, int, int, int\)|not enough arguments to return"
|
||||
}
|
||||
return 2, 3 // ERROR "not enough arguments to return\n\thave \(number, number\)\n\twant \(int, int, int, int\)|not enough arguments to return|wrong number of return values"
|
||||
return 2, 3 // ERROR "not enough return values\n\thave \(number, number\)\n\twant \(int, int, int, int\)|not enough arguments to return"
|
||||
}
|
||||
|
||||
func foo4(name string) (string, int) {
|
||||
switch name {
|
||||
case "cow":
|
||||
return "moo" // ERROR "not enough arguments to return\n\thave \(string\)\n\twant \(string, int\)|not enough arguments to return|wrong number of return values"
|
||||
return "moo" // ERROR "not enough return values\n\thave \(string\)\n\twant \(string, int\)|not enough arguments to return"
|
||||
case "dog":
|
||||
return "dog", 10, true // ERROR "too many arguments to return\n\thave \(string, number, bool\)\n\twant \(string, int\)|too many values in return statement|wrong number of return values"
|
||||
return "dog", 10, true // ERROR "too many return values\n\thave \(string, number, bool\)\n\twant \(string, int\)|too many arguments to return"
|
||||
case "fish":
|
||||
return "" // ERROR "not enough arguments to return\n\thave \(string\)\n\twant \(string, int\)|not enough arguments to return|wrong number of return values"
|
||||
return "" // ERROR "not enough return values\n\thave \(string\)\n\twant \(string, int\)|not enough arguments to return"
|
||||
default:
|
||||
return "lizard", 10
|
||||
}
|
||||
@ -40,14 +40,14 @@ type U float64
|
||||
|
||||
func foo5() (S, T, U) {
|
||||
if false {
|
||||
return "" // ERROR "not enough arguments to return\n\thave \(string\)\n\twant \(S, T, U\)|not enough arguments to return|wrong number of return values"
|
||||
return "" // ERROR "not enough return values\n\thave \(string\)\n\twant \(S, T, U\)|not enough arguments to return"
|
||||
} else {
|
||||
ptr := new(T)
|
||||
return ptr // ERROR "not enough arguments to return\n\thave \(\*T\)\n\twant \(S, T, U\)|not enough arguments to return|wrong number of return values"
|
||||
return ptr // ERROR "not enough return values\n\thave \(\*T\)\n\twant \(S, T, U\)|not enough arguments to return"
|
||||
}
|
||||
return new(S), 12.34, 1 + 0i, 'r', true // ERROR "too many arguments to return\n\thave \(\*S, number, number, number, bool\)\n\twant \(S, T, U\)|too many values in return statement|wrong number of return values"
|
||||
return new(S), 12.34, 1 + 0i, 'r', true // ERROR "too many return values\n\thave \(\*S, number, number, number, bool\)\n\twant \(S, T, U\)|too many arguments to return"
|
||||
}
|
||||
|
||||
func foo6() (T, string) {
|
||||
return "T", true, true // ERROR "too many arguments to return\n\thave \(string, bool, bool\)\n\twant \(T, string\)|too many values in return statement|wrong number of return values"
|
||||
return "T", true, true // ERROR "too many return values\n\thave \(string, bool, bool\)\n\twant \(T, string\)|too many arguments to return"
|
||||
}
|
||||
|
@ -9,5 +9,5 @@ package main
|
||||
func f(a int, b ...int) {}
|
||||
|
||||
func main() {
|
||||
f(nil...) // ERROR "not enough arguments in call to f$"
|
||||
f(nil...) // ERROR "not enough arguments in call to f\n\thave \(nil\)\n\twant \(int, \[\]int\)|not enough arguments"
|
||||
}
|
||||
|
24
test/fixedbugs/issue48834.go
Normal file
24
test/fixedbugs/issue48834.go
Normal file
@ -0,0 +1,24 @@
|
||||
// errorcheck
|
||||
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
|
||||
func _() (int, error) {
|
||||
return 1 // ERROR "not enough (arguments to return|return values)\n\thave \(number\)\n\twant \(int, error\)"
|
||||
}
|
||||
|
||||
func _() (int, error) {
|
||||
var x int
|
||||
return x // ERROR "not enough (arguments to return|return values)\n\thave \(int\)\n\twant \(int, error\)"
|
||||
}
|
||||
|
||||
func _() int {
|
||||
return 1, 2 // ERROR "too many (arguments to return|return values)\n\thave \(number, number\)\n\twant \(int\)"
|
||||
}
|
||||
|
||||
func _() {
|
||||
return 1 // ERROR "too many arguments to return\n\thave \(number\)\n\twant \(\)|no result values expected"
|
||||
}
|
25
test/fixedbugs/issue48835.go
Normal file
25
test/fixedbugs/issue48835.go
Normal file
@ -0,0 +1,25 @@
|
||||
// errorcheck
|
||||
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
|
||||
func f0()
|
||||
func f1(_ int)
|
||||
func f2(_, _ int)
|
||||
func f2ddd(_, _ int, _ ...int)
|
||||
|
||||
func f() {
|
||||
var x int
|
||||
f0(1) // ERROR "too many arguments in call to f0\n\thave \(number\)\n\twant \(\)"
|
||||
f0(x) // ERROR "too many arguments in call to f0\n\thave \(int\)\n\twant \(\)"
|
||||
f1() // ERROR "not enough arguments in call to f1\n\thave \(\)\n\twant \(int\)"
|
||||
f1(1, 2) // ERROR "too many arguments in call to f1\n\thave \(number, number\)\n\twant \(int\)"
|
||||
f2(1) // ERROR "not enough arguments in call to f2\n\thave \(number\)\n\twant \(int, int\)"
|
||||
f2(1, "foo", true) // ERROR "too many arguments in call to f2\n\thave \(number, string, bool\)\n\twant \(int, int\)"
|
||||
f2ddd(1) // ERROR "not enough arguments in call to f2ddd\n\thave \(number\)\n\twant \(int, int, \.\.\.int\)"
|
||||
f2ddd(1, 2)
|
||||
f2ddd(1, 2, 3)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user