mirror of
https://github.com/golang/go
synced 2024-11-18 16:14:46 -07:00
go.tools/go/types: no errors for x.(T) where T is an interface
Also: Added Config.Strict flag to enable type checker tests beyond the Go 1 specification. Fixes golang/go#8561. LGTM=adonovan R=adonovan CC=golang-codereviews https://golang.org/cl/134050043
This commit is contained in:
parent
cd5b7ff318
commit
289e96cc26
@ -79,6 +79,18 @@ 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
|
||||
|
@ -20,6 +20,9 @@
|
||||
// _ = x /* ERROR "not declared" */ + 1
|
||||
// }
|
||||
|
||||
// TODO(gri) Also collect strict mode errors of the form /* STRICT ... */
|
||||
// and test against strict mode.
|
||||
|
||||
package types_test
|
||||
|
||||
import (
|
||||
|
@ -1406,10 +1406,18 @@ 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)
|
||||
if method == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var msg string
|
||||
if wrongType {
|
||||
msg = "wrong type for method"
|
||||
|
2
go/types/testdata/expr3.src
vendored
2
go/types/testdata/expr3.src
vendored
@ -381,7 +381,7 @@ func type_asserts() {
|
||||
_ = t.(*T)
|
||||
_ = t /* ERROR "missing method m" */ .(T1)
|
||||
_ = t /* ERROR "wrong type for method m" */ .(T2)
|
||||
_ = t /* ERROR "wrong type for method m" */ .(I2)
|
||||
_ = t /* STRICT "wrong type for method m" */ .(I2) // only an error in strict mode (issue 8561)
|
||||
|
||||
// e doesn't statically have an m, but may have one dynamically.
|
||||
_ = e.(I2)
|
||||
|
4
go/types/testdata/stmt0.src
vendored
4
go/types/testdata/stmt0.src
vendored
@ -558,7 +558,7 @@ func typeswitches() {
|
||||
case T:
|
||||
case T1 /* ERROR "missing method m" */ :
|
||||
case T2 /* ERROR "wrong type for method m" */ :
|
||||
case I2 /* ERROR "wrong type for method m" */ :
|
||||
case I2 /* STRICT "wrong type for method m" */ : // only an error in strict mode (issue 8561)
|
||||
}
|
||||
}
|
||||
|
||||
@ -596,7 +596,7 @@ func typeswitch2() {
|
||||
switch A(nil).(type) {
|
||||
case A:
|
||||
case B:
|
||||
case C /* ERROR "cannot have dynamic type" */:
|
||||
case C /* STRICT "cannot have dynamic type" */: // only an error in strict mode (issue 8561)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user