]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: adjustments toward matching compiler...
authorRobert Griesemer <gri@golang.org>
Tue, 1 Dec 2020 05:28:32 +0000 (21:28 -0800)
committerRobert Griesemer <gri@golang.org>
Tue, 1 Dec 2020 21:49:25 +0000 (21:49 +0000)
In order to get types2 usable by the compiler, we need to
pass all the compiler tests with respect to error messages.
Sometimes the compiler error messages are better, sometimes
the types2 error messages are better. Where we can, we decide
on a case-by-case basis; but sometimes, for expediency's sake,
we just choose the compiler error message as it may reduce the
amount of tests that we need to update.

This CL introduces a new Config flag: CompilerErrorMessages.
If set, the typechecker emits an error message that matches
the expected errors in the tests most easily. Eventually, we
need to get rid of this flag by either adjusting the typechecker
errors or the test cases; t.b.d. on a case-by-case basis.

This CL also adjust a few error typechecker error messages already.

Change-Id: I9d4e491efadf87e999fc0d5b5151ec02a059f891
Reviewed-on: https://go-review.googlesource.com/c/go/+/274312
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
12 files changed:
src/cmd/compile/internal/types2/api.go
src/cmd/compile/internal/types2/api_test.go
src/cmd/compile/internal/types2/assignments.go
src/cmd/compile/internal/types2/builtins.go
src/cmd/compile/internal/types2/decl.go
src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/exprstring.go
src/cmd/compile/internal/types2/exprstring_test.go
src/cmd/compile/internal/types2/testdata/decls3.src
src/cmd/compile/internal/types2/testdata/decls4.src
src/cmd/compile/internal/types2/testdata/issue28251.src
src/cmd/compile/internal/types2/typexpr.go

