mirror of https://github.com/golang/go.git
go/types: prepare resolver for types with type parameters
Change-Id: If4395181b5683750098aefd5292a00921b3a5427
This commit is contained in:
parent
7d54168ae9
commit
aa0fabb90e
|
|
@ -101,6 +101,7 @@ var tests = [][]string{
|
|||
|
||||
// Go 2 tests (type parameters and contracts)
|
||||
{"testdata/typeparams.go2"},
|
||||
//{"testdata/typeinst.go2"},
|
||||
{"testdata/contracts.go2"},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -183,13 +183,13 @@ func (check *Checker) objDecl(obj Object, def *Named) {
|
|||
switch obj := obj.(type) {
|
||||
case *Const:
|
||||
check.decl = d // new package-level const decl
|
||||
check.constDecl(obj, d.typ, d.init)
|
||||
check.constDecl(obj, d.vtyp, d.init)
|
||||
case *Var:
|
||||
check.decl = d // new package-level var decl
|
||||
check.varDecl(obj, d.lhs, d.typ, d.init)
|
||||
check.varDecl(obj, d.lhs, d.vtyp, d.init)
|
||||
case *TypeName:
|
||||
// invalid recursive types are detected via path
|
||||
check.typeDecl(obj, d.typ, def, d.alias)
|
||||
check.typeDecl(obj, d.tdecl, def)
|
||||
case *Func:
|
||||
// functions may be recursive - no need to track dependencies
|
||||
check.funcDecl(obj, d)
|
||||
|
|
@ -234,7 +234,7 @@ func (check *Checker) cycle(obj Object) (isCycle bool) {
|
|||
// this information explicitly in the object.
|
||||
var alias bool
|
||||
if d := check.objMap[obj]; d != nil {
|
||||
alias = d.alias // package-level object
|
||||
alias = d.tdecl.Assign.IsValid() // package-level object
|
||||
} else {
|
||||
alias = obj.IsAlias() // function local object
|
||||
}
|
||||
|
|
@ -539,26 +539,28 @@ func (n *Named) setUnderlying(typ Type) {
|
|||
}
|
||||
}
|
||||
|
||||
func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, alias bool) {
|
||||
func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
|
||||
assert(obj.typ == nil)
|
||||
|
||||
check.later(func() {
|
||||
check.validType(obj.typ, nil)
|
||||
})
|
||||
|
||||
if alias {
|
||||
if tdecl.Assign.IsValid() {
|
||||
// type alias declaration
|
||||
|
||||
obj.typ = Typ[Invalid]
|
||||
obj.typ = check.typ(typ)
|
||||
obj.typ = check.typ(tdecl.Type)
|
||||
|
||||
} else {
|
||||
// defined type declaration
|
||||
|
||||
named := &Named{obj: obj}
|
||||
def.setUnderlying(named)
|
||||
obj.typ = named // make sure recursive type declarations terminate
|
||||
|
||||
// determine underlying type of named
|
||||
named.orig = check.definedType(typ, named)
|
||||
named.orig = check.definedType(tdecl.Type, named)
|
||||
|
||||
// The underlying type of named may be itself a named type that is
|
||||
// incomplete:
|
||||
|
|
@ -590,7 +592,7 @@ func (check *Checker) addMethodDecls(obj *TypeName) {
|
|||
return
|
||||
}
|
||||
delete(check.methods, obj)
|
||||
assert(!check.objMap[obj].alias) // don't use TypeName.IsAlias (requires fully set up object)
|
||||
assert(!check.objMap[obj].tdecl.Assign.IsValid()) // don't use TypeName.IsAlias (requires fully set up object)
|
||||
|
||||
// use an objset to check for name conflicts
|
||||
var mset objset
|
||||
|
|
@ -783,7 +785,7 @@ func (check *Checker) declStmt(decl ast.Decl) {
|
|||
check.declare(check.scope, s.Name, obj, scopePos)
|
||||
// mark and unmark type before calling typeDecl; its type is still nil (see Checker.objDecl)
|
||||
obj.setColor(grey + color(check.push(obj)))
|
||||
check.typeDecl(obj, s.Type, nil, s.Assign.IsValid())
|
||||
check.typeDecl(obj, s, nil)
|
||||
check.pop().setColor(black)
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "const, type, or var declaration expected")
|
||||
|
|
|
|||
|
|
@ -62,7 +62,8 @@ func (check *Checker) infer(pos token.Pos, tparams []*TypeName, params *Tuple, a
|
|||
for i, t := range targs {
|
||||
if t == nil {
|
||||
tpar := tparams[i]
|
||||
check.errorf(pos, "cannot infer %s (%s)", tpar.name, tpar.pos)
|
||||
ppos := check.fset.Position(tpar.pos).String()
|
||||
check.errorf(pos, "cannot infer %s (%s)", tpar.name, ppos)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ import (
|
|||
type declInfo struct {
|
||||
file *Scope // scope of file containing this declaration
|
||||
lhs []*Var // lhs of n:1 variable declarations, or nil
|
||||
typ ast.Expr // type, or nil
|
||||
init ast.Expr // init/orig expression, or nil
|
||||
vtyp ast.Expr // type, or nil (for const and var declarations only)
|
||||
init ast.Expr // init/orig expression, or nil (for const and var declarations only)
|
||||
tdecl *ast.TypeSpec // type declaration, or nil
|
||||
fdecl *ast.FuncDecl // func declaration, or nil
|
||||
alias bool // type alias declaration
|
||||
|
||||
// The deps field tracks initialization expression dependencies.
|
||||
deps map[Object]bool // lazily initialized
|
||||
|
|
@ -340,7 +340,7 @@ func (check *Checker) collectObjects() {
|
|||
init = last.Values[i]
|
||||
}
|
||||
|
||||
d := &declInfo{file: fileScope, typ: last.Type, init: init}
|
||||
d := &declInfo{file: fileScope, vtyp: last.Type, init: init}
|
||||
check.declarePkgObj(name, obj, d)
|
||||
}
|
||||
|
||||
|
|
@ -357,7 +357,7 @@ func (check *Checker) collectObjects() {
|
|||
// The lhs elements are only set up after the for loop below,
|
||||
// but that's ok because declareVar only collects the declInfo
|
||||
// for a later phase.
|
||||
d1 = &declInfo{file: fileScope, lhs: lhs, typ: s.Type, init: s.Values[0]}
|
||||
d1 = &declInfo{file: fileScope, lhs: lhs, vtyp: s.Type, init: s.Values[0]}
|
||||
}
|
||||
|
||||
// declare all variables
|
||||
|
|
@ -372,7 +372,7 @@ func (check *Checker) collectObjects() {
|
|||
if i < len(s.Values) {
|
||||
init = s.Values[i]
|
||||
}
|
||||
d = &declInfo{file: fileScope, typ: s.Type, init: init}
|
||||
d = &declInfo{file: fileScope, vtyp: s.Type, init: init}
|
||||
}
|
||||
|
||||
check.declarePkgObj(name, obj, d)
|
||||
|
|
@ -386,7 +386,7 @@ func (check *Checker) collectObjects() {
|
|||
|
||||
case *ast.TypeSpec:
|
||||
obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil)
|
||||
check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, typ: s.Type, alias: s.Assign.IsValid()})
|
||||
check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, tdecl: s})
|
||||
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
|
||||
|
|
@ -521,13 +521,13 @@ func (check *Checker) resolveBaseTypeName(typ ast.Expr) (ptr bool, base *TypeNam
|
|||
|
||||
// we're done if tdecl defined tname as a new type
|
||||
// (rather than an alias)
|
||||
tdecl := check.objMap[tname] // must exist for objects in package scope
|
||||
if !tdecl.alias {
|
||||
tdecl := check.objMap[tname].tdecl // must exist for objects in package scope
|
||||
if !tdecl.Assign.IsValid() {
|
||||
return ptr, tname
|
||||
}
|
||||
|
||||
// otherwise, continue resolving
|
||||
typ = tdecl.typ
|
||||
typ = tdecl.Type
|
||||
if seen == nil {
|
||||
seen = make(map[*TypeName]bool)
|
||||
}
|
||||
|
|
@ -563,7 +563,7 @@ func (check *Checker) packageObjects() {
|
|||
// phase 1
|
||||
for _, obj := range objList {
|
||||
// If we have a type alias, collect it for the 2nd phase.
|
||||
if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].alias {
|
||||
if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].tdecl.Assign.IsValid() {
|
||||
aliasList = append(aliasList, tname)
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue