| // run |
| |
| // Copyright 2022 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 main |
| |
| import "fmt" |
| |
| type I interface { |
| M() |
| } |
| |
| type S struct { |
| str string |
| } |
| |
| func (s *S) M() {} |
| |
| var _ I = &S{} |
| |
| type CloningMap[K comparable, V any] struct { |
| inner map[K]V |
| } |
| |
| func (cm CloningMap[K, V]) With(key K, value V) CloningMap[K, V] { |
| result := CloneBad(cm.inner) |
| result[key] = value |
| return CloningMap[K, V]{result} |
| } |
| |
| func CloneBad[M ~map[K]V, K comparable, V any](m M) M { |
| r := make(M, len(m)) |
| for k, v := range m { |
| r[k] = v |
| } |
| return r |
| } |
| |
| func main() { |
| s1 := &S{"one"} |
| s2 := &S{"two"} |
| |
| m := CloningMap[string, I]{inner: make(map[string]I)} |
| m = m.With("a", s1) |
| m = m.With("b", s2) |
| |
| it, found := m.inner["a"] |
| if !found { |
| panic("a not found") |
| } |
| if _, ok := it.(*S); !ok { |
| panic(fmt.Sprintf("got %T want *main.S", it)) |
| } |
| } |