// Instances can have a nil underlying at the end of type checking — they
// will lazily expand it as needed. All other types must have one.
if n.inst == nil {
- n.resolve().under()
+ n.Underlying()
}
n.check = nil
}
}
}
- return n.under()
+ n.resolveUnderlying()
+ return n.underlying
}
func (t *Named) String() string { return TypeString(t, nil) }
// TODO(rfindley): reorganize the loading and expansion methods under this
// heading.
-// under returns the (possibly expanded) underlying type of n.
+// resolveUnderlying computes the underlying type of n.
//
// It does so by following RHS type chains. If a type literal is found, each
// named type in the chain has its underlying set to that type. Aliases are
//
// This function also checks for instantiated layout cycles, which are
// reachable only in the case where resolve() expanded an instantiated
-// type which became self-referencing without indirection. If such a
-// cycle is found, the result is Typ[Invalid]; if n.check != nil, the
-// cycle is also reported.
-func (n *Named) under() Type {
+// type which became self-referencing without indirection.
+// If such a cycle is found, the underlying type is set to Typ[Invalid]
+// and a cycle is reported.
+func (n *Named) resolveUnderlying() {
assert(n.stateHas(resolved))
// optimization for likely case
if n.stateHas(underlying) {
- return n.underlying
+ return
}
- var rhs Type = n
- var u Type
-
seen := make(map[*Named]int)
var path []Object
- for u == nil {
+ var u Type
+ for rhs := Type(n); u == nil; {
switch t := rhs.(type) {
case nil:
u = Typ[Invalid]
case *Named:
if i, ok := seen[t]; ok {
+ // Note: This code may only be called during type checking,
+ // hence n.check != nil.
n.check.cycleError(path[i:], firstInSrc(path[i:]))
u = Typ[Invalid]
break
}
}
- // go back up the chain
+ // set underlying for all Named types in the chain
for t := range seen {
t.underlying = u
t.setState(underlying)
}
-
- return u
}
func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
// Instances can have a nil underlying at the end of type checking — they
// will lazily expand it as needed. All other types must have one.
if n.inst == nil {
- n.resolve().under()
+ n.Underlying()
}
n.check = nil
}
}
}
- return n.under()
+ n.resolveUnderlying()
+ return n.underlying
}
func (t *Named) String() string { return TypeString(t, nil) }
// TODO(rfindley): reorganize the loading and expansion methods under this
// heading.
-// under returns the (possibly expanded) underlying type of n.
+// resolveUnderlying computes the underlying type of n.
//
// It does so by following RHS type chains. If a type literal is found, each
// named type in the chain has its underlying set to that type. Aliases are
//
// This function also checks for instantiated layout cycles, which are
// reachable only in the case where resolve() expanded an instantiated
-// type which became self-referencing without indirection. If such a
-// cycle is found, the result is Typ[Invalid]; if n.check != nil, the
-// cycle is also reported.
-func (n *Named) under() Type {
+// type which became self-referencing without indirection.
+// If such a cycle is found, the underlying type is set to Typ[Invalid]
+// and a cycle is reported.
+func (n *Named) resolveUnderlying() {
assert(n.stateHas(resolved))
// optimization for likely case
if n.stateHas(underlying) {
- return n.underlying
+ return
}
- var rhs Type = n
- var u Type
-
seen := make(map[*Named]int)
var path []Object
- for u == nil {
+ var u Type
+ for rhs := Type(n); u == nil; {
switch t := rhs.(type) {
case nil:
u = Typ[Invalid]
case *Named:
if i, ok := seen[t]; ok {
+ // Note: This code may only be called during type checking,
+ // hence n.check != nil.
n.check.cycleError(path[i:], firstInSrc(path[i:]))
u = Typ[Invalid]
break
}
}
- // go back up the chain
+ // set underlying for all Named types in the chain
for t := range seen {
t.underlying = u
t.setState(underlying)
}
-
- return u
}
func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {