// If this PointsToSet came from a Pointer of interface kind // or a reflect.Value, DynamicTypes returns the set of dynamic // types that it may contain. (For an interface, they will // always be concrete types.) // // The result is a mapping whose keys are the dynamic types to // which it may point. For each pointer-like key type, the // corresponding map value is a set of pointer abstractions of // that dynamic type, represented as a []Pointer slice. Use // PointsToCombined to merge them. // // The result is empty unless CanHaveDynamicTypes(T). // func (s PointsToSet) DynamicTypes() *typemap.M { var tmap typemap.M tmap.SetHasher(s.a.hasher) for ifaceObjId := range s.pts { if !s.a.isTaggedObject(ifaceObjId) { continue // !CanHaveDynamicTypes(tDyn) } tDyn, v, indirect := s.a.taggedValue(ifaceObjId) if indirect { panic("indirect tagged object") // implement later } prev, _ := tmap.At(tDyn).([]Pointer) tmap.Set(tDyn, append(prev, Pointer{s.a, nil, v})) } return &tmap }