[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 return
} }
check.convertUntyped(x, y.typ) canMix := func(x, y *operand) bool {
if x.mode == invalid { if IsInterface(x.typ) || IsInterface(y.typ) {
return 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 canMix(x, &y) {
if y.mode == invalid { check.convertUntyped(x, y.typ)
x.mode = invalid if x.mode == invalid {
return return
}
check.convertUntyped(&y, x.typ)
if y.mode == invalid {
x.mode = invalid
return
}
} }
if isComparison(op) { if isComparison(op) {

View File

@ -27,7 +27,7 @@ const (
ub1 = true ub1 = true
ub2 = 2 < 1 ub2 = 2 < 1
ub3 = ui1 == uf1 ub3 = ui1 == uf1
ub4 = true /* ERROR "cannot convert" */ == 0 ub4 = true /* ERROR "mismatched types untyped bool and untyped int" */ == 0
// integer values // integer values
ui0 = 0 ui0 = 0

View File

@ -83,7 +83,7 @@ var (
// Constant expression initializations // Constant expression initializations
var ( var (
v1 = 1 /* ERROR "cannot convert" */ + "foo" v1 = 1 /* ERROR "mismatched types untyped int and untyped string" */ + "foo"
v2 = c + 255 v2 = c + 255
v3 = c + 256 /* ERROR "overflows" */ v3 = c + 256 /* ERROR "overflows" */
v4 = r + 2147483647 v4 = r + 2147483647

View File

@ -111,10 +111,10 @@ type mystring string
func _(x, y string, z mystring) { func _(x, y string, z mystring) {
x = x + "foo" x = x + "foo"
x = x /* ERROR not defined */ - "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 + y
x = x /* ERROR not defined */ - 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 } func f() (a, b int) { return }

View File

@ -10,7 +10,7 @@ func _bool() {
const t = true == true const t = true == true
const f = true == false const f = true == false
_ = t /* ERROR "cannot compare" */ < f _ = t /* ERROR "cannot compare" */ < f
_ = 0 /* ERROR "cannot convert" */ == t _ = 0 /* ERROR "mismatched types untyped int and untyped bool" */ == t
var b bool var b bool
var x, y float32 var x, y float32
b = x < y b = x < y

View File

@ -104,7 +104,7 @@ func indexes() {
var ok mybool var ok mybool
_, ok = m["bar"] _, ok = m["bar"]
_ = ok _ = 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 var t string
_ = t[- /* ERROR "negative" */ 1] _ = t[- /* ERROR "negative" */ 1]

View File

@ -49,18 +49,18 @@ func assignments1() {
b = true b = true
i += 1 i += 1
i += "foo" /* ERROR "cannot convert.*int" */ i += "foo" /* ERROR "mismatched types int and untyped string" */
f -= 1 f -= 1
f /= 0 f /= 0
f = float32(0)/0 /* ERROR "division by zero" */ 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 *= 1
c /= 0 c /= 0
s += "bar" s += "bar"
s += 1 /* ERROR "cannot convert.*string" */ s += 1 /* ERROR "mismatched types string and untyped int" */
var u64 uint64 var u64 uint64
u64 += 1<<u64 u64 += 1<<u64
@ -937,13 +937,13 @@ func issue6766b() {
// errors reported). // errors reported).
func issue10148() { func issue10148() {
for y /* ERROR declared but not used */ := range "" { 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 */ { 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 */ { 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() { func f() {
var x *s var x *s
_ = x == nil || len(x.slice) // 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|cannot convert" _ = 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|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|cannot convert" _ = 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 package p
var _ = true == '\\' // ERROR "invalid operation: true == '\\\\'|cannot convert true" var _ = true == '\\' // ERROR "invalid operation: (cannot compare true)|(true) == '\\\\' \(mismatched types untyped bool and untyped rune\)"
var _ = true == '\'' // ERROR "invalid operation: true == '\\''|cannot convert true" var _ = true == '\'' // ERROR "invalid operation: (cannot compare true)|(true) == '\\'' \(mismatched types untyped bool and untyped rune\)"
var _ = true == '\n' // ERROR "invalid operation: true == '\\n'|cannot convert true" 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 ( var (
_ = "" + b // ERROR "invalid operation.*mismatched types.*untyped string and bool" _ = "" + b // ERROR "invalid operation.*mismatched types.*untyped string and bool"
_ = "" + i // ERROR "invalid operation.*mismatched types.*untyped string and int" _ = "" + 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 ( var (
_ = s + false // ERROR "invalid operation.*mismatched types.*string and untyped bool" _ = s + false // ERROR "invalid operation.*mismatched types.*string and untyped bool"
_ = s + 1 // ERROR "invalid operation.*mismatched types.*string and untyped int" _ = 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 (
@ -31,7 +31,7 @@ var (
var ( var (
_ = b + 1 // ERROR "invalid operation.*mismatched types.*bool and untyped int" _ = b + 1 // ERROR "invalid operation.*mismatched types.*bool and untyped int"
_ = i + false // ERROR "invalid operation.*mismatched types.*int and untyped bool" _ = i + false // ERROR "invalid operation.*mismatched types.*int and untyped bool"
_ = iface + 1 // ERROR "invalid operation.*mismatched types.*interface {} and int" _ = iface + 1 // ERROR "invalid operation.*mismatched types.*interface *{} and int"
_ = iface + 1.0 // ERROR "invalid operation.*mismatched types.*interface {} and float64" _ = iface + 1.0 // ERROR "invalid operation.*mismatched types.*interface *{} and float64"
_ = iface + false // ERROR "invalid operation.*mismatched types.*interface {} and bool" _ = 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/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/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/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) "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 // tests that rely on -m diagnostics, which currently differ with -G=3