cmd/compile/internal/types2: refactor untyped conversions

Based on https://golang.org/cl/284256 for go/types.
Brings this code more in line with go/types.

Adjusted various tests to match new error messages which
generally are now better: for assignment errors, instead
of a generic "cannot convert" we now say "cannot use"
followed by a clearer reason as to why not.

Major differences to go/types with respect to the changed
files:

- Some of the new code now returns error codes, but they
  are only used internally for now, and not reported with
  errors.

- go/types does not "convert" untyped nil values to target
  types, but here we do. This is unchanged from how types2
  handled this before this CL.

Change-Id: If45336d7ee679ece100f6d9d9f291a6ea55004d8
Reviewed-on: https://go-review.googlesource.com/c/go/+/302757
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2021-03-17 22:13:16 -07:00
parent 0265b6475f
commit 8f19394b62
23 changed files with 300 additions and 275 deletions

View file

@ -415,7 +415,8 @@ func AssertableTo(V *Interface, T Type) bool {
// AssignableTo reports whether a value of type V is assignable to a variable of type T. // AssignableTo reports whether a value of type V is assignable to a variable of type T.
func AssignableTo(V, T Type) bool { func AssignableTo(V, T Type) bool {
x := operand{mode: value, typ: V} x := operand{mode: value, typ: V}
return x.assignableTo(nil, T, nil) // check not needed for non-constant x ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x
return ok
} }
// ConvertibleTo reports whether a value of type V is convertible to a value of type T. // ConvertibleTo reports whether a value of type V is convertible to a value of type T.

View file

@ -33,8 +33,8 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
// spec: "If an untyped constant is assigned to a variable of interface // spec: "If an untyped constant is assigned to a variable of interface
// type or the blank identifier, the constant is first converted to type // type or the blank identifier, the constant is first converted to type
// bool, rune, int, float64, complex128 or string respectively, depending // bool, rune, int, float64, complex128 or string respectively, depending
// on whether the value is a boolean, rune, integer, floating-point, complex, // on whether the value is a boolean, rune, integer, floating-point,
// or string constant." // complex, or string constant."
if x.isNil() { if x.isNil() {
if T == nil { if T == nil {
check.errorf(x, "use of untyped nil in %s", context) check.errorf(x, "use of untyped nil in %s", context)
@ -44,10 +44,27 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
} else if T == nil || IsInterface(T) { } else if T == nil || IsInterface(T) {
target = Default(x.typ) target = Default(x.typ)
} }
check.convertUntyped(x, target) newType, val, code := check.implicitTypeAndValue(x, target)
if x.mode == invalid { if code != 0 {
msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
switch code {
case _TruncatedFloat:
msg += " (truncated)"
case _NumericOverflow:
msg += " (overflows)"
}
check.error(x, msg)
x.mode = invalid
return return
} }
if val != nil {
x.val = val
check.updateExprVal(x.expr, val)
}
if newType != x.typ {
x.typ = newType
check.updateExprType(x.expr, newType, false)
}
} }
// x.typ is typed // x.typ is typed
@ -63,7 +80,8 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
return return
} }
if reason := ""; !x.assignableTo(check, T, &reason) { reason := ""
if ok, _ := x.assignableTo(check, T, &reason); !ok {
if check.conf.CompilerErrorMessages { if check.conf.CompilerErrorMessages {
check.errorf(x, "incompatible type: cannot use %s as %s value", x, T) check.errorf(x, "incompatible type: cannot use %s as %s value", x, T)
} else { } else {

View file

@ -95,23 +95,25 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
// spec: "As a special case, append also accepts a first argument assignable // spec: "As a special case, append also accepts a first argument assignable
// to type []byte with a second argument of string type followed by ... . // to type []byte with a second argument of string type followed by ... .
// This form appends the bytes of the string. // This form appends the bytes of the string.
if nargs == 2 && call.HasDots && x.assignableTo(check, NewSlice(universeByte), nil) { if nargs == 2 && call.HasDots {
arg(x, 1) if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
if x.mode == invalid { arg(x, 1)
return if x.mode == invalid {
} return
if isString(x.typ) {
if check.Types != nil {
sig := makeSig(S, S, x.typ)
sig.variadic = true
check.recordBuiltinType(call.Fun, sig)
} }
x.mode = value if isString(x.typ) {
x.typ = S if check.Types != nil {
break sig := makeSig(S, S, x.typ)
sig.variadic = true
check.recordBuiltinType(call.Fun, sig)
}
x.mode = value
x.typ = S
break
}
alist = append(alist, *x)
// fallthrough
} }
alist = append(alist, *x)
// fallthrough
} }
// check general case by creating custom signature // check general case by creating custom signature

View file

@ -426,7 +426,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, args []*o
// check arguments // check arguments
for i, a := range args { for i, a := range args {
check.assignment(a, sigParams.vars[i].typ, "argument") check.assignment(a, sigParams.vars[i].typ, check.sprintf("argument to %s", call.Fun))
} }
return return

View file

@ -83,7 +83,7 @@ func (check *Checker) conversion(x *operand, T Type) {
// exported API call, i.e., when all methods have been type-checked. // exported API call, i.e., when all methods have been type-checked.
func (x *operand) convertibleTo(check *Checker, T Type) bool { func (x *operand) convertibleTo(check *Checker, T Type) bool {
// "x is assignable to T" // "x is assignable to T"
if x.assignableTo(check, T, nil) { if ok, _ := x.assignableTo(check, T, nil); ok {
return true return true
} }

View file

@ -40,7 +40,7 @@ func (t T1[[ /* ERROR must be an identifier */ ]int]) m2() {}
// and usually should be avoided. There are some notable exceptions; e.g., // and usually should be avoided. There are some notable exceptions; e.g.,
// sometimes it makes sense to use the identifier "copy" which happens to // sometimes it makes sense to use the identifier "copy" which happens to
// also be the name of a predeclared built-in function. // also be the name of a predeclared built-in function.
func (t T1[int]) m3() { var _ int = 42 /* ERROR cannot convert 42 .* to int */ } func (t T1[int]) m3() { var _ int = 42 /* ERROR cannot use 42 .* as int */ }
// The names of the type parameters used in a parameterized receiver // The names of the type parameters used in a parameterized receiver
// type don't have to match the type parameter names in the declaration // type don't have to match the type parameter names in the declaration

View file

@ -145,11 +145,11 @@ func opName(e *syntax.Operation) string {
return "" return ""
} }
// Entries must be "" or end with a space.
var op2str1 = [...]string{ var op2str1 = [...]string{
syntax.Xor: "bitwise complement", syntax.Xor: "bitwise complement",
} }
// This is only used for operations that may cause overflow.
var op2str2 = [...]string{ var op2str2 = [...]string{
syntax.Add: "addition", syntax.Add: "addition",
syntax.Sub: "subtraction", syntax.Sub: "subtraction",
@ -410,11 +410,51 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c
return false return false
} }
// representable checks that a constant operand is representable in the given basic type. // An errorCode is a (constant) value uniquely identifing a specific error.
type errorCode int
// The following error codes are "borrowed" from go/types which codes for
// all errors. Here we list the few codes currently needed by the various
// conversion checking functions.
// Eventually we will switch to reporting codes for all errors, using a
// an error code table shared between types2 and go/types.
const (
_ = errorCode(iota)
_TruncatedFloat
_NumericOverflow
_InvalidConstVal
_InvalidUntypedConversion
// The following error codes are only returned by operand.assignableTo
// and none of its callers use the error. Still, we keep returning the
// error codes to make the transition to reporting error codes all the
// time easier in the future.
_IncompatibleAssign
_InvalidIfaceAssign
_InvalidChanAssign
)
// representable checks that a constant operand is representable in the given
// basic type.
func (check *Checker) representable(x *operand, typ *Basic) { func (check *Checker) representable(x *operand, typ *Basic) {
v, code := check.representation(x, typ)
if code != 0 {
check.invalidConversion(code, x, typ)
x.mode = invalid
return
}
assert(v != nil)
x.val = v
}
// representation returns the representation of the constant operand x as the
// basic type typ.
//
// If no such representation is possible, it returns a non-zero error code.
func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, errorCode) {
assert(x.mode == constant_) assert(x.mode == constant_)
if !representableConst(x.val, check, typ, &x.val) { v := x.val
var msg string if !representableConst(x.val, check, typ, &v) {
if isNumeric(x.typ) && isNumeric(typ) { if isNumeric(x.typ) && isNumeric(typ) {
// numeric conversion : error msg // numeric conversion : error msg
// //
@ -424,16 +464,25 @@ func (check *Checker) representable(x *operand, typ *Basic) {
// float -> float : overflows // float -> float : overflows
// //
if !isInteger(x.typ) && isInteger(typ) { if !isInteger(x.typ) && isInteger(typ) {
msg = "%s truncated to %s" return nil, _TruncatedFloat
} else { } else {
msg = "%s overflows %s" return nil, _NumericOverflow
} }
} else {
msg = "cannot convert %s to %s"
} }
check.errorf(x, msg, x, typ) return nil, _InvalidConstVal
x.mode = invalid
} }
return v, 0
}
func (check *Checker) invalidConversion(code errorCode, x *operand, target Type) {
msg := "cannot convert %s to %s"
switch code {
case _TruncatedFloat:
msg = "%s truncated to %s"
case _NumericOverflow:
msg = "%s overflows %s"
}
check.errorf(x, msg, x, target)
} }
// updateExprType updates the type of x to typ and invokes itself // updateExprType updates the type of x to typ and invokes itself
@ -592,13 +641,33 @@ func (check *Checker) updateExprVal(x syntax.Expr, val constant.Value) {
// convertUntyped attempts to set the type of an untyped value to the target type. // convertUntyped attempts to set the type of an untyped value to the target type.
func (check *Checker) convertUntyped(x *operand, target Type) { func (check *Checker) convertUntyped(x *operand, target Type) {
target = expand(target) newType, val, code := check.implicitTypeAndValue(x, target)
if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] { if code != 0 {
check.invalidConversion(code, x, target.Underlying())
x.mode = invalid
return return
} }
if val != nil {
x.val = val
check.updateExprVal(x.expr, val)
}
if newType != x.typ {
x.typ = newType
check.updateExprType(x.expr, newType, false)
}
}
// TODO(gri) Sloppy code - clean up. This function is central // implicitTypeAndValue returns the implicit type of x when used in a context
// to assignment and expression checking. // where the target type is expected. If no such implicit conversion is
// possible, it returns a nil Type and non-zero error code.
//
// If x is a constant operand, the returned constant.Value will be the
// representation of x in this context.
func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, constant.Value, errorCode) {
target = expand(target)
if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] {
return x.typ, nil, 0
}
if isUntyped(target) { if isUntyped(target) {
// both x and target are untyped // both x and target are untyped
@ -606,129 +675,84 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
tkind := target.(*Basic).kind tkind := target.(*Basic).kind
if isNumeric(x.typ) && isNumeric(target) { if isNumeric(x.typ) && isNumeric(target) {
if xkind < tkind { if xkind < tkind {
x.typ = target return target, nil, 0
check.updateExprType(x.expr, target, false)
} }
} else if xkind != tkind { } else if xkind != tkind {
goto Error return nil, nil, _InvalidUntypedConversion
} }
return return x.typ, nil, 0
} }
// In case of a type parameter, conversion must succeed against
// all types enumerated by the type parameter bound.
// TODO(gri) We should not need this because we have the code
// for Sum types in convertUntypedInternal. But at least one
// test fails. Investigate.
if t := asTypeParam(target); t != nil {
types := t.Bound().allTypes
if types == nil {
goto Error
}
for _, t := range unpack(types) {
x := *x // make a copy; convertUntypedInternal modifies x
check.convertUntypedInternal(&x, t, false)
if x.mode == invalid {
goto Error
}
}
x.typ = target
check.updateExprType(x.expr, target, true)
return
}
check.convertUntypedInternal(x, target, true)
return
Error:
// TODO(gri) better error message (explain cause)
check.errorf(x, "cannot convert %s to %s", x, target)
x.mode = invalid
}
// convertUntypedInternal should only be called by convertUntyped.
func (check *Checker) convertUntypedInternal(x *operand, target Type, update bool) {
assert(isTyped(target))
if x.isNil() { if x.isNil() {
assert(isUntyped(x.typ)) assert(isUntyped(x.typ))
if hasNil(target) { if hasNil(target) {
goto OK return target, nil, 0
} }
goto Error return nil, nil, _InvalidUntypedConversion
} }
// typed target
switch t := optype(target).(type) { switch t := optype(target).(type) {
case *Basic: case *Basic:
if x.mode == constant_ { if x.mode == constant_ {
check.representable(x, t) v, code := check.representation(x, t)
if x.mode == invalid { if code != 0 {
return return nil, nil, code
} }
// expression value may have been rounded - update if needed return target, v, code
if update { }
check.updateExprVal(x.expr, x.val) // Non-constant untyped values may appear as the
// result of comparisons (untyped bool), intermediate
// (delayed-checked) rhs operands of shifts, and as
// the value nil.
switch x.typ.(*Basic).kind {
case UntypedBool:
if !isBoolean(target) {
return nil, nil, _InvalidUntypedConversion
} }
} else { case UntypedInt, UntypedRune, UntypedFloat, UntypedComplex:
// Non-constant untyped values may appear as the if !isNumeric(target) {
// result of comparisons (untyped bool), intermediate return nil, nil, _InvalidUntypedConversion
// (delayed-checked) rhs operands of shifts, and as
// the value nil. Nil was handled upfront.
switch x.typ.(*Basic).kind {
case UntypedBool:
if !isBoolean(target) {
goto Error
}
case UntypedInt, UntypedRune, UntypedFloat, UntypedComplex:
if !isNumeric(target) {
goto Error
}
case UntypedString:
// Non-constant untyped string values are not
// permitted by the spec and should not occur.
unreachable()
default:
goto Error
} }
case UntypedString:
// Non-constant untyped string values are not permitted by the spec and
// should not occur during normal typechecking passes, but this path is
// reachable via the AssignableTo API.
if !isString(target) {
return nil, nil, _InvalidUntypedConversion
}
default:
return nil, nil, _InvalidUntypedConversion
} }
case *Sum: case *Sum:
t.is(func(t Type) bool { ok := t.is(func(t Type) bool {
check.convertUntypedInternal(x, t, false) target, _, _ := check.implicitTypeAndValue(x, t)
return x.mode != invalid return target != nil
}) })
if !ok {
return nil, nil, _InvalidUntypedConversion
}
case *Interface: case *Interface:
// Update operand types to the default type rather then the target // Update operand types to the default type rather than the target
// (interface) type: values must have concrete dynamic types. // (interface) type: values must have concrete dynamic types.
// Untyped nil was handled upfront. // Untyped nil was handled upfront.
check.completeInterface(nopos, t) check.completeInterface(nopos, t)
if !t.Empty() { if !t.Empty() {
goto Error // cannot assign untyped values to non-empty interfaces return nil, nil, _InvalidUntypedConversion // cannot assign untyped values to non-empty interfaces
} }
target = Default(x.typ) return Default(x.typ), nil, 0 // default type for nil is nil
default: default:
goto Error return nil, nil, _InvalidUntypedConversion
} }
return target, nil, 0
OK:
x.typ = target
if update {
check.updateExprType(x.expr, target, true)
}
return
Error:
check.errorf(x, "cannot convert %s to %s", x, target)
x.mode = invalid
} }
func (check *Checker) comparison(x, y *operand, op syntax.Operator) { func (check *Checker) comparison(x, y *operand, op syntax.Operator) {
// spec: "In any comparison, the first operand must be assignable // spec: "In any comparison, the first operand must be assignable
// to the type of the second operand, or vice versa." // to the type of the second operand, or vice versa."
err := "" err := ""
if x.assignableTo(check, y.typ, nil) || y.assignableTo(check, x.typ, nil) { xok, _ := x.assignableTo(check, y.typ, nil)
yok, _ := y.assignableTo(check, x.typ, nil)
if xok || yok {
defined := false defined := false
switch op { switch op {
case syntax.Eql, syntax.Neq: case syntax.Eql, syntax.Neq:

View file

@ -236,65 +236,45 @@ func (x *operand) setConst(k syntax.LitKind, lit string) {
// isNil reports whether x is a typed or the untyped nil value. // isNil reports whether x is a typed or the untyped nil value.
func (x *operand) isNil() bool { return x.mode == nilvalue } func (x *operand) isNil() bool { return x.mode == nilvalue }
// TODO(gri) The functions operand.assignableTo, checker.convertUntyped, // assignableTo reports whether x is assignable to a variable of type T. If the
// checker.representable, and checker.assignment are // result is false and a non-nil reason is provided, it may be set to a more
// overlapping in functionality. Need to simplify and clean up. // detailed explanation of the failure (result != ""). The returned error code
// is only valid if the (first) result is false. The check parameter may be nil
// assignableTo reports whether x is assignable to a variable of type T. // if assignableTo is invoked through an exported API call, i.e., when all
// If the result is false and a non-nil reason is provided, it may be set // methods have been type-checked.
// to a more detailed explanation of the failure (result != ""). func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, errorCode) {
// The check parameter may be nil if assignableTo is invoked through
// an exported API call, i.e., when all methods have been type-checked.
func (x *operand) assignableTo(check *Checker, T Type, reason *string) bool {
if x.mode == invalid || T == Typ[Invalid] { if x.mode == invalid || T == Typ[Invalid] {
return true // avoid spurious errors return true, 0 // avoid spurious errors
} }
V := x.typ V := x.typ
// x's type is identical to T // x's type is identical to T
if check.identical(V, T) { if check.identical(V, T) {
return true return true, 0
} }
Vu := optype(V) Vu := optype(V)
Tu := optype(T) Tu := optype(T)
// x is an untyped value representable by a value of type T // x is an untyped value representable by a value of type T.
// TODO(gri) This is borrowing from checker.convertUntyped and
// checker.representable. Need to clean up.
if isUntyped(Vu) { if isUntyped(Vu) {
switch t := Tu.(type) { if t, ok := Tu.(*Sum); ok {
case *Basic:
if x.isNil() && t.kind == UnsafePointer {
return true
}
if x.mode == constant_ {
return representableConst(x.val, check, t, nil)
}
// The result of a comparison is an untyped boolean,
// but may not be a constant.
if Vb, _ := Vu.(*Basic); Vb != nil {
return Vb.kind == UntypedBool && isBoolean(Tu)
}
case *Sum:
return t.is(func(t Type) bool { return t.is(func(t Type) bool {
// TODO(gri) this could probably be more efficient // TODO(gri) this could probably be more efficient
return x.assignableTo(check, t, reason) ok, _ := x.assignableTo(check, t, reason)
}) return ok
case *Interface: }), _IncompatibleAssign
check.completeInterface(nopos, t)
return x.isNil() || t.Empty()
case *Pointer, *Signature, *Slice, *Map, *Chan:
return x.isNil()
} }
newType, _, _ := check.implicitTypeAndValue(x, Tu)
return newType != nil, _IncompatibleAssign
} }
// Vu is typed // Vu is typed
// x's type V and T have identical underlying types // x's type V and T have identical underlying types
// and at least one of V or T is not a named type // and at least one of V or T is not a named type
if check.identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { if check.identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) {
return true return true, 0
} }
// T is an interface type and x implements T // T is an interface type and x implements T
@ -312,9 +292,9 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) bool {
*reason = "missing method " + m.Name() *reason = "missing method " + m.Name()
} }
} }
return false return false, _InvalidIfaceAssign
} }
return true return true, 0
} }
// x is a bidirectional channel value, T is a channel // x is a bidirectional channel value, T is a channel
@ -322,11 +302,11 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) bool {
// and at least one of V or T is not a named type // and at least one of V or T is not a named type
if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv { if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
if Tc, ok := Tu.(*Chan); ok && check.identical(Vc.elem, Tc.elem) { if Tc, ok := Tu.(*Chan); ok && check.identical(Vc.elem, Tc.elem) {
return !isNamed(V) || !isNamed(T) return !isNamed(V) || !isNamed(T), _InvalidChanAssign
} }
} }
return false return false, _IncompatibleAssign
} }
// kind2tok translates syntax.LitKinds into token.Tokens. // kind2tok translates syntax.LitKinds into token.Tokens.

