[dev.typeparams] go/types: report better error for invalid untyped operation

This is port of CL 328053 for types2 to go/type.

The change is identical, but for some tweaks to the error positions in
tests.

Updates #46749

Change-Id: I8d34c5b1669e59e4ec7d91f81dcf655b2bfd89a5
Reviewed-on: https://go-review.googlesource.com/c/go/+/328869
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 Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Cuong Manh Le 2021-06-17 10:14:07 +07:00
parent 90096f445e
commit 2a7900762c
8 changed files with 34 additions and 20 deletions

View file

@ -875,7 +875,7 @@ const (
// context in which it is used.
//
// Example:
// var _ = 1 + ""
// var _ = 1 + nil
_InvalidUntypedConversion
// _BadOffsetofSyntax occurs when unsafe.Offsetof is called with an argument

View file

@ -927,14 +927,28 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token
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 /* ERROR mismatched types string and untyped int */ + 1
x = x + y
x = x /* ERROR not defined */ - y
x = x * 10 // ERROR cannot convert
x = x /* ERROR mismatched types string and untyped int */* 10
}
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

@ -103,7 +103,7 @@ func indexes() {
var ok mybool
_, ok = m["bar"]
_ = ok
_ = m[0 /* ERROR "cannot use 0" */ ] + "foo" // ERROR "cannot convert"
_ = m/* ERROR "mismatched types int and untyped string" */[0 /* ERROR "cannot use 0" */ ] + "foo"
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 /* ERROR "mismatched types int and untyped string" */+= "foo"
f -= 1
f /= 0
f = float32(0)/0 /* ERROR "division by zero" */
f -= "foo" /* ERROR "cannot convert.*float64" */
f /* ERROR "mismatched types float64 and untyped string" */-= "foo"
c *= 1
c /= 0
s += "bar"
s += 1 /* ERROR "cannot convert.*string" */
s /* ERROR "mismatched types string and untyped int" */+= 1
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
}
}