From 0e6d095d1187dbd1fdf4da0cd452d72b4047fa26 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 23 Sep 2013 15:39:11 -0700 Subject: [PATCH] go.tools/go/types: better error messages for invald expression statements Also: removed some dynamic print formats. R=adonovan CC=golang-dev https://golang.org/cl/13849043 --- go/types/expr.go | 24 ++++++++++++------------ go/types/stmt.go | 16 +++++++++++++--- go/types/testdata/stmt0.src | 13 ++++++++++++- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/go/types/expr.go b/go/types/expr.go index d4ca5eba..096d556f 100644 --- a/go/types/expr.go +++ b/go/types/expr.go @@ -1280,7 +1280,7 @@ func (check *checker) expr0(x *operand, e ast.Expr, hint Type) exprKind { } if e.Op == token.ARROW { x.expr = e - return statement // receive operators may appear in statement context + return statement // receive operations may appear in statement context } case *ast.BinaryExpr: @@ -1329,11 +1329,11 @@ func (check *checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface, } var msg string if wrongType { - msg = "%s cannot have dynamic type %s (wrong type for method %s)" + msg = "wrong type for method" } else { - msg = "%s cannot have dynamic type %s (missing method %s)" + msg = "missing method" } - check.errorf(pos, msg, x, T, method.name) + check.errorf(pos, "%s cannot have dynamic type %s (%s %s)", x, T, msg, method.name) } // expr typechecks expression e and initializes x with the expression value. @@ -1346,13 +1346,13 @@ func (check *checker) expr(x *operand, e ast.Expr) { default: return case novalue: - msg = "%s used as value" + msg = "used as value" case builtin: - msg = "%s must be called" + msg = "must be called" case typexpr: - msg = "%s is not an expression" + msg = "is not an expression" } - check.errorf(x.pos(), msg, x) + check.errorf(x.pos(), "%s %s", x, msg) x.mode = invalid } @@ -1368,13 +1368,13 @@ func (check *checker) exprWithHint(x *operand, e ast.Expr, hint Type) { default: return case novalue: - msg = "%s used as value" + msg = "used as value" case builtin: - msg = "%s must be called" + msg = "must be called" case typexpr: - msg = "%s is not an expression" + msg = "is not an expression" } - check.errorf(x.pos(), msg, x) + check.errorf(x.pos(), "%s %s", x, msg) x.mode = invalid } diff --git a/go/types/stmt.go b/go/types/stmt.go index dfd6338a..87246106 100644 --- a/go/types/stmt.go +++ b/go/types/stmt.go @@ -119,10 +119,20 @@ func (check *checker) stmt(s ast.Stmt, fallthroughOk bool) { // function and method calls and receive operations can appear // in statement context. Such statements may be parenthesized." var x operand - if check.rawExpr(&x, s.X, nil) != statement { - check.errorf(s.X.Pos(), "%s is not used", s.X) + kind := check.rawExpr(&x, s.X, nil) + var msg string + switch x.mode { + default: + if kind == statement { + return + } + msg = "is not used" + case builtin: + msg = "must be called" + case typexpr: + msg = "is not an expression" } - return + check.errorf(x.pos(), "%s %s", &x, msg) case *ast.SendStmt: var ch, x operand diff --git a/go/types/testdata/stmt0.src b/go/types/testdata/stmt0.src index 953c3df8..393af5d6 100644 --- a/go/types/testdata/stmt0.src +++ b/go/types/testdata/stmt0.src @@ -467,4 +467,15 @@ func labels0() { L1: L2: } -} \ No newline at end of file +} + +func expression_statements(ch chan int) { + expression_statements(ch) + <-ch + println() + + 0 /* ERROR "not used" */ + 1 /* ERROR "not used" */ +2 + cap /* ERROR "not used" */ (ch) + println /* ERROR "must be called" */ +}