Value constant.Value
}
-// TODO(gri) Consider eliminating the IsVoid predicate. Instead, report
-// "void" values as regular values but with the empty tuple type.
-
// IsVoid reports whether the corresponding expression
// is a function call without results.
func (tv TypeAndValue) IsVoid() bool {
// order code.
switch obj := obj.(type) {
case *Const:
- if check.typeCycle(obj) || obj.typ == nil {
+ if check.cycle(obj) || obj.typ == nil {
obj.typ = Typ[Invalid]
}
case *Var:
- if check.typeCycle(obj) || obj.typ == nil {
+ if check.cycle(obj) || obj.typ == nil {
obj.typ = Typ[Invalid]
}
case *TypeName:
- if check.typeCycle(obj) {
+ if check.cycle(obj) {
// break cycle
// (without this, calling underlying()
// below may lead to an endless loop
}
case *Func:
- if check.typeCycle(obj) {
+ if check.cycle(obj) {
// Don't set obj.typ to Typ[Invalid] here
// because plenty of code type-asserts that
// functions have a *Signature type. Grey
}
}
-// typeCycle checks if the cycle starting with obj is valid and
+// cycle checks if the cycle starting with obj is valid and
// reports an error if it is not.
-// TODO(gri) rename s/typeCycle/cycle/ once we don't need the other
-// cycle method anymore.
-func (check *Checker) typeCycle(obj Object) (isCycle bool) {
+func (check *Checker) cycle(obj Object) (isCycle bool) {
// The object map contains the package scope objects and the non-interface methods.
if debug {
info := check.objMap[obj]
// non-alias type name. If we encounter anything but pointer types or
// parentheses we're done. If we encounter more than one pointer type
// we're done.
- var path []*TypeName
+ var seen map[*TypeName]bool
for {
typ = unparen(typ)
typ = unparen(pexpr.X) // continue with pointer base type
}
- // typ must be the name
+ // typ must be a name
name, _ := typ.(*ast.Ident)
if name == nil {
return false, nil
}
// ... which we have not seen before
- if check.cycle(tname, path, false) {
+ if seen[tname] {
return false, nil
}
// otherwise, continue resolving
typ = tdecl.typ
- path = append(path, tname)
- }
-}
-
-// cycle reports whether obj appears in path or not.
-// If it does, and report is set, it also reports a cycle error.
-func (check *Checker) cycle(obj *TypeName, path []*TypeName, report bool) bool {
- // (it's ok to iterate forward because each named type appears at most once in path)
- for i, prev := range path {
- if prev == obj {
- if report {
- check.errorf(obj.pos, "illegal cycle in declaration of %s", obj.name)
- // print cycle
- for _, obj := range path[i:] {
- check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
- }
- check.errorf(obj.Pos(), "\t%s", obj.Name())
- }
- return true
+ if seen == nil {
+ seen = make(map[*TypeName]bool)
}
+ seen[tname] = true
}
- return false
}
// packageObjects typechecks all package objects, but not function bodies.