diff options
author | Robert Griesemer <gri@golang.org> | 2019-09-16 14:34:02 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2019-09-17 23:16:18 +0000 |
commit | 04fb929a5b7991ed0945d05ab8015c1721958d82 (patch) | |
tree | bc01628d2345e3c9bd1e72c6a168df8b8897bf27 /src/go/types/expr.go | |
parent | 5cc64141e738b008b62d0698cdbadf2b9aead72d (diff) | |
download | go-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.go | 8 |
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 } |