From a4d1505cfc0c9e4bf946db7d1662c8643f974b3d Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 29 Aug 2014 09:15:36 -0700 Subject: [PATCH] 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 --- go/types/api.go | 16 ++-------------- go/types/check.go | 13 +++++++++++++ go/types/expr.go | 9 +-------- go/types/lookup.go | 13 +++++++++++++ 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/go/types/api.go b/go/types/api.go index 7e98d054..2079a384 100644 --- a/go/types/api.go +++ b/go/types/api.go @@ -79,18 +79,6 @@ type Importer func(map[string]*Package, string) (*Package, error) // A Config specifies the configuration for type checking. // The zero value for Config is a ready-to-use default configuration. 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 // type-checked. 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. func AssertableTo(V *Interface, T Type) bool { - f, _ := MissingMethod(T, V, false) - return f == nil + m, _ := assertableTo(V, T) + return m == nil } // AssignableTo reports whether a value of type V is assignable to a variable of type T. diff --git a/go/types/check.go b/go/types/check.go index 0e24f04f..c527ca3d 100644 --- a/go/types/check.go +++ b/go/types/check.go @@ -20,6 +20,19 @@ const ( 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. type exprInfo struct { isLhs bool // expression is lhs operand of a shift with delayed type-check diff --git a/go/types/expr.go b/go/types/expr.go index 22d5b804..cda473f3 100644 --- a/go/types/expr.go +++ b/go/types/expr.go @@ -1406,14 +1406,7 @@ Error: // 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) { - // 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 && !check.conf.Strict { - return - } - - method, wrongType := MissingMethod(T, xtyp, false) + method, wrongType := assertableTo(xtyp, T) if method == nil { return } diff --git a/go/types/lookup.go b/go/types/lookup.go index b4fc74ce..2d2b0990 100644 --- a/go/types/lookup.go +++ b/go/types/lookup.go @@ -293,6 +293,19 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b 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. // Otherwise it returns (typ, false). func deref(typ Type) (Type, bool) {