diff --git a/src/cmd/compile/internal/types2/sanitize.go b/src/cmd/compile/internal/types2/sanitize.go index bac569416b4..cd1719c8c0f 100644 --- a/src/cmd/compile/internal/types2/sanitize.go +++ b/src/cmd/compile/internal/types2/sanitize.go @@ -1,10 +1,16 @@ -// 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) @@ -12,27 +18,42 @@ func sanitizeInfo(info *Info) { // 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) + } } } @@ -56,16 +77,22 @@ func (s sanitizer) typ(typ Type) Type { // 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) @@ -86,27 +113,39 @@ func (s sanitizer) typ(typ Type) Type { 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 @@ -114,7 +153,9 @@ func (s sanitizer) typ(typ Type) Type { 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 + } } } @@ -132,7 +173,9 @@ func (s sanitizer) tuple(t *Tuple) { 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 + } } } @@ -144,6 +187,8 @@ func (s sanitizer) funcList(list []*Func) { 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 + } } }