@@ -38,6 +38,9 @@ type typeParamParentEntry struct {
3838 isFromReceiver bool
3939}
4040
41+ // typeParamMutex protects typeParamParent and typeParamOrigin.
42+ var typeParamMutex sync.RWMutex
43+
4144var typeParamParent map [* types.TypeParam ]typeParamParentEntry = make (map [* types.TypeParam ]typeParamParentEntry )
4245
4346var typeParamOrigin map [* types.TypeParam ]* types.TypeParam = make (map [* types.TypeParam ]* types.TypeParam )
@@ -2043,7 +2046,10 @@ func getObjectBeingUsed(tw *trap.Writer, ident *ast.Ident) types.Object {
20432046}
20442047
20452048func getTypeParamParentLabel (tw * trap.Writer , tp * types.TypeParam ) (trap.Label , bool ) {
2049+ typeParamMutex .RLock ()
20462050 entry , exists := typeParamParent [tp ]
2051+ typeParamMutex .RUnlock ()
2052+
20472053 if ! exists {
20482054 log .Fatalf ("Parent of type parameter does not exist: %s %s" , tp .String (), tp .Constraint ().String ())
20492055 }
@@ -2055,6 +2061,13 @@ func getTypeParamParentLabel(tw *trap.Writer, tp *types.TypeParam) (trap.Label,
20552061}
20562062
20572063func setTypeParamParent (tp * types.TypeParam , parent types.Object , isFromReceiver bool ) {
2064+ typeParamMutex .Lock ()
2065+ defer typeParamMutex .Unlock ()
2066+ setTypeParamParentLocked (tp , parent , isFromReceiver )
2067+ }
2068+
2069+ // setTypeParamParentLocked requires typeParamMutex to be held for writing.
2070+ func setTypeParamParentLocked (tp * types.TypeParam , parent types.Object , isFromReceiver bool ) {
20582071 entry , exists := typeParamParent [tp ]
20592072 newEntry := typeParamParentEntry {parent , isFromReceiver }
20602073 if ! exists {
@@ -2106,9 +2119,12 @@ func checkObjectNotSpecialized(obj types.Object) {
21062119// getTypeParamOrigin returns the origin type parameter for a type parameter
21072120// from an instantiated method.
21082121func getTypeParamOrigin (tp * types.TypeParam ) * types.TypeParam {
2122+ typeParamMutex .RLock ()
21092123 if origin , exists := typeParamOrigin [tp ]; exists {
2124+ typeParamMutex .RUnlock ()
21102125 return origin
21112126 }
2127+ typeParamMutex .RUnlock ()
21122128 return tp
21132129}
21142130
@@ -2144,12 +2160,29 @@ func populateTypeParamParentAndOrigin(tp *types.Named, i int, meth *types.Func)
21442160 originParams := meth .Type ().(* types.Signature ).TypeParams ()
21452161
21462162 if instantiatedParams .Len () != originParams .Len () {
2147- log .Fatalf ("Method instantiation %s has %d type parameters, origin has %d" , tp .Method (i ), instantiatedParams .Len (), originParams .Len ())
2163+ log .Fatalf ("Method instantiation %s has %d type parameters, origin has %d" ,
2164+ tp .Method (i ), instantiatedParams .Len (), originParams .Len ())
21482165 }
21492166
21502167 for j := 0 ; j < instantiatedParams .Len (); j ++ {
2151- instantiatedParam := instantiatedParams .At (j )
2152- setTypeParamParent (instantiatedParam , meth , false )
2153- typeParamOrigin [instantiatedParam ] = originParams .At (j )
2168+ setTypeParamParentAndOrigin (instantiatedParams .At (j ), meth , originParams .At (j ))
21542169 }
21552170}
2171+
2172+ // setTypeParamParentAndOrigin atomically records the parent and origin of an
2173+ // instantiated method type parameter.
2174+ func setTypeParamParentAndOrigin (instantiatedParam * types.TypeParam , parent * types.Func , originParam * types.TypeParam ) {
2175+ typeParamMutex .Lock ()
2176+ defer typeParamMutex .Unlock ()
2177+
2178+ setTypeParamParentLocked (instantiatedParam , parent , false )
2179+
2180+ if existing , exists := typeParamOrigin [instantiatedParam ]; exists {
2181+ if existing != originParam {
2182+ log .Fatalf ("Origin of type parameter '%s %s' being set to a different value: '%s' vs '%s'" ,
2183+ instantiatedParam .String (), instantiatedParam .Constraint ().String (), existing .String (), originParam .String ())
2184+ }
2185+ }
2186+
2187+ typeParamOrigin [instantiatedParam ] = originParam
2188+ }
0 commit comments