mirror of
https://github.com/golang/go
synced 2024-11-23 19:00:04 -07:00
go/types, types2: better error message for invalid == on type parameters
Fixes #48712. Change-Id: I6f214cdfdd1815493f2a04828e8f0097f1d8c124 Reviewed-on: https://go-review.googlesource.com/c/go/+/372734 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
90860e0c31
commit
2639f2f79b
@ -770,10 +770,12 @@ func (check *Checker) comparison(x, y *operand, op syntax.Operator) {
|
||||
xok, _ := x.assignableTo(check, y.typ, nil)
|
||||
yok, _ := y.assignableTo(check, x.typ, nil)
|
||||
if xok || yok {
|
||||
equality := false
|
||||
defined := false
|
||||
switch op {
|
||||
case syntax.Eql, syntax.Neq:
|
||||
// spec: "The equality operators == and != apply to operands that are comparable."
|
||||
equality = true
|
||||
defined = Comparable(x.typ) && Comparable(y.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ)
|
||||
case syntax.Lss, syntax.Leq, syntax.Gtr, syntax.Geq:
|
||||
// spec: The ordering operators <, <=, >, and >= apply to operands that are ordered."
|
||||
@ -782,11 +784,19 @@ func (check *Checker) comparison(x, y *operand, op syntax.Operator) {
|
||||
unreachable()
|
||||
}
|
||||
if !defined {
|
||||
typ := x.typ
|
||||
if x.isNil() {
|
||||
typ = y.typ
|
||||
if equality && (isTypeParam(x.typ) || isTypeParam(y.typ)) {
|
||||
typ := x.typ
|
||||
if isTypeParam(y.typ) {
|
||||
typ = y.typ
|
||||
}
|
||||
err = check.sprintf("%s is not comparable", typ)
|
||||
} else {
|
||||
typ := x.typ
|
||||
if x.isNil() {
|
||||
typ = y.typ
|
||||
}
|
||||
err = check.sprintf("operator %s not defined on %s", op, typ)
|
||||
}
|
||||
err = check.sprintf("operator %s not defined on %s", op, typ)
|
||||
}
|
||||
} else {
|
||||
err = check.sprintf("mismatched types %s and %s", x.typ, y.typ)
|
||||
|
41
src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go2
vendored
Normal file
41
src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go2
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
|
||||
func _[P comparable](x, y P) {
|
||||
_ = x == x
|
||||
_ = x == y
|
||||
_ = y == x
|
||||
_ = y == y
|
||||
|
||||
_ = x /* ERROR operator < not defined on P */ < y
|
||||
}
|
||||
|
||||
func _[P comparable](x P, y any) {
|
||||
_ = x == x
|
||||
_ = x == y
|
||||
_ = y == x
|
||||
_ = y == y
|
||||
|
||||
_ = x /* ERROR operator < not defined on P */ < y
|
||||
}
|
||||
|
||||
func _[P any](x, y P) {
|
||||
_ = x /* ERROR P is not comparable */ == x
|
||||
_ = x /* ERROR P is not comparable */ == y
|
||||
_ = y /* ERROR P is not comparable */ == x
|
||||
_ = y /* ERROR P is not comparable */ == y
|
||||
|
||||
_ = x /* ERROR operator < not defined on P */ < y
|
||||
}
|
||||
|
||||
func _[P any](x P, y any) {
|
||||
_ = x /* ERROR P is not comparable */ == x
|
||||
_ = x /* ERROR P is not comparable */ == y
|
||||
_ = y /* ERROR P is not comparable */ == x
|
||||
_ = y == y
|
||||
|
||||
_ = x /* ERROR operator < not defined on P */ < y
|
||||
}
|
@ -729,10 +729,12 @@ func (check *Checker) comparison(x, y *operand, op token.Token) {
|
||||
xok, _ := x.assignableTo(check, y.typ, nil)
|
||||
yok, _ := y.assignableTo(check, x.typ, nil)
|
||||
if xok || yok {
|
||||
equality := false
|
||||
defined := false
|
||||
switch op {
|
||||
case token.EQL, token.NEQ:
|
||||
// spec: "The equality operators == and != apply to operands that are comparable."
|
||||
equality = true
|
||||
defined = Comparable(x.typ) && Comparable(y.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ)
|
||||
case token.LSS, token.LEQ, token.GTR, token.GEQ:
|
||||
// spec: The ordering operators <, <=, >, and >= apply to operands that are ordered."
|
||||
@ -741,11 +743,19 @@ func (check *Checker) comparison(x, y *operand, op token.Token) {
|
||||
unreachable()
|
||||
}
|
||||
if !defined {
|
||||
typ := x.typ
|
||||
if x.isNil() {
|
||||
typ = y.typ
|
||||
if equality && (isTypeParam(x.typ) || isTypeParam(y.typ)) {
|
||||
typ := x.typ
|
||||
if isTypeParam(y.typ) {
|
||||
typ = y.typ
|
||||
}
|
||||
err = check.sprintf("%s is not comparable", typ)
|
||||
} else {
|
||||
typ := x.typ
|
||||
if x.isNil() {
|
||||
typ = y.typ
|
||||
}
|
||||
err = check.sprintf("operator %s not defined on %s", op, typ)
|
||||
}
|
||||
err = check.sprintf("operator %s not defined on %s", op, typ)
|
||||
code = _UndefinedOp
|
||||
}
|
||||
} else {
|
||||
|
41
src/go/types/testdata/fixedbugs/issue48712.go2
vendored
Normal file
41
src/go/types/testdata/fixedbugs/issue48712.go2
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
|
||||
func _[P comparable](x, y P) {
|
||||
_ = x == x
|
||||
_ = x == y
|
||||
_ = y == x
|
||||
_ = y == y
|
||||
|
||||
_ = x /* ERROR operator < not defined on P */ < y
|
||||
}
|
||||
|
||||
func _[P comparable](x P, y any) {
|
||||
_ = x == x
|
||||
_ = x == y
|
||||
_ = y == x
|
||||
_ = y == y
|
||||
|
||||
_ = x /* ERROR operator < not defined on P */ < y
|
||||
}
|
||||
|
||||
func _[P any](x, y P) {
|
||||
_ = x /* ERROR P is not comparable */ == x
|
||||
_ = x /* ERROR P is not comparable */ == y
|
||||
_ = y /* ERROR P is not comparable */ == x
|
||||
_ = y /* ERROR P is not comparable */ == y
|
||||
|
||||
_ = x /* ERROR operator < not defined on P */ < y
|
||||
}
|
||||
|
||||
func _[P any](x P, y any) {
|
||||
_ = x /* ERROR P is not comparable */ == x
|
||||
_ = x /* ERROR P is not comparable */ == y
|
||||
_ = y /* ERROR P is not comparable */ == x
|
||||
_ = y == y
|
||||
|
||||
_ = x /* ERROR operator < not defined on P */ < y
|
||||
}
|
Loading…
Reference in New Issue
Block a user