View file

@ -35,9 +35,9 @@ func append1() {
type S []byte type S []byte
type T string type T string
var t T var t T
_ = append(s, "foo" /* ERROR cannot convert */ ) _ = append(s, "foo" /* ERROR cannot use .* in argument to append */ )
_ = append(s, "foo"...) _ = append(s, "foo"...)
_ = append(S(s), "foo" /* ERROR cannot convert */ ) _ = append(S(s), "foo" /* ERROR cannot use .* in argument to append */ )
_ = append(S(s), "foo"...) _ = append(S(s), "foo"...)
_ = append(s, t /* ERROR cannot use t */ ) _ = append(s, t /* ERROR cannot use t */ )
_ = append(s, t...) _ = append(s, t...)
@ -283,7 +283,7 @@ func delete1() {
delete() // ERROR not enough arguments delete() // ERROR not enough arguments
delete(1) // ERROR not enough arguments delete(1) // ERROR not enough arguments
delete(1, 2, 3) // ERROR too many arguments delete(1, 2, 3) // ERROR too many arguments
delete(m, 0 /* ERROR cannot convert */) delete(m, 0 /* ERROR cannot use */)
delete(m, s) delete(m, s)
_ = delete /* ERROR used as value */ (m, s) _ = delete /* ERROR used as value */ (m, s)

View file

@ -111,13 +111,13 @@ func _() {
const ( const (
_ byte = 255 + iota _ byte = 255 + iota
/* some gap */ /* some gap */
_ // ERROR overflows byte _ // ERROR overflows
/* some gap */ /* some gap */
/* some gap */ _ /* ERROR overflows byte */; _ /* ERROR overflows byte */ /* some gap */ _ /* ERROR overflows */; _ /* ERROR overflows */
/* some gap */ /* some gap */
_ = 255 + iota _ = 255 + iota
_ = byte /* ERROR overflows byte */ (255) + iota _ = byte /* ERROR overflows */ (255) + iota
_ /* ERROR overflows byte */ _ /* ERROR overflows */
) )
// Test cases from issue. // Test cases from issue.

View file

@ -40,17 +40,17 @@ func f_double /* ERROR "redeclared" */ () {}
// Verify by checking that errors are reported. // Verify by checking that errors are reported.
func (T /* ERROR "undeclared" */ ) _() {} func (T /* ERROR "undeclared" */ ) _() {}
func (T1) _(undeclared /* ERROR "undeclared" */ ) {} func (T1) _(undeclared /* ERROR "undeclared" */ ) {}
func (T1) _() int { return "foo" /* ERROR "cannot convert" */ } func (T1) _() int { return "foo" /* ERROR "cannot use .* in return statement" */ }
// Methods with undeclared receiver type can still be checked. // Methods with undeclared receiver type can still be checked.
// Verify by checking that errors are reported. // Verify by checking that errors are reported.
func (Foo /* ERROR "undeclared" */ ) m() {} func (Foo /* ERROR "undeclared" */ ) m() {}
func (Foo /* ERROR "undeclared" */ ) m(undeclared /* ERROR "undeclared" */ ) {} func (Foo /* ERROR "undeclared" */ ) m(undeclared /* ERROR "undeclared" */ ) {}
func (Foo /* ERROR "undeclared" */ ) m() int { return "foo" /* ERROR "cannot convert" */ } func (Foo /* ERROR "undeclared" */ ) m() int { return "foo" /* ERROR "cannot use .* in return statement" */ }
func (Foo /* ERROR "undeclared" */ ) _() {} func (Foo /* ERROR "undeclared" */ ) _() {}
func (Foo /* ERROR "undeclared" */ ) _(undeclared /* ERROR "undeclared" */ ) {} func (Foo /* ERROR "undeclared" */ ) _(undeclared /* ERROR "undeclared" */ ) {}
func (Foo /* ERROR "undeclared" */ ) _() int { return "foo" /* ERROR "cannot convert" */ } func (Foo /* ERROR "undeclared" */ ) _() int { return "foo" /* ERROR "cannot use .* in return statement" */ }
// Receiver declarations are regular parameter lists; // Receiver declarations are regular parameter lists;
// receiver types may use parentheses, and the list // receiver types may use parentheses, and the list

View file

@ -95,7 +95,7 @@ func indexes() {
_ = &s /* ERROR "cannot take address" */ [:10] _ = &s /* ERROR "cannot take address" */ [:10]
var m map[string]int var m map[string]int
_ = m[0 /* ERROR "cannot convert" */ ] _ = m[0 /* ERROR "cannot use .* in map index" */ ]
_ = m /* ERROR "cannot slice" */ ["foo" : "bar"] _ = m /* ERROR "cannot slice" */ ["foo" : "bar"]
_ = m["foo"] _ = m["foo"]
// ok is of type bool // ok is of type bool
@ -103,7 +103,7 @@ func indexes() {
var ok mybool var ok mybool
_, ok = m["bar"] _, ok = m["bar"]
_ = ok _ = ok
_ = m[0 /* ERROR "cannot convert 0" */ ] + "foo" // ERROR "cannot convert" _ = m[0 /* ERROR "cannot use 0" */ ] + "foo" // ERROR "cannot convert"
var t string var t string
_ = t[- /* ERROR "negative" */ 1] _ = t[- /* ERROR "negative" */ 1]
@ -186,7 +186,7 @@ func struct_literals() {
_ = T1{aa /* ERROR "unknown field" */ : 0} _ = T1{aa /* ERROR "unknown field" */ : 0}
_ = T1{1 /* ERROR "invalid field name" */ : 0} _ = T1{1 /* ERROR "invalid field name" */ : 0}
_ = T1{a: 0, s: "foo", u: 0, a /* ERROR "duplicate field" */: 10} _ = T1{a: 0, s: "foo", u: 0, a /* ERROR "duplicate field" */: 10}
_ = T1{a: "foo" /* ERROR "cannot convert" */ } _ = T1{a: "foo" /* ERROR "cannot use .* in struct literal" */ }
_ = T1{c /* ERROR "unknown field" */ : 0} _ = T1{c /* ERROR "unknown field" */ : 0}
_ = T1{T0: { /* ERROR "missing type" */ }} // struct literal element type may not be elided _ = T1{T0: { /* ERROR "missing type" */ }} // struct literal element type may not be elided
_ = T1{T0: T0{}} _ = T1{T0: T0{}}
@ -197,7 +197,7 @@ func struct_literals() {
_ = T0{1, b /* ERROR "mixture" */ : 2, 3} _ = T0{1, b /* ERROR "mixture" */ : 2, 3}
_ = T0{1, 2} /* ERROR "too few values" */ _ = T0{1, 2} /* ERROR "too few values" */
_ = T0{1, 2, 3, 4 /* ERROR "too many values" */ } _ = T0{1, 2, 3, 4 /* ERROR "too many values" */ }
_ = T0{1, "foo" /* ERROR "cannot convert" */, 3.4 /* ERROR "truncated" */} _ = T0{1, "foo" /* ERROR "cannot use .* in struct literal" */, 3.4 /* ERROR "cannot use .*\(truncated\)" */}
// invalid type // invalid type
type P *struct{ type P *struct{
@ -237,7 +237,7 @@ func array_literals() {
_ = A1{5: 5, 6, 7, 4: 4, 1 /* ERROR "overflows" */ <<100: 4} _ = A1{5: 5, 6, 7, 4: 4, 1 /* ERROR "overflows" */ <<100: 4}
_ = A1{2.0} _ = A1{2.0}
_ = A1{2.1 /* ERROR "truncated" */ } _ = A1{2.1 /* ERROR "truncated" */ }
_ = A1{"foo" /* ERROR "cannot convert" */ } _ = A1{"foo" /* ERROR "cannot use .* in array or slice literal" */ }
// indices must be integer constants // indices must be integer constants
i := 1 i := 1
@ -303,7 +303,7 @@ func slice_literals() {
_ = S0{5: 5, 6, 7, 4: 4, 1 /* ERROR "overflows" */ <<100: 4} _ = S0{5: 5, 6, 7, 4: 4, 1 /* ERROR "overflows" */ <<100: 4}
_ = S0{2.0} _ = S0{2.0}
_ = S0{2.1 /* ERROR "truncated" */ } _ = S0{2.1 /* ERROR "truncated" */ }
_ = S0{"foo" /* ERROR "cannot convert" */ } _ = S0{"foo" /* ERROR "cannot use .* in array or slice literal" */ }
// indices must be resolved correctly // indices must be resolved correctly
const index1 = 1 const index1 = 1
@ -356,8 +356,8 @@ func map_literals() {
_ = M0{} _ = M0{}
_ = M0{1 /* ERROR "missing key" */ } _ = M0{1 /* ERROR "missing key" */ }
_ = M0{1 /* ERROR "cannot convert" */ : 2} _ = M0{1 /* ERROR "cannot use .* in map literal" */ : 2}
_ = M0{"foo": "bar" /* ERROR "cannot convert" */ } _ = M0{"foo": "bar" /* ERROR "cannot use .* in map literal" */ }
_ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 } _ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 }
_ = map[interface{}]int{2: 1, 2 /* ERROR "duplicate key" */ : 1} _ = map[interface{}]int{2: 1, 2 /* ERROR "duplicate key" */ : 1}

View file

@ -354,10 +354,10 @@ func issue26234c() {
func issue35895() { func issue35895() {
// T is defined in this package, don't qualify its name with the package name. // T is defined in this package, don't qualify its name with the package name.
var _ T = 0 // ERROR cannot convert 0 \(untyped int constant\) to T var _ T = 0 // ERROR cannot use 0 \(untyped int constant\) as T
// There is only one package with name syntax imported, only use the (global) package name in error messages. // There is only one package with name syntax imported, only use the (global) package name in error messages.
var _ *syn.File = 0 // ERROR cannot convert 0 \(untyped int constant\) to \*syntax.File var _ *syn.File = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.File
// Because both t1 and t2 have the same global package name (template), // Because both t1 and t2 have the same global package name (template),
// qualify packages with full path name in this case. // qualify packages with full path name in this case.

View file

@ -69,10 +69,10 @@ func assignments1() {
// test cases for issue 5800 // test cases for issue 5800
var ( var (
_ int = nil /* ERROR "cannot convert untyped nil" */ _ int = nil /* ERROR "untyped nil" */
_ [10]int = nil /* ERROR "cannot convert untyped nil" */ _ [10]int = nil /* ERROR "untyped nil" */
_ []byte = nil _ []byte = nil
_ struct{} = nil /* ERROR "cannot convert untyped nil" */ _ struct{} = nil /* ERROR "untyped nil" */
_ func() = nil _ func() = nil
_ map[int]string = nil _ map[int]string = nil
_ chan int = nil _ chan int = nil
@ -182,7 +182,7 @@ func sends() {
var x int var x int
x <- /* ERROR "cannot send" */ x x <- /* ERROR "cannot send" */ x
rch <- /* ERROR "cannot send" */ x rch <- /* ERROR "cannot send" */ x
ch <- "foo" /* ERROR "cannot convert" */ ch <- "foo" /* ERROR "cannot use .* in send" */
ch <- x ch <- x
} }
@ -381,13 +381,13 @@ func returns0() {
func returns1(x float64) (int, *float64) { func returns1(x float64) (int, *float64) {
return 0, &x return 0, &x
return /* ERROR wrong number of return values */ return /* ERROR wrong number of return values */
return "foo" /* ERROR "cannot convert" */, x /* ERROR "cannot use .* in return statement" */ 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 /* ERROR wrong number of return values */ 0, &x, 1
} }
func returns2() (a, b int) { func returns2() (a, b int) {
return return
return 1, "foo" /* ERROR cannot convert */ return 1, "foo" /* ERROR cannot use .* in return statement */
return /* ERROR wrong number of return values */ 1, 2, 3 return /* ERROR wrong number of return values */ 1, 2, 3
{ {
type a int type a int
@ -609,7 +609,7 @@ func switches2() {
// untyped constants are converted to default types // untyped constants are converted to default types
switch 1<<63-1 { switch 1<<63-1 {
} }
switch 1 /* ERROR "overflows int" */ << 63 { switch 1 /* ERROR "cannot use .* as int value.*\(overflows\)" */ << 63 {
} }
var x int var x int
switch 1.0 { switch 1.0 {
@ -631,9 +631,9 @@ func switches2() {
} }
func issue11667() { func issue11667() {
switch 9223372036854775808 /* ERROR "overflows int" */ { switch 9223372036854775808 /* ERROR "cannot use .* as int value.*\(overflows\)" */ {
} }
switch 9223372036854775808 /* ERROR "overflows int" */ { switch 9223372036854775808 /* ERROR "cannot use .* as int value.*\(overflows\)" */ {
case 9223372036854775808: case 9223372036854775808:
} }
var x int var x int

View file

@ -37,7 +37,7 @@ var _ = reverse /* ERROR cannot use generic function reverse */
var _ = reverse[int, float32 /* ERROR got 2 type arguments */ ] ([]int{1, 2, 3}) var _ = reverse[int, float32 /* ERROR got 2 type arguments */ ] ([]int{1, 2, 3})
var _ = reverse[int]([ /* ERROR cannot use */ ]float32{1, 2, 3}) var _ = reverse[int]([ /* ERROR cannot use */ ]float32{1, 2, 3})
var f = reverse[chan int] var f = reverse[chan int]
var _ = f(0 /* ERROR cannot convert 0 .* to \[\]chan int */ ) var _ = f(0 /* ERROR cannot use 0 .* as \[\]chan int */ )
func swap[A, B any](a A, b B) (B, A) { return b, a } func swap[A, B any](a A, b B) (B, A) { return b, a }
@ -310,7 +310,7 @@ func (_ R1[A, B]) _[A /* ERROR redeclared */ any](B)
func _() { func _() {
var r R1[int, string] var r R1[int, string]
r.m1[rune](42, "foo", 'a') r.m1[rune](42, "foo", 'a')
r.m1[rune](42, "foo", 1.2 /* ERROR truncated to rune */) r.m1[rune](42, "foo", 1.2 /* ERROR cannot use .* as rune .* \(truncated\) */)
r.m1(42, "foo", 1.2) // using type inference r.m1(42, "foo", 1.2) // using type inference
var _ float64 = r.m1(42, "foo", 1.2) var _ float64 = r.m1(42, "foo", 1.2)
} }

View file

@ -34,7 +34,7 @@ var bad4 = "a" + 1 // ERROR "literals|incompatible|convert|invalid"
var bad5 = "a" + 'a' // ERROR "literals|incompatible|convert|invalid" var bad5 = "a" + 'a' // ERROR "literals|incompatible|convert|invalid"
var bad6 int = 1.5 // ERROR "convert|truncate" var bad6 int = 1.5 // ERROR "convert|truncate"
var bad7 int = 1e100 // ERROR "overflow|truncated to int" var bad7 int = 1e100 // ERROR "overflow|truncated to int|truncated"
var bad8 float32 = 1e200 // ERROR "overflow" var bad8 float32 = 1e200 // ERROR "overflow"
// but these implicit conversions are okay // but these implicit conversions are okay

View file

@ -13,6 +13,6 @@ var m map[string]int;
func main() { func main() {
println(t["hi"]); // ERROR "non-integer slice index|must be integer|cannot convert" println(t["hi"]); // ERROR "non-integer slice index|must be integer|cannot convert"
println(s["hi"]); // ERROR "non-integer string index|must be integer|cannot convert" println(s["hi"]); // ERROR "non-integer string index|must be integer|cannot convert"
println(m[0]); // ERROR "cannot use.*as type string|cannot convert" println(m[0]); // ERROR "cannot use.*as type string|cannot convert|cannot use"
} }

View file

@ -9,5 +9,5 @@ package main
// Issue 2623 // Issue 2623
var m = map[string]int{ var m = map[string]int{
"abc": 1, "abc": 1,
1: 2, // ERROR "cannot use 1.*as type string in map key|incompatible type|cannot convert" 1: 2, // ERROR "cannot use 1.*as type string in map key|incompatible type|cannot convert|cannot use"
} }

View file

@ -18,14 +18,14 @@ func main() {
// Any implementation must be able to handle these constants at // Any implementation must be able to handle these constants at
// compile time (even though they cannot be assigned to a float64). // compile time (even though they cannot be assigned to a float64).
var _ = 1e646456992 // ERROR "1e\+646456992 overflows float64|floating-point constant overflow|exponent too large|overflows float64" var _ = 1e646456992 // ERROR "1e\+646456992 overflows float64|floating-point constant overflow|exponent too large|overflows float64|overflows"
var _ = 1e64645699 // ERROR "1e\+64645699 overflows float64|floating-point constant overflow|exponent too large|overflows float64" var _ = 1e64645699 // ERROR "1e\+64645699 overflows float64|floating-point constant overflow|exponent too large|overflows float64|overflows"
var _ = 1e6464569 // ERROR "1e\+6464569 overflows float64|floating-point constant overflow|exponent too large|overflows float64" var _ = 1e6464569 // ERROR "1e\+6464569 overflows float64|floating-point constant overflow|exponent too large|overflows float64|overflows"
var _ = 1e646456 // ERROR "1e\+646456 overflows float64|floating-point constant overflow|exponent too large|overflows float64" var _ = 1e646456 // ERROR "1e\+646456 overflows float64|floating-point constant overflow|exponent too large|overflows float64|overflows"
var _ = 1e64645 // ERROR "1e\+64645 overflows float64|floating-point constant overflow|exponent too large|overflows float64" var _ = 1e64645 // ERROR "1e\+64645 overflows float64|floating-point constant overflow|exponent too large|overflows float64|overflows"
var _ = 1e6464 // ERROR "1e\+6464 overflows float64|floating-point constant overflow|overflows float64" var _ = 1e6464 // ERROR "1e\+6464 overflows float64|floating-point constant overflow|overflows float64|overflows"
var _ = 1e646 // ERROR "1e\+646 overflows float64|floating-point constant overflow|overflows float64" var _ = 1e646 // ERROR "1e\+646 overflows float64|floating-point constant overflow|overflows float64|overflows"
var _ = 1e309 // ERROR "1e\+309 overflows float64|floating-point constant overflow|overflows float64" var _ = 1e309 // ERROR "1e\+309 overflows float64|floating-point constant overflow|overflows float64|overflows"
var _ = 1e308 var _ = 1e308
} }

View file

@ -9,9 +9,9 @@
package issue11371 package issue11371
const a int = 1.1 // ERROR "constant 1.1 truncated to integer|floating-point constant truncated to integer|truncated to int" const a int = 1.1 // ERROR "constant 1.1 truncated to integer|floating-point constant truncated to integer|truncated to int|truncated"
const b int = 1e20 // ERROR "overflows int|integer constant overflow|truncated to int" const b int = 1e20 // ERROR "overflows int|integer constant overflow|truncated to int|truncated"
const c int = 1 + 1e-70 // ERROR "constant truncated to integer|truncated to int" const c int = 1 + 1e-70 // ERROR "constant truncated to integer|truncated to int|truncated"
const d int = 1 - 1e-70 // ERROR "constant truncated to integer|truncated to int" const d int = 1 - 1e-70 // ERROR "constant truncated to integer|truncated to int|truncated"
const e int = 1.00000001 // ERROR "constant truncated to integer|truncated to int" const e int = 1.00000001 // ERROR "constant truncated to integer|truncated to int|truncated"
const f int = 0.00000001 // ERROR "constant 1e-08 truncated to integer|floating-point constant truncated to integer|truncated to int" const f int = 0.00000001 // ERROR "constant 1e-08 truncated to integer|floating-point constant truncated to integer|truncated to int|truncated"

View file

@ -10,80 +10,80 @@
package p package p
// failure case in issue // failure case in issue
const _ int64 = 1e-10000 // ERROR "1e\-10000 truncated|.* truncated to int64" const _ int64 = 1e-10000 // ERROR "1e\-10000 truncated|.* truncated to int64|truncated"
const ( const (
_ int64 = 1e10000000 // ERROR "integer too large|truncated to int64" _ int64 = 1e10000000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = 1e1000000 // ERROR "integer too large|truncated to int64" _ int64 = 1e1000000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = 1e100000 // ERROR "integer too large|truncated to int64" _ int64 = 1e100000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = 1e10000 // ERROR "integer too large|truncated to int64" _ int64 = 1e10000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = 1e1000 // ERROR "integer too large|truncated to int64" _ int64 = 1e1000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = 1e100 // ERROR "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows|truncated to int64" _ int64 = 1e100 // ERROR "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows|truncated to int64|truncated"
_ int64 = 1e10 _ int64 = 1e10
_ int64 = 1e1 _ int64 = 1e1
_ int64 = 1e0 _ int64 = 1e0
_ int64 = 1e-1 // ERROR "0\.1 truncated|.* truncated to int64" _ int64 = 1e-1 // ERROR "0\.1 truncated|.* truncated to int64|truncated"
_ int64 = 1e-10 // ERROR "1e\-10 truncated|.* truncated to int64" _ int64 = 1e-10 // ERROR "1e\-10 truncated|.* truncated to int64|truncated"
_ int64 = 1e-100 // ERROR "1e\-100 truncated|.* truncated to int64" _ int64 = 1e-100 // ERROR "1e\-100 truncated|.* truncated to int64|truncated"
_ int64 = 1e-1000 // ERROR "1e\-1000 truncated|.* truncated to int64" _ int64 = 1e-1000 // ERROR "1e\-1000 truncated|.* truncated to int64|truncated"
_ int64 = 1e-10000 // ERROR "1e\-10000 truncated|.* truncated to int64" _ int64 = 1e-10000 // ERROR "1e\-10000 truncated|.* truncated to int64|truncated"
_ int64 = 1e-100000 // ERROR "1e\-100000 truncated|.* truncated to int64" _ int64 = 1e-100000 // ERROR "1e\-100000 truncated|.* truncated to int64|truncated"
_ int64 = 1e-1000000 // ERROR "1e\-1000000 truncated|.* truncated to int64" _ int64 = 1e-1000000 // ERROR "1e\-1000000 truncated|.* truncated to int64|truncated"
) )
const ( const (
_ int64 = -1e10000000 // ERROR "integer too large|truncated to int64" _ int64 = -1e10000000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = -1e1000000 // ERROR "integer too large|truncated to int64" _ int64 = -1e1000000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = -1e100000 // ERROR "integer too large|truncated to int64" _ int64 = -1e100000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = -1e10000 // ERROR "integer too large|truncated to int64" _ int64 = -1e10000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = -1e1000 // ERROR "integer too large|truncated to int64" _ int64 = -1e1000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = -1e100 // ERROR "\-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows|truncated to int64" _ int64 = -1e100 // ERROR "\-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows|truncated to int64|truncated"
_ int64 = -1e10 _ int64 = -1e10
_ int64 = -1e1 _ int64 = -1e1
_ int64 = -1e0 _ int64 = -1e0
_ int64 = -1e-1 // ERROR "\-0\.1 truncated|.* truncated to int64" _ int64 = -1e-1 // ERROR "\-0\.1 truncated|.* truncated to int64|truncated"
_ int64 = -1e-10 // ERROR "\-1e\-10 truncated|.* truncated to int64" _ int64 = -1e-10 // ERROR "\-1e\-10 truncated|.* truncated to int64|truncated"
_ int64 = -1e-100 // ERROR "\-1e\-100 truncated|.* truncated to int64" _ int64 = -1e-100 // ERROR "\-1e\-100 truncated|.* truncated to int64|truncated"
_ int64 = -1e-1000 // ERROR "\-1e\-1000 truncated|.* truncated to int64" _ int64 = -1e-1000 // ERROR "\-1e\-1000 truncated|.* truncated to int64|truncated"
_ int64 = -1e-10000 // ERROR "\-1e\-10000 truncated|.* truncated to int64" _ int64 = -1e-10000 // ERROR "\-1e\-10000 truncated|.* truncated to int64|truncated"
_ int64 = -1e-100000 // ERROR "\-1e\-100000 truncated|.* truncated to int64" _ int64 = -1e-100000 // ERROR "\-1e\-100000 truncated|.* truncated to int64|truncated"
_ int64 = -1e-1000000 // ERROR "\-1e\-1000000 truncated|.* truncated to int64" _ int64 = -1e-1000000 // ERROR "\-1e\-1000000 truncated|.* truncated to int64|truncated"
) )
const ( const (
_ int64 = 1.23456789e10000000 // ERROR "integer too large|truncated to int64" _ int64 = 1.23456789e10000000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = 1.23456789e1000000 // ERROR "integer too large|truncated to int64" _ int64 = 1.23456789e1000000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = 1.23456789e100000 // ERROR "integer too large|truncated to int64" _ int64 = 1.23456789e100000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = 1.23456789e10000 // ERROR "integer too large|truncated to int64" _ int64 = 1.23456789e10000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = 1.23456789e1000 // ERROR "integer too large|truncated to int64" _ int64 = 1.23456789e1000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = 1.23456789e100 // ERROR "12345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows|truncated to int64" _ int64 = 1.23456789e100 // ERROR "12345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows|truncated to int64|truncated"
_ int64 = 1.23456789e10 _ int64 = 1.23456789e10
_ int64 = 1.23456789e1 // ERROR "12\.3457 truncated|.* truncated to int64" _ int64 = 1.23456789e1 // ERROR "12\.3457 truncated|.* truncated to int64|truncated"
_ int64 = 1.23456789e0 // ERROR "1\.23457 truncated|.* truncated to int64" _ int64 = 1.23456789e0 // ERROR "1\.23457 truncated|.* truncated to int64|truncated"
_ int64 = 1.23456789e-1 // ERROR "0\.123457 truncated|.* truncated to int64" _ int64 = 1.23456789e-1 // ERROR "0\.123457 truncated|.* truncated to int64|truncated"
_ int64 = 1.23456789e-10 // ERROR "1\.23457e\-10 truncated|.* truncated to int64" _ int64 = 1.23456789e-10 // ERROR "1\.23457e\-10 truncated|.* truncated to int64|truncated"
_ int64 = 1.23456789e-100 // ERROR "1\.23457e\-100 truncated|.* truncated to int64" _ int64 = 1.23456789e-100 // ERROR "1\.23457e\-100 truncated|.* truncated to int64|truncated"
_ int64 = 1.23456789e-1000 // ERROR "1\.23457e\-1000 truncated|.* truncated to int64" _ int64 = 1.23456789e-1000 // ERROR "1\.23457e\-1000 truncated|.* truncated to int64|truncated"
_ int64 = 1.23456789e-10000 // ERROR "1\.23457e\-10000 truncated|.* truncated to int64" _ int64 = 1.23456789e-10000 // ERROR "1\.23457e\-10000 truncated|.* truncated to int64|truncated"
_ int64 = 1.23456789e-100000 // ERROR "1\.23457e\-100000 truncated|.* truncated to int64" _ int64 = 1.23456789e-100000 // ERROR "1\.23457e\-100000 truncated|.* truncated to int64|truncated"
_ int64 = 1.23456789e-1000000 // ERROR "1\.23457e\-1000000 truncated|.* truncated to int64" _ int64 = 1.23456789e-1000000 // ERROR "1\.23457e\-1000000 truncated|.* truncated to int64|truncated"
) )
const ( const (
_ int64 = -1.23456789e10000000 // ERROR "integer too large|truncated to int64" _ int64 = -1.23456789e10000000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = -1.23456789e1000000 // ERROR "integer too large|truncated to int64" _ int64 = -1.23456789e1000000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = -1.23456789e100000 // ERROR "integer too large|truncated to int64" _ int64 = -1.23456789e100000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = -1.23456789e10000 // ERROR "integer too large|truncated to int64" _ int64 = -1.23456789e10000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = -1.23456789e1000 // ERROR "integer too large|truncated to int64" _ int64 = -1.23456789e1000 // ERROR "integer too large|truncated to int64|truncated"
_ int64 = -1.23456789e100 // ERROR "\-12345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows|truncated to int64" _ int64 = -1.23456789e100 // ERROR "\-12345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows|truncated to int64|truncated"
_ int64 = -1.23456789e10 _ int64 = -1.23456789e10
_ int64 = -1.23456789e1 // ERROR "\-12\.3457 truncated|.* truncated to int64" _ int64 = -1.23456789e1 // ERROR "\-12\.3457 truncated|.* truncated to int64|truncated"
_ int64 = -1.23456789e0 // ERROR "\-1\.23457 truncated|.* truncated to int64" _ int64 = -1.23456789e0 // ERROR "\-1\.23457 truncated|.* truncated to int64|truncated"
_ int64 = -1.23456789e-1 // ERROR "\-0\.123457 truncated|.* truncated to int64" _ int64 = -1.23456789e-1 // ERROR "\-0\.123457 truncated|.* truncated to int64|truncated"
_ int64 = -1.23456789e-10 // ERROR "\-1\.23457e\-10 truncated|.* truncated to int64" _ int64 = -1.23456789e-10 // ERROR "\-1\.23457e\-10 truncated|.* truncated to int64|truncated"
_ int64 = -1.23456789e-100 // ERROR "\-1\.23457e\-100 truncated|.* truncated to int64" _ int64 = -1.23456789e-100 // ERROR "\-1\.23457e\-100 truncated|.* truncated to int64|truncated"
_ int64 = -1.23456789e-1000 // ERROR "\-1\.23457e\-1000 truncated|.* truncated to int64" _ int64 = -1.23456789e-1000 // ERROR "\-1\.23457e\-1000 truncated|.* truncated to int64|truncated"
_ int64 = -1.23456789e-10000 // ERROR "\-1\.23457e\-10000 truncated|.* truncated to int64" _ int64 = -1.23456789e-10000 // ERROR "\-1\.23457e\-10000 truncated|.* truncated to int64|truncated"
_ int64 = -1.23456789e-100000 // ERROR "\-1\.23457e\-100000 truncated|.* truncated to int64" _ int64 = -1.23456789e-100000 // ERROR "\-1\.23457e\-100000 truncated|.* truncated to int64|truncated"
_ int64 = -1.23456789e-1000000 // ERROR "\-1\.23457e\-1000000 truncated|.* truncated to int64" _ int64 = -1.23456789e-1000000 // ERROR "\-1\.23457e\-1000000 truncated|.* truncated to int64|truncated"
) )

View file

@ -9,5 +9,5 @@
package p package p
func f() uintptr { func f() uintptr {
return nil // ERROR "cannot use nil as type uintptr in return argument|incompatible type|cannot convert untyped nil" return nil // ERROR "cannot use nil as type uintptr in return argument|incompatible type|cannot use untyped nil"
} }

View file

@ -8,4 +8,4 @@
package p package p
var _ = []int{a: true, true} // ERROR "undefined: a" "cannot use true \(type untyped bool\) as type int in slice literal|undefined name .*a|incompatible type|cannot convert" var _ = []int{a: true, true} // ERROR "undefined: a" "cannot use true \(type untyped bool\) as type int in slice literal|undefined name .*a|incompatible type|cannot use"