]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: perform delayed tests even for types.Eval
authorRobert Griesemer <gri@golang.org>
Tue, 19 Dec 2017 23:45:50 +0000 (15:45 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 12 Feb 2018 21:40:19 +0000 (21:40 +0000)
R=go1.11

types.Eval historically never evaluated any delayed tests, which
included verification of validity of map keys, but also function
literal bodies.

Now, embedded interfaces are also type-checked in a delayed fashion,
so it becomes imperative to do all delayed checks for eval (otherwise
obviously incorrect type expressions are silently accepted).

Enabling the delayed tests also removes the restriction that function
literals were not type-checked.

Also fixed a bug where eval wouldn't return a type-checking error
because check.handleBailout was using the wrong err variable.

Added tests that verify that method set computation is using the
right types when evaluating interfaces with embedded types.

For #18395.
For #22992.

Change-Id: I574fa84568b5158bca4b4ccd4ef5abb616fbf896
Reviewed-on: https://go-review.googlesource.com/84898
Reviewed-by: Alan Donovan <adonovan@google.com>
src/go/types/eval.go
src/go/types/eval_test.go

index 831d771d8075c92879ecb8ae12996669553280fd..8d4db48a9f90fccf7ac6f34e1543d883d01b2d2b 100644 (file)
@@ -16,9 +16,6 @@ import (
 // complete position information relative to the provided file
 // set.
 //
-// If the expression contains function literals, their bodies
-// are ignored (i.e., the bodies are not type-checked).
-//
 // If pkg == nil, the Universe scope is used and the provided
 // position pos is ignored. If pkg != nil, and pos is invalid,
 // the package scope is used. Otherwise, pos must belong to the
@@ -34,7 +31,7 @@ import (
 // level untyped constants will return an untyped type rather then the
 // respective context-specific type.
 //
-func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (TypeAndValue, error) {
+func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (_ TypeAndValue, err error) {
        // determine scope
        var scope *Scope
        if pkg == nil {
@@ -79,5 +76,7 @@ func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (TypeAn
        // evaluate node
        var x operand
        check.rawExpr(&x, node, nil)
-       return TypeAndValue{x.mode, x.typ, x.val}, err
+       check.processDelayed(0) // incl. all functions
+
+       return TypeAndValue{x.mode, x.typ, x.val}, nil
 }
index 603211257dc572b32286286b76a5be669debf2c7..d3b3fec66fc04c7caeea0d7b443a7ade217c7d55 100644 (file)
@@ -149,6 +149,19 @@ func TestEvalPos(t *testing.T) {
                package p
                /* T => , p.T */
                `,
+               `
+               package p
+               import "io"
+               type R = io.Reader
+               func _() {
+                       /* interface{R}.Read => , func(interface{io.Reader}, p []byte) (n int, err error) */
+                       _ = func() {
+                               /* interface{io.Writer}.Write => , func(interface{io.Writer}, p []byte) (n int, err error) */
+                               type io interface {} // must not shadow io in line above
+                       }
+                       type R interface {} // must not shadow R in first line of this function body
+               }
+               `,
        }
 
        fset := token.NewFileSet()