From 5ec27f6da9bf8d877d92150564f2c11da3e27892 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 11 Jul 2013 14:23:23 -0700 Subject: [PATCH] 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 --- go/types/api.go | 9 ++++++++- go/types/assignments.go | 2 +- go/types/builtins.go | 2 +- go/types/conversions.go | 2 +- go/types/expr.go | 2 +- go/types/operand.go | 6 +++--- 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/go/types/api.go b/go/types/api.go index d203126e..06e1c7b6 100644 --- a/go/types/api.go +++ b/go/types/api.go @@ -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 +} diff --git a/go/types/assignments.go b/go/types/assignments.go index 4d5b59c6..f7dd63c8 100644 --- a/go/types/assignments.go +++ b/go/types/assignments.go @@ -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) { diff --git a/go/types/builtins.go b/go/types/builtins.go index e6233cac..f0203d4e 100644 --- a/go/types/builtins.go +++ b/go/types/builtins.go @@ -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 } diff --git a/go/types/conversions.go b/go/types/conversions.go index 6d999df2..7ca10089 100644 --- a/go/types/conversions.go +++ b/go/types/conversions.go @@ -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 } diff --git a/go/types/expr.go b/go/types/expr.go index 6b416720..3a0205e0 100644 --- a/go/types/expr.go +++ b/go/types/expr.go @@ -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) || diff --git a/go/types/operand.go b/go/types/operand.go index f42fc7b0..43d70b71 100644 --- a/go/types/operand.go +++ b/go/types/operand.go @@ -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 }