[dev.typeparams] cmd/compile: make types2 report better error for invalid untyped operation

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>
This commit is contained in:
Cuong Manh Le 2021-06-16 16:23:44 +07:00
parent 8115ae198d
commit b14fd720a8
11 changed files with 45 additions and 32 deletions

View File

@ -972,14 +972,28 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op
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) {

View File

@ -27,7 +27,7 @@ const (
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

View File

@ -83,7 +83,7 @@ var (
// 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

View File

@ -111,10 +111,10 @@ type mystring string
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 }

View File

@ -10,7 +10,7 @@ func _bool() {
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

View File

@ -104,7 +104,7 @@ func indexes() {
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]

View File

@ -49,18 +49,18 @@ func assignments1() {
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
@ -937,13 +937,13 @@ func issue6766b() {
// 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
}
}

View File

@ -13,8 +13,8 @@ type s struct {
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"
}

View File

@ -6,6 +6,6 @@
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\)"

View File

@ -14,13 +14,13 @@ var iface interface{}
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 (
@ -31,7 +31,7 @@ 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"
)

View File

@ -2089,7 +2089,6 @@ var excludedFiles = map[string]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