tailscale/cmd/cloner/clonerex/clonerex_clone.go
Andrew Dunham d52ae45e9b cmd/cloner: deep-clone pointer elements in map-of-slice values
The cloner's codegen for map[K][]*V fields was doing a shallow
append (copying pointer values) instead of cloning each element.
This meant that cloned structs aliased the original's pointed-to
values through the map's slice entries.

Mirror the existing standalone-slice logic that checks
ContainsPointers(sliceType.Elem()) and generates per-element
cloning for pointer, interface, and struct types.

Regenerate net/dns and tailcfg which both had affected
map[...][]*dnstype.Resolver fields.

Fixes #19284

Signed-off-by: Andrew Dunham <andrew@tailscale.com>
2026-04-17 11:36:05 -04:00

273 lines
6.8 KiB
Go

// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by tailscale.com/cmd/cloner; DO NOT EDIT.
package clonerex
import (
"maps"
)
// Clone makes a deep copy of SliceContainer.
// The result aliases no memory with the original.
func (src *SliceContainer) Clone() *SliceContainer {
if src == nil {
return nil
}
dst := new(SliceContainer)
*dst = *src
if src.Slice != nil {
dst.Slice = make([]*int, len(src.Slice))
for i := range dst.Slice {
if src.Slice[i] == nil {
dst.Slice[i] = nil
} else {
dst.Slice[i] = new(*src.Slice[i])
}
}
}
return dst
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _SliceContainerCloneNeedsRegeneration = SliceContainer(struct {
Slice []*int
}{})
// Clone makes a deep copy of InterfaceContainer.
// The result aliases no memory with the original.
func (src *InterfaceContainer) Clone() *InterfaceContainer {
if src == nil {
return nil
}
dst := new(InterfaceContainer)
*dst = *src
if src.Interface != nil {
dst.Interface = src.Interface.Clone()
}
return dst
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _InterfaceContainerCloneNeedsRegeneration = InterfaceContainer(struct {
Interface Cloneable
}{})
// Clone makes a deep copy of MapWithPointers.
// The result aliases no memory with the original.
func (src *MapWithPointers) Clone() *MapWithPointers {
if src == nil {
return nil
}
dst := new(MapWithPointers)
*dst = *src
if dst.Nested != nil {
dst.Nested = map[string]*int{}
for k, v := range src.Nested {
if v == nil {
dst.Nested[k] = nil
} else {
dst.Nested[k] = new(*v)
}
}
}
if dst.WithCloneMethod != nil {
dst.WithCloneMethod = map[string]*SliceContainer{}
for k, v := range src.WithCloneMethod {
if v == nil {
dst.WithCloneMethod[k] = nil
} else {
dst.WithCloneMethod[k] = v.Clone()
}
}
}
if dst.CloneInterface != nil {
dst.CloneInterface = map[string]Cloneable{}
for k, v := range src.CloneInterface {
dst.CloneInterface[k] = v.Clone()
}
}
return dst
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _MapWithPointersCloneNeedsRegeneration = MapWithPointers(struct {
Nested map[string]*int
WithCloneMethod map[string]*SliceContainer
CloneInterface map[string]Cloneable
}{})
// Clone makes a deep copy of DeeplyNestedMap.
// The result aliases no memory with the original.
func (src *DeeplyNestedMap) Clone() *DeeplyNestedMap {
if src == nil {
return nil
}
dst := new(DeeplyNestedMap)
*dst = *src
if dst.ThreeLevels != nil {
dst.ThreeLevels = map[string]map[string]map[string]int{}
for k, v := range src.ThreeLevels {
if v == nil {
dst.ThreeLevels[k] = nil
continue
}
dst.ThreeLevels[k] = map[string]map[string]int{}
for k2, v2 := range v {
dst.ThreeLevels[k][k2] = maps.Clone(v2)
}
}
}
if dst.FourLevels != nil {
dst.FourLevels = map[string]map[string]map[string]map[string]*SliceContainer{}
for k, v := range src.FourLevels {
if v == nil {
dst.FourLevels[k] = nil
continue
}
dst.FourLevels[k] = map[string]map[string]map[string]*SliceContainer{}
for k2, v2 := range v {
if v2 == nil {
dst.FourLevels[k][k2] = nil
continue
}
dst.FourLevels[k][k2] = map[string]map[string]*SliceContainer{}
for k3, v3 := range v2 {
if v3 == nil {
dst.FourLevels[k][k2][k3] = nil
continue
}
dst.FourLevels[k][k2][k3] = map[string]*SliceContainer{}
for k4, v4 := range v3 {
if v4 == nil {
dst.FourLevels[k][k2][k3][k4] = nil
} else {
dst.FourLevels[k][k2][k3][k4] = v4.Clone()
}
}
}
}
}
}
return dst
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _DeeplyNestedMapCloneNeedsRegeneration = DeeplyNestedMap(struct {
ThreeLevels map[string]map[string]map[string]int
FourLevels map[string]map[string]map[string]map[string]*SliceContainer
}{})
// Clone makes a deep copy of NamedMapContainer.
// The result aliases no memory with the original.
func (src *NamedMapContainer) Clone() *NamedMapContainer {
if src == nil {
return nil
}
dst := new(NamedMapContainer)
*dst = *src
dst.Attrs = src.Attrs.Clone()
return dst
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _NamedMapContainerCloneNeedsRegeneration = NamedMapContainer(struct {
Attrs NamedMap
}{})
// Clone makes a deep copy of MapSlicePointerContainer.
// The result aliases no memory with the original.
func (src *MapSlicePointerContainer) Clone() *MapSlicePointerContainer {
if src == nil {
return nil
}
dst := new(MapSlicePointerContainer)
*dst = *src
if dst.Routes != nil {
dst.Routes = map[string][]*SliceContainer{}
for k, sv := range src.Routes {
if sv == nil {
continue
}
dst.Routes[k] = make([]*SliceContainer, len(sv))
for i := range sv {
if sv[i] == nil {
dst.Routes[k][i] = nil
} else {
dst.Routes[k][i] = sv[i].Clone()
}
}
}
}
return dst
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _MapSlicePointerContainerCloneNeedsRegeneration = MapSlicePointerContainer(struct {
Routes map[string][]*SliceContainer
}{})
// Clone duplicates src into dst and reports whether it succeeded.
// To succeed, <src, dst> must be of types <*T, *T> or <*T, **T>,
// where T is one of SliceContainer,InterfaceContainer,MapWithPointers,DeeplyNestedMap,NamedMapContainer,MapSlicePointerContainer.
func Clone(dst, src any) bool {
switch src := src.(type) {
case *SliceContainer:
switch dst := dst.(type) {
case *SliceContainer:
*dst = *src.Clone()
return true
case **SliceContainer:
*dst = src.Clone()
return true
}
case *InterfaceContainer:
switch dst := dst.(type) {
case *InterfaceContainer:
*dst = *src.Clone()
return true
case **InterfaceContainer:
*dst = src.Clone()
return true
}
case *MapWithPointers:
switch dst := dst.(type) {
case *MapWithPointers:
*dst = *src.Clone()
return true
case **MapWithPointers:
*dst = src.Clone()
return true
}
case *DeeplyNestedMap:
switch dst := dst.(type) {
case *DeeplyNestedMap:
*dst = *src.Clone()
return true
case **DeeplyNestedMap:
*dst = src.Clone()
return true
}
case *NamedMapContainer:
switch dst := dst.(type) {
case *NamedMapContainer:
*dst = *src.Clone()
return true
case **NamedMapContainer:
*dst = src.Clone()
return true
}
case *MapSlicePointerContainer:
switch dst := dst.(type) {
case *MapSlicePointerContainer:
*dst = *src.Clone()
return true
case **MapSlicePointerContainer:
*dst = src.Clone()
return true
}
}
return false
}