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
This commit is contained in:
Robert Griesemer 2013-09-23 15:39:11 -07:00
parent 318b83e376
commit 0e6d095d11
3 changed files with 37 additions and 16 deletions

View File

@ -1280,7 +1280,7 @@ func (check *checker) expr0(x *operand, e ast.Expr, hint Type) exprKind {
} }
if e.Op == token.ARROW { if e.Op == token.ARROW {
x.expr = e x.expr = e
return statement // receive operators may appear in statement context return statement // receive operations may appear in statement context
} }
case *ast.BinaryExpr: case *ast.BinaryExpr:
@ -1329,11 +1329,11 @@ func (check *checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface,
} }
var msg string var msg string
if wrongType { if wrongType {
msg = "%s cannot have dynamic type %s (wrong type for method %s)" msg = "wrong type for method"
} else { } 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. // 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: default:
return return
case novalue: case novalue:
msg = "%s used as value" msg = "used as value"
case builtin: case builtin:
msg = "%s must be called" msg = "must be called"
case typexpr: 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 x.mode = invalid
} }
@ -1368,13 +1368,13 @@ func (check *checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
default: default:
return return
case novalue: case novalue:
msg = "%s used as value" msg = "used as value"
case builtin: case builtin:
msg = "%s must be called" msg = "must be called"
case typexpr: 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 x.mode = invalid
} }

View File

@ -119,10 +119,20 @@ func (check *checker) stmt(s ast.Stmt, fallthroughOk bool) {
// function and method calls and receive operations can appear // function and method calls and receive operations can appear
// in statement context. Such statements may be parenthesized." // in statement context. Such statements may be parenthesized."
var x operand var x operand
if check.rawExpr(&x, s.X, nil) != statement { kind := check.rawExpr(&x, s.X, nil)
check.errorf(s.X.Pos(), "%s is not used", s.X) var msg string
} switch x.mode {
default:
if kind == statement {
return return
}
msg = "is not used"
case builtin:
msg = "must be called"
case typexpr:
msg = "is not an expression"
}
check.errorf(x.pos(), "%s %s", &x, msg)
case *ast.SendStmt: case *ast.SendStmt:
var ch, x operand var ch, x operand

View File

@ -468,3 +468,14 @@ func labels0() {
L2: L2:
} }
} }
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" */
}