go/types: add primitive instantiated type map for canonicalization

Change-Id: I265105d483b6fdcee95f3770b9d6d774c1633638
This commit is contained in:
Robert Griesemer 2019-07-08 16:58:05 -07:00
parent 8142528bfd
commit a76283d6e4
4 changed files with 29 additions and 8 deletions

View File

@ -16,8 +16,9 @@ import (
// debugging/development support
const (
debug = true // leave on during development
debug = false // leave on during development
trace = false // turn on for detailed type resolution traces
halt = false // panic on error
)
// If Strict is set, the type-checker enforces additional
@ -81,6 +82,7 @@ type Checker struct {
objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info
impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
posMap map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions
typMap map[string]*TypeName // maps an instantiated type to a *Named type -- TODO(gri) this is a quick hack; fix this
pkgCnt map[string]int // counts number of imported packages with a given name (for better error messages)
// information collected during type-checking of a set of package files
@ -193,6 +195,7 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
objMap: make(map[Object]*declInfo),
impMap: make(map[importKey]*Package),
posMap: make(map[*Interface][]token.Pos),
typMap: make(map[string]*TypeName),
pkgCnt: make(map[string]int),
}
}

View File

@ -90,6 +90,10 @@ func (check *Checker) err(pos token.Pos, msg string, soft bool) {
if trace {
check.trace(pos, "ERROR: %s", msg)
}
if halt {
panic(err)
}
f := check.conf.Error
if f == nil {

View File

@ -102,12 +102,19 @@ func (s *subster) typ(typ Type) (res Type) {
if len(t.methods) > 0 {
panic("cannot handle instantiation of types with methods yet")
}
// TODO(gri) what is the correct position to use here?
obj := NewTypeName(t.obj.pos, s.check.pkg, t.obj.name+typesString(s.targs), nil)
return NewNamed(obj, underlying, nil) // TODO(gri) provide correct method list
name := t.obj.name + typesString(s.targs)
tname, found := s.check.typMap[name]
if !found {
// TODO(gri) what is the correct position to use here?
tname = NewTypeName(t.obj.pos, s.check.pkg, name, nil)
NewNamed(tname, underlying, nil) // TODO(gri) provide correct method list
s.check.typMap[name] = tname
}
return tname.typ
}
case *TypeParam:
// TODO(gri) do we need to check that we're using the correct targs list/index?
if targ := s.targs[t.index]; targ != nil {
return targ
}

View File

@ -47,11 +47,18 @@ var _ A1(float32) = x // ERROR cannot use x .* as float32
var _ T2(*int) = A2(*int){}
var _ T2(*int) = A2 /* ERROR cannot use */ (int){}
var _ T2(int) = T2(int){}
var _ List(int) = []int{1, 2, 3}
var _ List([]int) = [][]int{{1, 2, 3}}
// var _ List(List(int)) // TODO(gri) cannot not do this yet
// Parametrized types containing parametrized types
type T3(type P) = List(P)
// var _ T3(int) = List(int){1, 2, 3} // TODO(gri) cannot do this yet
// TODO(gri) cannot handle this yet due because instantiated types are not yet canonicalized
//var _ T2(int) = T2(int){}
// TODO
// think about instantiated types (they are defined types unless alias)
// need type map
// type map maps to unique name found in scopes?