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.
|
// 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
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@
|
||||||
// _ = x /* ERROR "not declared" */ + 1
|
// _ = x /* ERROR "not declared" */ + 1
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// TODO(gri) Also collect strict mode errors of the form /* STRICT ... */
|
||||||
|
// and test against strict mode.
|
||||||
|
|
||||||
package types_test
|
package types_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -1406,10 +1406,18 @@ 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
|
||||||
|
// 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 := MissingMethod(T, xtyp, false)
|
||||||
if method == nil {
|
if method == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
if wrongType {
|
if wrongType {
|
||||||
msg = "wrong type for method"
|
msg = "wrong type for method"
|
||||||
|
|
|
||||||
|
|
@ -381,7 +381,7 @@ func type_asserts() {
|
||||||
_ = t.(*T)
|
_ = t.(*T)
|
||||||
_ = t /* ERROR "missing method m" */ .(T1)
|
_ = t /* ERROR "missing method m" */ .(T1)
|
||||||
_ = t /* ERROR "wrong type for method m" */ .(T2)
|
_ = 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 doesn't statically have an m, but may have one dynamically.
|
||||||
_ = e.(I2)
|
_ = e.(I2)
|
||||||
|
|
|
||||||
|
|
@ -558,7 +558,7 @@ func typeswitches() {
|
||||||
case T:
|
case T:
|
||||||
case T1 /* ERROR "missing method m" */ :
|
case T1 /* ERROR "missing method m" */ :
|
||||||
case T2 /* ERROR "wrong type for 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) {
|
switch A(nil).(type) {
|
||||||
case A:
|
case A:
|
||||||
case B:
|
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