func (check *Checker) initVars(lhs []*Var, rhs *ast.ExprList, returnPos token.Pos, entangledLhs *Var) {
	check.checkVars(lhs, rhs, returnPos, entangledLhs, func(_ int, lhs *Var, x *operand, context string) Type {
		return check.initVar(lhs, x, context)
	})
}
If returnPos is valid, initVars is called to type-check the assignment of
return expressions, and returnPos is the position of the return statement.
package types
import (
	"fmt"
	"github.com/tcard/sgo/sgo/ast"
	"github.com/tcard/sgo/sgo/constant"
	"github.com/tcard/sgo/sgo/token"
)
func (check *Checker) assignment(x *operand, T Type, context string) {
	check.singleValue(x)
	switch x.mode {
	case invalid:
		return  
	case constant_, variable, mapindex, value, commaok:
	default:
		unreachable()
	}
	if isUntyped(x.typ) {
		target := T
		if T == nil || IsInterface(T) {
			if T == nil && x.typ == Typ[UntypedNil] {
				check.errorf(x.pos(), "use of untyped nil in %s", context)
				x.mode = invalid
				return
			}
			target = Default(x.typ)
		}
		check.convertUntyped(x, target)
		if x.mode == invalid {
			return
		}
	}
	if T == nil {
		return
	}
	if reason := ""; !x.assignableTo(check.conf, T, &reason) {
		if reason != "" {
			check.errorf(x.pos(), "cannot use %s as %s value in %s: %s", x, T, context, reason)
		} else {
			check.errorf(x.pos(), "cannot use %s as %s value in %s", x, T, context)
		}
		x.mode = invalid
	}
}
func (check *Checker) initConst(lhs *Const, x *operand) {
	if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
		if lhs.typ == nil {
			lhs.typ = Typ[Invalid]
		}
		return
	}
	if x.mode != constant_ {
		check.errorf(x.pos(), "%s is not constant", x)
		if lhs.typ == nil {
			lhs.typ = Typ[Invalid]
		}
		return
	}
	assert(isConstType(x.typ))
	if lhs.typ == nil {
		lhs.typ = x.typ
	}
	check.assignment(x, lhs.typ, "constant declaration")
	if x.mode == invalid {
		return
	}
	lhs.val = x.val
}
func (check *Checker) initVar(lhs *Var, x *operand, context string) Type {
	if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
		if lhs.typ == nil {
			lhs.typ = Typ[Invalid]
		}
		return nil
	}
	if lhs.typ == nil {
		typ := x.typ
		if isUntyped(typ) {
			if typ == Typ[UntypedNil] {
				check.errorf(x.pos(), "use of untyped nil in %s", context)
				lhs.typ = Typ[Invalid]
				return nil
			}
			typ = Default(typ)
		}
		lhs.setType(typ)
		lhs.usable = true
		if debugUsable {
			fmt.Println("USABLE initVar:", lhs.name, fmt.Sprintf("%p", lhs), lhs.usable)
		}
	}
	check.assignment(x, lhs.typ, context)
	if x.mode == invalid {
		return nil
	}
	return x.typ
}
func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
	if x.mode == invalid || x.typ == Typ[Invalid] {
		return nil
	}
	ident, _ := unparen(lhs).(*ast.Ident)
	if ident != nil && ident.Name == "_" {
		check.recordDef(ident, nil)
		check.assignment(x, nil, "assignment to _ identifier")
		if x.mode == invalid {
			return nil
		}
		return x.typ
	}
	var v *Var
	var v_used bool
	if ident != nil {
		if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
			if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
				v = w
				v_used = v.used
				v.usable = true
				if debugUsable {
					fmt.Println("USABLE assignVar:", v.name, fmt.Sprintf("%p", v), v.usable)
				}
			}
		}
	}
	var z operand
	z.lhs = true
	check.expr(&z, lhs)
	if v != nil {
		v.used = v_used  
	}
	if z.mode == invalid || z.typ == Typ[Invalid] {
		return nil
	}
	switch z.mode {
	case invalid:
		return nil
	case variable, mapindex:
	default:
		if sel, ok := z.expr.(*ast.SelectorExpr); ok {
			var op operand
			check.expr(&op, sel.X)
			if op.mode == mapindex {
				check.errorf(z.pos(), "cannot assign to struct field %s in map", ExprString(z.expr))
				return nil
			}
		}
		check.errorf(z.pos(), "cannot assign to %s", &z)
		return nil
	}
	check.assignment(x, z.typ, "assignment")
	if x.mode == invalid {
		return nil
	}
	return x.typ
}