go.tools/go/types: remove Strict mode from API

Also: factor out shared code assertableTo.

LGTM=adonovan
R=adonovan, gordon.klaus
CC=golang-codereviews
https://golang.org/cl/139880043
This commit is contained in:
Robert Griesemer 2014-08-29 09:15:36 -07:00
parent 2b15aa63b7
commit a4d1505cfc
4 changed files with 29 additions and 22 deletions

View File

@ -79,18 +79,6 @@ type Importer func(map[string]*Package, string) (*Package, error)
// A Config specifies the configuration for type checking. // A Config specifies the configuration for type checking.
// The zero value for Config is a ready-to-use default configuration. // The zero value for Config is a ready-to-use default configuration.
type Config struct { type Config struct {
// If Strict is set, the type-checker enforces additional
// rules not specified by the Go 1 spec, but which will
// catch guaranteed run-time errors if the respective
// code is executed. In other words, programs passing in
// Strict mode are Go 1 compliant, but not all Go 1 programs
// will pass in Strict mode. The additional rules are:
//
// - A type assertion x.(T) where T is an interface type
// is invalid if any (statically known) method that exists
// for both x and T have different signatures.
Strict bool
// If IgnoreFuncBodies is set, function bodies are not // If IgnoreFuncBodies is set, function bodies are not
// type-checked. // type-checked.
IgnoreFuncBodies bool IgnoreFuncBodies bool
@ -345,8 +333,8 @@ func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, i
// AssertableTo reports whether a value of type V can be asserted to have type T. // AssertableTo reports whether a value of type V can be asserted to have type T.
func AssertableTo(V *Interface, T Type) bool { func AssertableTo(V *Interface, T Type) bool {
f, _ := MissingMethod(T, V, false) m, _ := assertableTo(V, T)
return f == nil return m == nil
} }
// AssignableTo reports whether a value of type V is assignable to a variable of type T. // AssignableTo reports whether a value of type V is assignable to a variable of type T.

View File

@ -20,6 +20,19 @@ const (
trace = false // turn on for detailed type resolution traces trace = false // turn on for detailed type resolution traces
) )
// If Strict is set, the type-checker enforces additional
// rules not specified by the Go 1 spec, but which will
// catch guaranteed run-time errors if the respective
// code is executed. In other words, programs passing in
// Strict mode are Go 1 compliant, but not all Go 1 programs
// will pass in Strict mode. The additional rules are:
//
// - A type assertion x.(T) where T is an interface type
// is invalid if any (statically known) method that exists
// for both x and T have different signatures.
//
const strict = false
// exprInfo stores information about an untyped expression. // exprInfo stores information about an untyped expression.
type exprInfo struct { type exprInfo struct {
isLhs bool // expression is lhs operand of a shift with delayed type-check isLhs bool // expression is lhs operand of a shift with delayed type-check

View File

@ -1406,14 +1406,7 @@ Error:
// typeAssertion checks that x.(T) is legal; xtyp must be the type of x. // typeAssertion checks that x.(T) is legal; xtyp must be the type of x.
func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface, T Type) { func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface, T Type) {
// no static check is required if T is an interface method, wrongType := assertableTo(xtyp, T)
// spec: "If T is an interface type, x.(T) asserts that the
// dynamic type of x implements the interface T."
if _, ok := T.Underlying().(*Interface); ok && !check.conf.Strict {
return
}
method, wrongType := MissingMethod(T, xtyp, false)
if method == nil { if method == nil {
return return
} }

View File

@ -293,6 +293,19 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b
return return
} }
// assertableTo reports whether a value of type V can be asserted to have type T.
// It returns (nil, false) as affirmative answer. Otherwise it returns a missing
// method required by V and whether it is missing or just has the wrong type.
func assertableTo(V *Interface, T Type) (method *Func, wrongType bool) {
// no static check is required if T is an interface
// spec: "If T is an interface type, x.(T) asserts that the
// dynamic type of x implements the interface T."
if _, ok := T.Underlying().(*Interface); ok && !strict {
return
}
return MissingMethod(T, V, false)
}
// deref dereferences typ if it is a *Pointer and returns its base and true. // deref dereferences typ if it is a *Pointer and returns its base and true.
// Otherwise it returns (typ, false). // Otherwise it returns (typ, false).
func deref(typ Type) (Type, bool) { func deref(typ Type) (Type, bool) {