This ports the fix in CL 328050 for typecheck to types2.
The fix is not identical, due to code structure differences between
typecheck and types2, but the idea is the same. We only do the untyped
conversion when both operands can be mixed.
Updates #46749
Change-Id: Ib2c63ba0d5dd8bf02318b1bfdfe51dcaeeeb7f82
Reviewed-on: https://go-review.googlesource.com/c/go/+/328053
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
return
}
- check.convertUntyped(x, y.typ)
- if x.mode == invalid {
- return
+ canMix := func(x, y *operand) bool {
+ if IsInterface(x.typ) || IsInterface(y.typ) {
+ return true
+ }
+ if isBoolean(x.typ) != isBoolean(y.typ) {
+ return false
+ }
+ if isString(x.typ) != isString(y.typ) {
+ return false
+ }
+ return true
}
- check.convertUntyped(&y, x.typ)
- if y.mode == invalid {
- x.mode = invalid
- return
+ if canMix(x, &y) {
+ check.convertUntyped(x, y.typ)
+ if x.mode == invalid {
+ return
+ }
+ check.convertUntyped(&y, x.typ)
+ if y.mode == invalid {
+ x.mode = invalid
+ return
+ }
}
if isComparison(op) {
ub1 = true
ub2 = 2 < 1
ub3 = ui1 == uf1
- ub4 = true /* ERROR "cannot convert" */ == 0
+ ub4 = true /* ERROR "mismatched types untyped bool and untyped int" */ == 0
// integer values
ui0 = 0
// Constant expression initializations
var (
- v1 = 1 /* ERROR "cannot convert" */ + "foo"
+ v1 = 1 /* ERROR "mismatched types untyped int and untyped string" */ + "foo"
v2 = c + 255
v3 = c + 256 /* ERROR "overflows" */
v4 = r + 2147483647
func _(x, y string, z mystring) {
x = x + "foo"
x = x /* ERROR not defined */ - "foo"
- x = x + 1 // ERROR cannot convert
+ x = x + 1 // ERROR mismatched types string and untyped int
x = x + y
x = x /* ERROR not defined */ - y
- x = x * 10 // ERROR cannot convert
+ x = x * 10 // ERROR mismatched types string and untyped int
}
func f() (a, b int) { return }
const t = true == true
const f = true == false
_ = t /* ERROR "cannot compare" */ < f
- _ = 0 /* ERROR "cannot convert" */ == t
+ _ = 0 /* ERROR "mismatched types untyped int and untyped bool" */ == t
var b bool
var x, y float32
b = x < y
var ok mybool
_, ok = m["bar"]
_ = ok
- _ = m[0 /* ERROR "cannot use 0" */ ] + "foo" // ERROR "cannot convert"
+ _ = m[0 /* ERROR "cannot use 0" */ ] + "foo" // ERROR "mismatched types int and untyped string"
var t string
_ = t[- /* ERROR "negative" */ 1]
b = true
i += 1
- i += "foo" /* ERROR "cannot convert.*int" */
+ i += "foo" /* ERROR "mismatched types int and untyped string" */
f -= 1
f /= 0
f = float32(0)/0 /* ERROR "division by zero" */
- f -= "foo" /* ERROR "cannot convert.*float64" */
+ f -= "foo" /* ERROR "mismatched types float64 and untyped string" */
c *= 1
c /= 0
s += "bar"
- s += 1 /* ERROR "cannot convert.*string" */
+ s += 1 /* ERROR "mismatched types string and untyped int" */
var u64 uint64
u64 += 1<<u64
// errors reported).
func issue10148() {
for y /* ERROR declared but not used */ := range "" {
- _ = "" /* ERROR cannot convert */ + 1
+ _ = "" /* ERROR mismatched types untyped string and untyped int*/ + 1
}
for range 1 /* ERROR cannot range over 1 */ {
- _ = "" /* ERROR cannot convert */ + 1
+ _ = "" /* ERROR mismatched types untyped string and untyped int*/ + 1
}
for y := range 1 /* ERROR cannot range over 1 */ {
- _ = "" /* ERROR cannot convert */ + 1
+ _ = "" /* ERROR mismatched types untyped string and untyped int*/ + 1
}
}
func f() {
var x *s
- _ = x == nil || len(x.slice) // ERROR "invalid operation: .+ \(operator \|\| not defined on int\)|incompatible types|cannot convert"
- _ = len(x.slice) || x == nil // ERROR "invalid operation: .+ \(operator \|\| not defined on int\)|incompatible types|cannot convert"
- _ = x == nil && len(x.slice) // ERROR "invalid operation: .+ \(operator && not defined on int\)|incompatible types|cannot convert"
- _ = len(x.slice) && x == nil // ERROR "invalid operation: .+ \(operator && not defined on int\)|incompatible types|cannot convert"
+ _ = x == nil || len(x.slice) // ERROR "invalid operation: .+ \(operator \|\| not defined on int\)|incompatible types|mismatched types untyped bool and int"
+ _ = len(x.slice) || x == nil // ERROR "invalid operation: .+ \(operator \|\| not defined on int\)|incompatible types|mismatched types int and untyped bool"
+ _ = x == nil && len(x.slice) // ERROR "invalid operation: .+ \(operator && not defined on int\)|incompatible types|mismatched types untyped bool and int"
+ _ = len(x.slice) && x == nil // ERROR "invalid operation: .+ \(operator && not defined on int\)|incompatible types|mismatched types int and untyped bool"
}
package p
-var _ = true == '\\' // ERROR "invalid operation: true == '\\\\'|cannot convert true"
-var _ = true == '\'' // ERROR "invalid operation: true == '\\''|cannot convert true"
-var _ = true == '\n' // ERROR "invalid operation: true == '\\n'|cannot convert true"
+var _ = true == '\\' // ERROR "invalid operation: (cannot compare true)|(true) == '\\\\' \(mismatched types untyped bool and untyped rune\)"
+var _ = true == '\'' // ERROR "invalid operation: (cannot compare true)|(true) == '\\'' \(mismatched types untyped bool and untyped rune\)"
+var _ = true == '\n' // ERROR "invalid operation: (cannot compare true)|(true) == '\\n' \(mismatched types untyped bool and untyped rune\)"
var (
_ = "" + b // ERROR "invalid operation.*mismatched types.*untyped string and bool"
_ = "" + i // ERROR "invalid operation.*mismatched types.*untyped string and int"
- _ = "" + nil // ERROR "invalid operation.*mismatched types.*untyped string and nil"
+ _ = "" + nil // ERROR "invalid operation.*mismatched types.*untyped string and nil|(untyped nil)"
)
var (
_ = s + false // ERROR "invalid operation.*mismatched types.*string and untyped bool"
_ = s + 1 // ERROR "invalid operation.*mismatched types.*string and untyped int"
- _ = s + nil // ERROR "invalid operation.*mismatched types.*string and nil"
+ _ = s + nil // ERROR "invalid operation.*mismatched types.*string and nil|(untyped nil)"
)
var (
var (
_ = b + 1 // ERROR "invalid operation.*mismatched types.*bool and untyped int"
_ = i + false // ERROR "invalid operation.*mismatched types.*int and untyped bool"
- _ = iface + 1 // ERROR "invalid operation.*mismatched types.*interface {} and int"
- _ = iface + 1.0 // ERROR "invalid operation.*mismatched types.*interface {} and float64"
- _ = iface + false // ERROR "invalid operation.*mismatched types.*interface {} and bool"
+ _ = iface + 1 // ERROR "invalid operation.*mismatched types.*interface *{} and int"
+ _ = iface + 1.0 // ERROR "invalid operation.*mismatched types.*interface *{} and float64"
+ _ = iface + false // ERROR "invalid operation.*mismatched types.*interface *{} and bool"
)
"fixedbugs/issue7525d.go": true, // types2 reports init cycle error on different line - ok otherwise
"fixedbugs/issue7525e.go": true, // types2 reports init cycle error on different line - ok otherwise
"fixedbugs/issue7525.go": true, // types2 reports init cycle error on different line - ok otherwise
- "fixedbugs/issue46749.go": true, // types2 reports can not convert error instead of type mismatched
"fixedbugs/issue9691.go": true, // "cannot assign to int(.autotmp_4)" (probably irgen's fault)
// tests that rely on -m diagnostics, which currently differ with -G=3