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:
parent
424b1fda00
commit
5ec27f6da9
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) ||
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue