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): 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): 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): Unused variables and imports are not reported.
// BUG(gri): Interface vs non-interface comparisons are not correctly implemented. // BUG(gri): Interface vs non-interface comparisons are not correctly implemented.
// BUG(gri): Switch statements don't check correct use of 'fallthrough'. // 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 var ctxt Context
return ctxt.Check(path, fset, files...) 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) 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) { 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 { if x.mode == invalid {
goto Error 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) check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.key)
goto Error goto Error
} }

View File

@ -93,7 +93,7 @@ Error:
func (x *operand) isConvertible(ctxt *Context, T Type) bool { func (x *operand) isConvertible(ctxt *Context, T Type) bool {
// "x is assignable to T" // "x is assignable to T"
if x.isAssignable(ctxt, T) { if x.isAssignableTo(ctxt, T) {
return true 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 // TODO(gri) deal with interface vs non-interface comparison
valid := false 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 { switch op {
case token.EQL, token.NEQ: case token.EQL, token.NEQ:
valid = isComparable(x.typ) || valid = isComparable(x.typ) ||

View File

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