-// UNREVIEWED
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package types2
+// sanitizeInfo walks the types contained in info to ensure that all instances
+// are expanded.
+//
+// This includes some objects that may be shared across concurrent
+// type-checking passes (such as those in the universe scope), so we are
+// careful here not to write types that are already sanitized. This avoids a
+// data race as any shared types should already be sanitized.
func sanitizeInfo(info *Info) {
var s sanitizer = make(map[Type]Type)
// If modified, they must be assigned back.
for e, tv := range info.Types {
- tv.Type = s.typ(tv.Type)
- info.Types[e] = tv
+ if typ := s.typ(tv.Type); typ != tv.Type {
+ tv.Type = typ
+ info.Types[e] = tv
+ }
}
for e, inf := range info.Inferred {
+ changed := false
for i, targ := range inf.Targs {
- inf.Targs[i] = s.typ(targ)
+ if typ := s.typ(targ); typ != targ {
+ inf.Targs[i] = typ
+ changed = true
+ }
+ }
+ if typ := s.typ(inf.Sig); typ != inf.Sig {
+ inf.Sig = typ.(*Signature)
+ changed = true
+ }
+ if changed {
+ info.Inferred[e] = inf
}
- inf.Sig = s.typ(inf.Sig).(*Signature)
- info.Inferred[e] = inf
}
for _, obj := range info.Defs {
if obj != nil {
- obj.setType(s.typ(obj.Type()))
+ if typ := s.typ(obj.Type()); typ != obj.Type() {
+ obj.setType(typ)
+ }
}
}
for _, obj := range info.Uses {
if obj != nil {
- obj.setType(s.typ(obj.Type()))
+ if typ := s.typ(obj.Type()); typ != obj.Type() {
+ obj.setType(typ)
+ }
}
}
// nothing to do
case *Array:
- t.elem = s.typ(t.elem)
+ if elem := s.typ(t.elem); elem != t.elem {
+ t.elem = elem
+ }
case *Slice:
- t.elem = s.typ(t.elem)
+ if elem := s.typ(t.elem); elem != t.elem {
+ t.elem = elem
+ }
case *Struct:
s.varList(t.fields)
case *Pointer:
- t.base = s.typ(t.base)
+ if base := s.typ(t.base); base != t.base {
+ t.base = base
+ }
case *Tuple:
s.tuple(t)
s.typ(t.allTypes)
case *Map:
- t.key = s.typ(t.key)
- t.elem = s.typ(t.elem)
+ if key := s.typ(t.key); key != t.key {
+ t.key = key
+ }
+ if elem := s.typ(t.elem); elem != t.elem {
+ t.elem = elem
+ }
case *Chan:
- t.elem = s.typ(t.elem)
+ if elem := s.typ(t.elem); elem != t.elem {
+ t.elem = elem
+ }
case *Named:
- t.orig = s.typ(t.orig)
- t.underlying = s.typ(t.underlying)
+ if orig := s.typ(t.orig); orig != t.orig {
+ t.orig = orig
+ }
+ if under := s.typ(t.underlying); under != t.underlying {
+ t.underlying = under
+ }
s.typeList(t.targs)
s.funcList(t.methods)
case *TypeParam:
- t.bound = s.typ(t.bound)
+ if bound := s.typ(t.bound); bound != t.bound {
+ t.bound = bound
+ }
case *instance:
typ = t.expand()
s[t] = typ
default:
- unimplemented()
+ panic("unimplemented")
}
return typ
func (s sanitizer) var_(v *Var) {
if v != nil {
- v.typ = s.typ(v.typ)
+ if typ := s.typ(v.typ); typ != v.typ {
+ v.typ = typ
+ }
}
}
func (s sanitizer) func_(f *Func) {
if f != nil {
- f.typ = s.typ(f.typ)
+ if typ := s.typ(f.typ); typ != f.typ {
+ f.typ = typ
+ }
}
}
func (s sanitizer) typeList(list []Type) {
for i, t := range list {
- list[i] = s.typ(t)
+ if typ := s.typ(t); typ != t {
+ list[i] = typ
+ }
}
}