Skip to content

Commit cae4516

Browse files
Robert Griesemergopherbot
authored andcommitted
go/types, types2: better error messages for certain type mismatches
When an untyped operand of a (typically binary) operation does not match the type of the operand and an implicit conversion is not possible, the error message should report a "type mismatch". The type-checkers mostly did so, but not for untyped numeric types to other types (e.g. an untyped int vs a function); in those cases it reported that the (impossible) conversion failed. Fix this for numeric types. This also improves the position and messages for some incorrect min/max built-in calls. Fixes #73428. Change-Id: I8af071918b73fcc72f16cc61858d7baca57fc259 Reviewed-on: https://go-review.googlesource.com/c/go/+/682495 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Mark Freeman <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> Auto-Submit: Robert Griesemer <[email protected]>
1 parent 2ddf542 commit cae4516

File tree

8 files changed

+30
-7
lines changed

8 files changed

+30
-7
lines changed

src/cmd/compile/internal/types2/expr.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,10 @@ func (check *Checker) matchTypes(x, y *operand) {
895895
if isTyped(x.typ) && isTyped(y.typ) {
896896
return false
897897
}
898+
// A numeric type can only convert to another numeric type.
899+
if allNumeric(x.typ) != allNumeric(y.typ) {
900+
return false
901+
}
898902
// An untyped operand may convert to its default type when paired with an empty interface
899903
// TODO(gri) This should only matter for comparisons (the only binary operation that is
900904
// valid with interfaces), but in that case the assignability check should take

src/go/types/expr.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,10 @@ func (check *Checker) matchTypes(x, y *operand) {
887887
if isTyped(x.typ) && isTyped(y.typ) {
888888
return false
889889
}
890+
// A numeric type can only convert to another numeric type.
891+
if allNumeric(x.typ) != allNumeric(y.typ) {
892+
return false
893+
}
890894
// An untyped operand may convert to its default type when paired with an empty interface
891895
// TODO(gri) This should only matter for comparisons (the only binary operation that is
892896
// valid with interfaces), but in that case the assignability check should take

src/internal/types/errors/codes.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,9 @@ const (
881881
// context in which it is used.
882882
//
883883
// Example:
884-
// var _ = 1 + []int{}
884+
// func f[T ~int8 | ~int16 | ~int32 | ~int64](x T) T {
885+
// return x + 1024
886+
// }
885887
InvalidUntypedConversion
886888

887889
// BadOffsetofSyntax occurs when unsafe.Offsetof is called with an argument

src/internal/types/testdata/check/builtins1.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ func _[
211211
var x2 P2
212212
_ = max(x2)
213213
_ = max(x2, x2)
214-
_ = max(1, 2 /* ERROR "cannot convert 2 (untyped int constant) to type P2" */, x2) // error at 2 because max is 2
214+
_ = max(1, 2, x2 /* ERROR "mismatched types untyped int (previous argument) and P2 (type of x2)" */ )
215215

216216
_ = max(x1, x2 /* ERROR "mismatched types P1 (previous argument) and P2 (type of x2)" */ )
217217
}
@@ -232,7 +232,7 @@ func _[
232232
var x2 P2
233233
_ = min(x2)
234234
_ = min(x2, x2)
235-
_ = min(1 /* ERROR "cannot convert 1 (untyped int constant) to type P2" */ , 2, x2) // error at 1 because min is 1
235+
_ = min(1, 2, x2 /* ERROR "mismatched types untyped int (previous argument) and P2 (type of x2)" */ )
236236

237237
_ = min(x1, x2 /* ERROR "mismatched types P1 (previous argument) and P2 (type of x2)" */ )
238238
}

src/internal/types/testdata/check/expr2.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ func interfaces() {
201201
var s11 S11
202202
var s2 S2
203203

204-
_ = i == 0 /* ERROR "cannot convert" */
204+
_ = i == 0 /* ERROR "invalid operation: i == 0 (mismatched types interface{m() int} and untyped int)" */
205205
_ = i == s1 /* ERROR "mismatched types" */
206206
_ = i == &s1
207207
_ = i == &s11

src/internal/types/testdata/fixedbugs/issue60434.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ var s struct{ x int }
1313

1414
func _() {
1515
f(s.y /* ERROR "s.y undefined" */)
16-
f(1 /* ERROR "cannot convert 1" */ / s)
16+
f(1 /* ERROR "invalid operation: 1 / s (mismatched types untyped int and struct{x int})" */ / s)
1717
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2025 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
func f() {}
8+
9+
const c = 0
10+
11+
var v int
12+
var _ = f < c // ERROR "invalid operation: f < c (mismatched types func() and untyped int)"
13+
var _ = f < v // ERROR "invalid operation: f < v (mismatched types func() and int)"

test/fixedbugs/issue46749.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ var (
3131
var (
3232
_ = b + 1 // ERROR "invalid operation.*mismatched types.*bool and untyped int"
3333
_ = i + false // ERROR "invalid operation.*mismatched types.*int and untyped bool"
34-
_ = iface + 1 // ERROR "invalid operation.*mismatched types.*interface *{} and int"
35-
_ = iface + 1.0 // ERROR "invalid operation.*mismatched types.*interface *{} and float64"
34+
_ = iface + 1 // ERROR "invalid operation.*mismatched types.*interface *{} and untyped int"
35+
_ = iface + 1.0 // ERROR "invalid operation.*mismatched types.*interface *{} and untyped float"
3636
_ = iface + false // ERROR "invalid operation.*mismatched types.*interface *{} and bool"
3737
)

0 commit comments

Comments
 (0)