go.tools/go/types: export IsAssignableTo

Tested implictly since its simply calling the
internal isAssignableTo which is used in every
assignment when testing the std library.

R=adonovan
CC=golang-dev
https://golang.org/cl/11189043
This commit is contained in:
Robert Griesemer 2013-07-11 14:23:23 -07:00
parent 424b1fda00
commit 5ec27f6da9
6 changed files with 15 additions and 8 deletions

View File

@ -35,7 +35,7 @@ package types
//
// BUG(gri): Conversions of constants only change the type, not the value (e.g., int(1.1) is wrong).
// BUG(gri): Some built-ins don't check parameters fully, yet (e.g. append).
// BUG(gri): Use of labels is not checked.
// BUG(gri): Use of labels is only partially checked.
// BUG(gri): Unused variables and imports are not reported.
// BUG(gri): Interface vs non-interface comparisons are not correctly implemented.
// BUG(gri): Switch statements don't check correct use of 'fallthrough'.
@ -150,3 +150,10 @@ func Check(path string, fset *token.FileSet, files ...*ast.File) (*Package, erro
var ctxt Context
return ctxt.Check(path, fset, files...)
}
// IsAssignableTo reports whether a value of type V
// is assignable to a variable of type T.
func IsAssignableTo(V, T Type) bool {
x := operand{mode: value, typ: V}
return x.isAssignableTo(nil, T) // context not needed for non-constant x
}

View File

@ -32,7 +32,7 @@ func (check *checker) assignment(x *operand, to Type) bool {
check.convertUntyped(x, to)
return x.mode != invalid && x.isAssignable(check.ctxt, to)
return x.mode != invalid && x.isAssignableTo(check.ctxt, to)
}
func (check *checker) initConst(lhs *Const, x *operand) {

View File

@ -236,7 +236,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *Builtin) {
if x.mode == invalid {
goto Error
}
if !x.isAssignable(check.ctxt, m.key) {
if !x.isAssignableTo(check.ctxt, m.key) {
check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.key)
goto Error
}

View File

@ -93,7 +93,7 @@ Error:
func (x *operand) isConvertible(ctxt *Context, T Type) bool {
// "x is assignable to T"
if x.isAssignable(ctxt, T) {
if x.isAssignableTo(ctxt, T) {
return true
}

View File

@ -471,7 +471,7 @@ func (check *checker) comparison(x, y *operand, op token.Token) {
// TODO(gri) deal with interface vs non-interface comparison
valid := false
if x.isAssignable(check.ctxt, y.typ) || y.isAssignable(check.ctxt, x.typ) {
if x.isAssignableTo(check.ctxt, y.typ) || y.isAssignableTo(check.ctxt, x.typ) {
switch op {
case token.EQL, token.NEQ:
valid = isComparable(x.typ) ||

View File

@ -122,12 +122,12 @@ func (x *operand) isNil() bool {
return x.mode == constant && x.val.Kind() == exact.Nil
}
// TODO(gri) The functions operand.isAssignable, checker.convertUntyped,
// TODO(gri) The functions operand.isAssignableTo, checker.convertUntyped,
// checker.isRepresentable, and checker.assignOperand are
// overlapping in functionality. Need to simplify and clean up.
// isAssignable reports whether x is assignable to a variable of type T.
func (x *operand) isAssignable(ctxt *Context, T Type) bool {
// isAssignableTo reports whether x is assignable to a variable of type T.
func (x *operand) isAssignableTo(ctxt *Context, T Type) bool {
if x.mode == invalid || T == Typ[Invalid] {
return true // avoid spurious errors
}