index eff90d4cdfc81e38e4793657234534fd5b7efaf8..a40665ee17ffa572a780c0d98e9b278c6182eb8d 100644 (file)
@@ -119,6 +119,11 @@ type Config struct {
        //          Do not use casually!
        FakeImportC bool
 
+       // If CompilerErrorMessages is set, errors are reported using
+       // cmd/compile error strings to match $GOROOT/test errors.
+       // TODO(gri) Consolidate error messages and remove this flag.
+       CompilerErrorMessages bool
+
        // If go115UsesCgo is set, the type checker expects the
        // _cgo_gotypes.go file generated by running cmd/cgo to be
        // provided as a package source file. Qualified identifiers
index 403df3f941d38e1ca41d67ef8aa2234951cb0b02..58d7df2f1dac7cd0dbce250f9fe5be9d1024d664 100644 (file)
@@ -687,8 +687,8 @@ func TestPredicatesInfo(t *testing.T) {
 
                // values
                {`package v0; var (a, b int; _ = a + b)`, `a + b`, `value`},
-               {`package v1; var _ = &[]int{1}`, `([]int literal)`, `value`},
-               {`package v2; var _ = func(){}`, `(func() literal)`, `value`},
+               {`package v1; var _ = &[]int{1}`, `[]int{…}`, `value`},
+               {`package v2; var _ = func(){}`, `func() {}`, `value`},
                {`package v4; func f() { _ = f }`, `f`, `value`},
                {`package v3; var _ *int = nil`, `nil`, `value, nil`},
                {`package v3; var _ *int = (nil)`, `(nil)`, `value, nil`},
@@ -896,10 +896,10 @@ func TestInitOrderInfo(t *testing.T) {
                        "z = 0", "a, b = f()",
                }},
                {`package p7; var (a = func() int { return b }(); b = 1)`, []string{
-                       "b = 1", "a = (func() int literal)()",
+                       "b = 1", "a = func() int {…}()",
                }},
                {`package p8; var (a, b = func() (_, _ int) { return c, c }(); c = 1)`, []string{
-                       "c = 1", "a, b = (func() (_, _ int) literal)()",
+                       "c = 1", "a, b = func() (_, _ int) {…}()",
                }},
                {`package p9; type T struct{}; func (T) m() int { _ = y; return 0 }; var x, y = T.m, 1`, []string{
                        "y = 1", "x = T.m",
index 93d3255686cf72e1605615501c3ea8f776480fbd..3178c38adeb7939e8e95a594ff67fd1c38939698 100644 (file)
@@ -63,10 +63,14 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
        }
 
        if reason := ""; !x.assignableTo(check, T, &reason) {
-               if reason != "" {
-                       check.errorf(x, "cannot use %s as %s value in %s: %s", x, T, context, reason)
+               if check.conf.CompilerErrorMessages {
+                       check.errorf(x, "incompatible type: cannot use %s as %s value", x, T)
                } else {
-                       check.errorf(x, "cannot use %s as %s value in %s", x, T, context)
+                       if reason != "" {
+                               check.errorf(x, "cannot use %s as %s value in %s: %s", x, T, context, reason)
+                       } else {
+                               check.errorf(x, "cannot use %s as %s value in %s", x, T, context)
+                       }
                }
                x.mode = invalid
        }
index 6ad84f43540bae1c18c028b85ab7be404abfebaa..43da6a15293055acfcc597c0c32b051aeda45446 100644 (file)
@@ -281,7 +281,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 
                // both argument types must be identical
                if !check.identical(x.typ, y.typ) {
-                       check.invalidArgf(x, "mismatched types %s and %s", x.typ, y.typ)
+                       check.invalidOpf(x, "%s (mismatched types %s and %s)", call, x.typ, y.typ)
                        return
                }
 
index ff37d85c6f4deb484dc36d294c5adf32e389fa26..c7bfd3fd7bd1e626781334fb5a19f31302c6e52a 100644 (file)
@@ -792,7 +792,11 @@ func (check *Checker) collectMethods(obj *TypeName) {
                        case *Var:
                                check.errorf(m.pos, "field and method with the same name %s", m.name)
                        case *Func:
-                               check.errorf(m.pos, "method %s already declared for %s", m.name, obj)
+                               if check.conf.CompilerErrorMessages {
+                                       check.errorf(m.pos, "%s.%s redeclared in this block", obj.Name(), m.name)
+                               } else {
+                                       check.errorf(m.pos, "method %s already declared for %s", m.name, obj)
+                               }
                        default:
                                unreachable()
                        }
index cb92143f93676976c2c5ae9747efcb9ba4e70183..3c9540783af4212737cb132058aa1442a07ecb1f 100644 (file)
@@ -736,7 +736,8 @@ func (check *Checker) comparison(x, y *operand, op syntax.Operator) {
        }
 
        if err != "" {
-               check.errorf(x, "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err)
+               // TODO(gri) better error message for cases where one can only compare against nil
+               check.invalidOpf(x, "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err)
                x.mode = invalid
                return
        }
@@ -1174,6 +1175,9 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
                goto Error
 
        case *syntax.BasicLit:
+               if e.Bad {
+                       goto Error // error was reported before
+               }
                x.setConst(e.Kind, e.Value)
                if x.mode == invalid {
                        // The parser already establishes syntactic correctness.
@@ -1624,7 +1628,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
                        valid = true
                        length = typ.len
                        if x.mode != variable {
-                               check.invalidOpf(x, "cannot slice %s (value not addressable)", x)
+                               check.invalidOpf(x, "%s (slice of unaddressable value)", x)
                                goto Error
                        }
                        x.typ = &Slice{elem: typ.elem}
index e187d050e6823079894bc98adf6f8fe380ebd80a..0ec5d1338f8a97874ece77c18ab143df06f808cb 100644 (file)
@@ -50,14 +50,20 @@ func WriteExpr(buf *bytes.Buffer, x syntax.Expr) {
                buf.WriteString(x.Value)
 
        case *syntax.FuncLit:
-               buf.WriteByte('(')
                WriteExpr(buf, x.Type)
-               buf.WriteString(" literal)") // shortened
+               if x.Body != nil && len(x.Body.List) > 0 {
+                       buf.WriteString(" {…}") // shortened
+               } else {
+                       buf.WriteString(" {}")
+               }
 
        case *syntax.CompositeLit:
-               buf.WriteByte('(')
                WriteExpr(buf, x.Type)
-               buf.WriteString(" literal)") // shortened
+               if len(x.ElemList) > 0 {
+                       buf.WriteString("{…}") // shortened
+               } else {
+                       buf.WriteString("{}")
+               }
 
        case *syntax.ParenExpr:
                buf.WriteByte('(')
index d7b9d5b2ef89b6d98793ea0bdcdad38d7503b0ac..efb7c308b78b855cd7b2629c0608498b16bc313b 100644 (file)
@@ -24,9 +24,9 @@ var testExprs = []testEntry{
        dup("`bar`"),
 
        // func and composite literals
-       {"func(){}", "(func() literal)"},
-       {"func(x int) complex128 {}", "(func(x int) complex128 literal)"},
-       {"[]int{1, 2, 3}", "([]int literal)"},
+       {"func(){}", "func() {}"},
+       {"func(x int) complex128 {}", "func(x int) complex128 {}"},
+       {"[]int{1, 2, 3}", "[]int{…}"},
 
        // non-type expressions
        dup("(x)"),
index 745175c7109390f81eac840585d026e3074bfde3..d7a0c444da12fd03ca2ca7b0c1526c4072624c41 100644 (file)
@@ -221,16 +221,16 @@ func _() {
        _ = S2{}.B
        _ = S2{}.C
        _ = S2{}.D /* ERROR "no field or method" */
-       _ = S3{}.S1 /* ERROR "ambiguous selector \(S3 literal\).S1" */
+       _ = S3{}.S1 /* ERROR "ambiguous selector S3\{\}.S1" */
        _ = S3{}.A
-       _ = S3{}.B /* ERROR "ambiguous selector" \(S3 literal\).B */
+       _ = S3{}.B /* ERROR "ambiguous selector" S3\{\}.B */
        _ = S3{}.D
        _ = S3{}.E
        _ = S4{}.A
        _ = S4{}.B /* ERROR "no field or method" */
-       _ = S5{}.X /* ERROR "ambiguous selector \(S5 literal\).X" */
+       _ = S5{}.X /* ERROR "ambiguous selector S5\{\}.X" */
        _ = S5{}.Y
-       _ = S10{}.X /* ERROR "ambiguous selector \(S10 literal\).X" */
+       _ = S10{}.X /* ERROR "ambiguous selector S10\{\}.X" */
        _ = S10{}.Y
 }
 
@@ -306,4 +306,4 @@ type R22 R21
 type R23 R21
 type R24 R21
 
-var _ = R0{}.X /* ERROR "ambiguous selector \(R0 literal\).X" */
\ No newline at end of file
+var _ = R0{}.X /* ERROR "ambiguous selector R0\{\}.X" */
\ No newline at end of file
index 140bbfd31fdf1cd09e7515d1a2af326acb6e3e10..eb08421beee0011f7064f735c6c7417dc5d73c64 100644 (file)
@@ -190,8 +190,8 @@ type eD struct {
 }
 
 var (
-       _ = eD{}.xf /* ERROR ambiguous selector \(eD literal\).xf */
-       _ = eD{}.xm /* ERROR ambiguous selector \(eD literal\).xm */
+       _ = eD{}.xf /* ERROR ambiguous selector eD\{\}.xf */
+       _ = eD{}.xm /* ERROR ambiguous selector eD\{\}.xm */
 )
 
 var (
index cd79e0e8b5d299e905628654369e8df0db5477fe..ef5e61df47f2c5e332a5db29e82f24bccadbd5e0 100644 (file)
@@ -60,6 +60,6 @@ type (
         T11 = T
 )
 
-func (T9 /* ERROR invalid receiver \*\*T */ ) m9() {}
+func (T9 /* ERROR invalid receiver type \*\*T */ ) m9() {}
 func _() { (T{}).m9 /* ERROR has no field or method m9 */ () }
 func _() { (&T{}).m9 /* ERROR has no field or method m9 */ () }
index 1adf967859a0f6c38c388144d54efd30a460a91e..0c27e5e04bd71363211811917f5850a206733359 100644 (file)
@@ -384,6 +384,10 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
                                // as the method."
                                if T.obj.pkg != check.pkg {
                                        err = "type not defined in this package"
+                                       if check.conf.CompilerErrorMessages {
+                                               check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ)
+                                               err = ""
+                                       }
                                } else {
                                        switch u := optype(T.Under()).(type) {
                                        case *Basic:
@@ -395,11 +399,17 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
                                                err = "pointer or interface type"
                                        }
                                }
-                       } else {
+                       } else if T := t.Basic(); T != nil {
                                err = "basic or unnamed type"
+                               if check.conf.CompilerErrorMessages {
+                                       check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ)
+                                       err = ""
+                               }
+                       } else {
+                               check.errorf(recv.pos, "invalid receiver type %s", recv.typ)
                        }
                        if err != "" {
-                               check.errorf(recv.pos, "invalid receiver %s (%s)", recv.typ, err)
+                               check.errorf(recv.pos, "invalid receiver type %s (%s)", recv.typ, err)
                                // ok to continue
                        }
                }