aboutsummaryrefslogtreecommitdiff
path: root/src/go/types/expr.go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2019-09-16 14:34:02 -0700
committerRobert Griesemer <gri@golang.org>2019-09-17 23:16:18 +0000
commit04fb929a5b7991ed0945d05ab8015c1721958d82 (patch)
treebc01628d2345e3c9bd1e72c6a168df8b8897bf27 /src/go/types/expr.go
parent5cc64141e738b008b62d0698cdbadf2b9aead72d (diff)
downloadgo-04fb929a5b7991ed0945d05ab8015c1721958d82.tar.gz
go-04fb929a5b7991ed0945d05ab8015c1721958d82.zip
go/types: make sure interfaces are complete before comparing them
Complete interfaces before comparing them with Checker.identical. This requires passing through a *Checker to various functions that didn't need this before. Verified that none of the exported API entry points for interfaces that rely on completed interfaces are used internally except for Interface.Empty. Verified that interfaces are complete before calling Empty on them, and added a dynamic check in the exported functions. Unfortunately, this fix exposed another problem with an esoteric test case (#33656) which we need to reopen. Fixes #34151. Updates #33656. Change-Id: I4e14bae3df74a2c21b565c24fdd07135f22e11c0 Reviewed-on: https://go-review.googlesource.com/c/go/+/195837 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/go/types/expr.go')
-rw-r--r--src/go/types/expr.go8
1 files changed, 3 insertions, 5 deletions
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index 66d62d6885..0edd2789fb 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -548,9 +548,6 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
}
}
case *Interface:
- if !x.isNil() && !t.Empty() /* empty interfaces are ok */ {
- goto Error
- }
// Update operand types to the default type rather then
// the target (interface) type: values must have concrete
// dynamic types. If the value is nil, keep it untyped
@@ -561,6 +558,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
target = Typ[UntypedNil]
} else {
// cannot assign untyped values to non-empty interfaces
+ check.completeInterface(t)
if !t.Empty() {
goto Error
}
@@ -809,7 +807,7 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
return
}
- if !Identical(x.typ, y.typ) {
+ if !check.identical(x.typ, y.typ) {
// only report an error if we have valid types
// (otherwise we had an error reported elsewhere already)
if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] {
@@ -1223,7 +1221,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
xkey := keyVal(x.val)
if _, ok := utyp.key.Underlying().(*Interface); ok {
for _, vtyp := range visited[xkey] {
- if Identical(vtyp, x.typ) {
+ if check.identical(vtyp, x.typ) {
duplicate = true
break
}