mirror of https://github.com/golang/go.git
go/types: minor improvements in tracing output, removed some TODOs
Also: added failing test cases to NOTES Change-Id: Ie7b823b4cc46c64068749676d7a1464082e60264
This commit is contained in:
parent
57c8d7fe0a
commit
be92a40c3f
|
|
@ -6,7 +6,33 @@ TODO
|
|||
- interface embedding doesn't take care of literal type constraints yet
|
||||
(need an allTypes list, like we have an allMethods list?)
|
||||
|
||||
|
||||
OPEN ISSUES
|
||||
- type constraints are not verified in some cases:
|
||||
|
||||
package p
|
||||
|
||||
type B interface{type int}
|
||||
|
||||
func f(type P B)(x P) {}
|
||||
|
||||
func _() {
|
||||
f(string)("foo") // this should be invalid
|
||||
f("foo") // this should be invalid
|
||||
}
|
||||
|
||||
- incorrect constraint errors:
|
||||
|
||||
package p
|
||||
|
||||
contract B(T) {
|
||||
T int
|
||||
}
|
||||
|
||||
type T(type P B) P
|
||||
|
||||
func f(type P B)(x T(P)) // this should be valid
|
||||
|
||||
|
||||
DESIGN DECISIONS
|
||||
- 12/4/2019: do not allow parenthesized generic uninstantiated types (unless instantiated implicitly)
|
||||
|
|
|
|||
|
|
@ -976,7 +976,7 @@ const (
|
|||
//
|
||||
func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
if check.conf.Trace {
|
||||
check.trace(e.Pos(), "%s", e)
|
||||
check.trace(e.Pos(), "expr %s", e)
|
||||
check.indent++
|
||||
defer func() {
|
||||
check.indent--
|
||||
|
|
|
|||
|
|
@ -461,7 +461,15 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
|
|||
if i > 0 {
|
||||
fmt.Fprint(buf, ", ")
|
||||
}
|
||||
fmt.Fprintf(buf, "%s", p.name)
|
||||
buf.WriteString(p.name)
|
||||
if p.typ != nil {
|
||||
if ptyp, _ := p.typ.(*TypeParam); ptyp != nil && ptyp.bound != nil {
|
||||
buf.WriteByte(' ')
|
||||
WriteType(buf, ptyp.bound, qf)
|
||||
// TODO(gri) if this is a generic type bound, we should print
|
||||
// the type parameters
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprint(buf, ")")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ type A struct{}
|
|||
|
||||
func (A) a() {}
|
||||
|
||||
var _ T1 /* ERROR not satisfied */ (int, int)
|
||||
var _ T1(int /* ERROR not satisfied */ , int)
|
||||
var _ T1(A, int)
|
||||
|
||||
contract Stringer(T) {
|
||||
|
|
@ -96,7 +96,7 @@ type List(type T Stringer) struct{
|
|||
}
|
||||
|
||||
var _ List(MyData)
|
||||
var _ List /* ERROR not satisfied */ (int)
|
||||
var _ List(int /* ERROR not satisfied */ )
|
||||
|
||||
type MyData string
|
||||
|
||||
|
|
@ -110,10 +110,10 @@ contract C3(T) {
|
|||
|
||||
type T2 (type _ C3) struct{}
|
||||
|
||||
var _ T2 /* ERROR not satisfied */ (int8)
|
||||
var _ T2(int8 /* ERROR not satisfied */ )
|
||||
var _ T2(int16)
|
||||
var _ T2(int32)
|
||||
var _ T2 /* ERROR not satisfied */ (int64)
|
||||
var _ T2(int64 /* ERROR not satisfied */ )
|
||||
var _ T2(int)
|
||||
var _ T2(struct{x int})
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ contract C(T) {
|
|||
|
||||
type Cm(type T C) T
|
||||
|
||||
func (a Cm /* ERROR not satisfied */ (T)) m() T
|
||||
func (a Cm(T /* ERROR not satisfied */ )) m() T
|
||||
|
||||
// TODO(gri) make this work
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
|
|||
//
|
||||
func (check *Checker) typInternal(e ast.Expr, def *Named) (T Type) {
|
||||
if check.conf.Trace {
|
||||
check.trace(e.Pos(), "expr %s", e)
|
||||
check.trace(e.Pos(), "type %s", e)
|
||||
check.indent++
|
||||
defer func() {
|
||||
check.indent--
|
||||
|
|
@ -272,28 +272,25 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) (T Type) {
|
|||
return typ // error already reported
|
||||
}
|
||||
|
||||
// evaluate arguments (always)
|
||||
targs := check.typeList(e.Args)
|
||||
if targs == nil {
|
||||
return Typ[Invalid]
|
||||
}
|
||||
|
||||
// the number of supplied types must match the number of type parameters
|
||||
// TODO(gri) fold into code below - we want to eval args always
|
||||
named, _ := typ.(*Named) // generic types are defined (= Named) types
|
||||
tname := named.obj
|
||||
if len(e.Args) != len(tname.tparams) {
|
||||
if len(targs) != len(tname.tparams) {
|
||||
// TODO(gri) provide better error message
|
||||
check.errorf(e.Pos(), "got %d arguments but %d type parameters", len(e.Args), len(tname.tparams))
|
||||
return Typ[Invalid]
|
||||
}
|
||||
|
||||
// evaluate arguments
|
||||
targs := check.typeList(e.Args)
|
||||
if targs == nil {
|
||||
return Typ[Invalid]
|
||||
}
|
||||
assert(len(targs) == len(tname.tparams))
|
||||
|
||||
// substitute type bound parameters with arguments
|
||||
// and check if each argument satisfies its bound
|
||||
for i, tpar := range tname.tparams {
|
||||
pos := e.Args[i].Pos()
|
||||
pos = e.Pos() // TODO(gri) remove in favor of more accurate pos on prev. line?
|
||||
bound := tpar.typ.(*TypeParam).bound // interface or contract or nil
|
||||
if bound == nil {
|
||||
continue // nothing to do
|
||||
|
|
@ -477,19 +474,16 @@ func (check *Checker) arrayLength(e ast.Expr) int64 {
|
|||
// If an error occured, the result is nil, but all list elements were type-checked.
|
||||
func (check *Checker) typeList(list []ast.Expr) []Type {
|
||||
res := make([]Type, len(list)) // res != nil even if len(list) == 0
|
||||
ok := true
|
||||
for i, x := range list {
|
||||
t := check.typ(x)
|
||||
if t == Typ[Invalid] {
|
||||
ok = false
|
||||
res = nil
|
||||
}
|
||||
if res != nil {
|
||||
res[i] = t
|
||||
}
|
||||
res[i] = t
|
||||
}
|
||||
if ok {
|
||||
return res
|
||||
|
||||
}
|
||||
return nil
|
||||
return res
|
||||
}
|
||||
|
||||
func (check *Checker) satisfyBound(pos token.Pos, tname *TypeName, arg Type, bound *Interface) bool {
|
||||
|
|
|
|||
Loading…
Reference in New Issue