1
0
mirror of https://github.com/golang/go synced 2024-11-26 08:07:57 -07:00

go/types: more internal cleanups

R=adonovan, bradfitz
CC=golang-dev
https://golang.org/cl/7492045
This commit is contained in:
Robert Griesemer 2013-03-07 11:17:30 -08:00
parent 77ddbf1ff0
commit 6ee75663c9

View File

@ -34,8 +34,8 @@ func (check *checker) assignment(x *operand, to Type) bool {
return x.mode != invalid && x.isAssignable(check.ctxt, to) return x.mode != invalid && x.isAssignable(check.ctxt, to)
} }
// assign1to1 typechecks a single assignment of the form lhs = rhs (if rhs != nil), // assign1to1 typechecks a single assignment of the form lhs = rhs (if rhs != nil), or
// or lhs = x (if rhs == nil). If decl is set, the lhs operand must be an identifier; // lhs = x (if rhs == nil). If decl is set, the lhs expression must be an identifier;
// if its type is not set, it is deduced from the type of x or set to Typ[Invalid] in // if its type is not set, it is deduced from the type of x or set to Typ[Invalid] in
// case of an error. // case of an error.
// //
@ -45,7 +45,7 @@ func (check *checker) assign1to1(lhs, rhs ast.Expr, x *operand, decl bool, iota
if x == nil { if x == nil {
x = new(operand) x = new(operand)
check.expr(x, rhs, nil, iota) check.expr(x, rhs, nil, iota)
// don't exit for declarations - we need the lhs obj first // don't exit for declarations - we need the lhs first
if x.mode == invalid && !decl { if x.mode == invalid && !decl {
return return
} }
@ -117,10 +117,10 @@ func (check *checker) assign1to1(lhs, rhs ast.Expr, x *operand, decl bool, iota
// convert untyped types to default types // convert untyped types to default types
if typ == Typ[UntypedNil] { if typ == Typ[UntypedNil] {
check.errorf(x.pos(), "use of untyped nil") check.errorf(x.pos(), "use of untyped nil")
obj.Type = Typ[Invalid] typ = Typ[Invalid]
return } else {
typ = defaultType(typ)
} }
typ = defaultType(typ)
} }
} }
obj.Type = typ obj.Type = typ
@ -156,15 +156,16 @@ func (check *checker) assign1to1(lhs, rhs ast.Expr, x *operand, decl bool, iota
} }
} }
// assignNtoM typechecks a general assignment. If decl is set, the lhs operands // assignNtoM typechecks a general assignment. If decl is set, the lhs expressions
// must be identifiers. If their types are not set, they are deduced from the // must be identifiers; if their types are not set, they are deduced from the types
// types of the corresponding rhs expressions. iota >= 0 indicates that the // of the corresponding rhs expressions, or set to Typ[Invalid] in case of an error.
// "assignment" is part of a constant/variable declaration.
// Precondition: len(lhs) > 0 . // Precondition: len(lhs) > 0 .
// //
func (check *checker) assignNtoM(lhs, rhs []ast.Expr, decl bool, iota int) { func (check *checker) assignNtoM(lhs, rhs []ast.Expr, decl bool, iota int) {
assert(len(lhs) > 0) assert(len(lhs) > 0)
// If the lhs and rhs have corresponding expressions, treat each
// matching pair as an individual pair.
if len(lhs) == len(rhs) { if len(lhs) == len(rhs) {
for i, e := range rhs { for i, e := range rhs {
check.assign1to1(lhs[i], e, nil, decl, iota) check.assign1to1(lhs[i], e, nil, decl, iota)
@ -172,20 +173,20 @@ func (check *checker) assignNtoM(lhs, rhs []ast.Expr, decl bool, iota int) {
return return
} }
// Otherwise, the rhs must be a single expression (possibly
// a function call returning multiple values, or a comma-ok
// expression).
if len(rhs) == 1 { if len(rhs) == 1 {
// len(lhs) > 1, therefore a correct rhs expression // len(lhs) > 1
// cannot be a shift and we don't need a type hint; // Start with rhs so we have expression types
// ok to evaluate rhs first // for declarations with implicit types.
var x operand var x operand
check.expr(&x, rhs[0], nil, iota) check.expr(&x, rhs[0], nil, iota)
if x.mode == invalid { if x.mode == invalid {
// If decl is set, this leaves the lhs identifiers goto Error
// untyped. We catch this when looking up the respective
// object.
return
} }
if t, ok := x.typ.(*Result); ok && len(lhs) == len(t.Values) { if t, _ := x.typ.(*Result); t != nil && len(lhs) == len(t.Values) {
// function result // function result
x.mode = value x.mode = value
for i, obj := range t.Values { for i, obj := range t.Values {
@ -201,7 +202,6 @@ func (check *checker) assignNtoM(lhs, rhs []ast.Expr, decl bool, iota int) {
x.mode = value x.mode = value
check.assign1to1(lhs[0], nil, &x, decl, iota) check.assign1to1(lhs[0], nil, &x, decl, iota)
x.mode = value
x.typ = Typ[UntypedBool] x.typ = Typ[UntypedBool]
check.assign1to1(lhs[1], nil, &x, decl, iota) check.assign1to1(lhs[1], nil, &x, decl, iota)
return return
@ -210,20 +210,22 @@ func (check *checker) assignNtoM(lhs, rhs []ast.Expr, decl bool, iota int) {
check.errorf(lhs[0].Pos(), "assignment count mismatch: %d = %d", len(lhs), len(rhs)) check.errorf(lhs[0].Pos(), "assignment count mismatch: %d = %d", len(lhs), len(rhs))
// avoid checking the same declaration over and over Error:
// again for each lhs identifier that has no type yet // In case of a declaration, set all lhs types to Typ[Invalid].
if iota >= 0 { if decl {
// declaration
for _, e := range lhs { for _, e := range lhs {
if name, ok := e.(*ast.Ident); ok { ident, _ := e.(*ast.Ident)
switch obj := check.lookup(name).(type) { if ident == nil {
case *Const: check.errorf(e.Pos(), "cannot declare %s", e)
obj.Type = Typ[Invalid] continue
case *Var: }
obj.Type = Typ[Invalid] switch obj := check.lookup(ident).(type) {
default: case *Const:
unreachable() obj.Type = Typ[Invalid]
} case *Var:
obj.Type = Typ[Invalid]
default:
unreachable()
} }
} }
} }