check.expr(x, lhs, nil, iota)
check.expr(&y, rhs, nil, iota)
+ if x.mode == invalid {
+ return
+ }
+ if y.mode == invalid {
+ x.mode = invalid
+ x.expr = y.expr
+ return
+ }
+
if isShift(op) {
check.shift(x, &y, op)
return
case *ast.IndexExpr:
check.expr(x, e.X, nil, iota)
+ if x.mode == invalid {
+ goto Error
+ }
valid := false
length := int64(-1) // valid if >= 0
case *Map:
var key operand
check.expr(&key, e.Index, nil, iota)
- if key.mode == invalid || !check.assignment(&key, typ.Key) {
- if x.mode != invalid {
- check.invalidOp(x.pos(), "cannot use %s as map index of type %s", &key, typ.Key)
+ if !check.assignment(&key, typ.Key) {
+ if key.mode != invalid {
+ check.invalidOp(key.pos(), "cannot use %s as map index of type %s", &key, typ.Key)
}
goto Error
}
case *ast.SliceExpr:
check.expr(x, e.X, nil, iota)
+ if x.mode == invalid {
+ goto Error
+ }
valid := false
length := int64(-1) // valid if >= 0
case *ast.UnaryExpr:
check.expr(x, e.X, nil, iota)
+ if x.mode == invalid {
+ goto Error
+ }
check.unary(x, e.Op)
+ if x.mode == invalid {
+ goto Error
+ }
case *ast.BinaryExpr:
check.binary(x, e.X, e.Y, e.Op, iota)
+ if x.mode == invalid {
+ goto Error
+ }
case *ast.KeyValueExpr:
// key:value expressions are handled in composite literals
x.typ = &Chan{Dir: e.Dir, Elt: check.typ(e.Value, true)}
default:
- check.dump("e = %s", e)
+ if debug {
+ check.dump("expr = %v (%T)", e, e)
+ }
unreachable()
}
// TODO(gri) This latter behavior is for historic reasons and complicates
// callers. Needs to be cleaned up.
func (check *checker) assignment(x *operand, to Type) bool {
+ if x.mode == invalid {
+ return false
+ }
+
if t, ok := x.typ.(*Result); ok {
// TODO(gri) elsewhere we use "assignment count mismatch" (consolidate)
check.errorf(x.pos(), "%d-valued expression %s used as single value", len(t.Values), x)