This repository has been archived by the owner on Mar 14, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathappend3.go
133 lines (104 loc) · 3.59 KB
/
append3.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// 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.
//go:build ignore
// append3 illustrates the properties of a 3-type-parameter "append" variant.
//
// With a more advanced type-inference algorithm and a proper "assignable to"
// constraint, it could support inference for all of the same cases as the
// built-in "append" does today, plus a few others.
package main
import (
"context"
"fmt"
"reflect"
)
type sliceOf[E any] interface{ ~[]E }
// buggyAssignableTo simulates an “assignable to” type constraint using
// something a little too permissive ("any").
// We confirm assignability at run-time using the reflect package.
type buggyAssignableTo[T any] interface { any }
func append[T any, T2 buggyAssignableTo[T], S sliceOf[T]](s S, t ...T2) S {
// Confirm that T2 is assignable to T.
// Ideally this should happen in the type system instead of at run-time.
rt := reflect.TypeOf(s).Elem()
rt2 := reflect.TypeOf(t).Elem()
if !rt2.AssignableTo(rt) {
panic("append: T2 is not assignable to T")
}
lens := len(s)
tot := lens + len(t)
if tot < 0 {
panic("append: cap out of range")
}
if tot > cap(s) {
news := make([]T, tot, tot+tot/2)
copy(news, s)
s = news
}
s = s[:tot]
for i, x := range t {
// We need to bounce through reflect because buggyAssignableTo doesn't
// actually enable assignment.
xt := reflect.ValueOf(x).Convert(rt).Interface().(T)
s[lens+i] = xt
}
return s
}
type Funcs []func()
type Cancels []context.CancelFunc
type Recv <-chan int
var (
f func()
cancel context.CancelFunc
funcSlice []func()
cancelSlice []context.CancelFunc
funcs Funcs
cancels Cancels
r <-chan int
recvSlice []<-chan int
R Recv
RecvSlice []Recv
b chan int
bidiSlice []chan int
)
func main() {
ff := append(funcSlice, f)
fmt.Printf("append(%T, %T) = %T\n", funcSlice, f, ff)
Ff := append(funcs, f)
fmt.Printf("append(%T, %T) = %T\n", funcs, f, Ff)
fc := append(funcSlice, cancel)
fmt.Printf("append(%T, %T) = %T\n", funcSlice, cancel, fc)
cf := append(cancelSlice, f)
fmt.Printf("append(%T, %T) = %T\n", cancelSlice, f, cf)
Fc := append(funcs, cancel)
fmt.Printf("append(%T, %T) = %T\n", funcs, cancel, Fc)
Cc := append(cancels, f)
fmt.Printf("append(%T, %T) = %T\n", cancels, f, Cc)
ffc := append(funcSlice, f, cancel)
fmt.Printf("append(%T, %T, %T) = %T\n", funcSlice, f, cancel, ffc)
ff2 := append(funcSlice, funcSlice...)
fmt.Printf("append(%T, %T...) = %T\n", funcSlice, funcSlice, ff2)
FF2 := append(funcs, funcs...)
fmt.Printf("append(%T, %T...) = %T\n", funcs, funcs, FF2)
Ff2 := append(funcs, funcSlice...)
fmt.Printf("append(%T, %T...) = %T\n", funcs, funcSlice, Ff2)
fc2 := append(funcSlice, cancelSlice...)
fmt.Printf("append(%T, %T...) = %T\n", funcSlice, cancelSlice, fc2)
FC2 := append(funcs, cancels...)
fmt.Printf("append(%T, %T...) = %T\n", funcs, cancels, FC2)
rr := append(recvSlice, r)
fmt.Printf("append(%T, %T) = %T\n", recvSlice, r, rr)
rb := append(recvSlice, b)
fmt.Printf("append(%T, %T) = %T\n", recvSlice, b, rb)
RR := append(RecvSlice, R)
fmt.Printf("append(%T, %T) = %T\n", RecvSlice, R, RR)
Rb := append(RecvSlice, b)
fmt.Printf("append(%T, %T) = %T\n", RecvSlice, b, Rb)
rrb := append(recvSlice, r, b)
fmt.Printf("append(%T, %T) = %T\n", recvSlice, b, rrb)
rr2 := append(recvSlice, recvSlice...)
fmt.Printf("append(%T, %T...) = %T\n", recvSlice, recvSlice, rr2)
rb2 := append(recvSlice, bidiSlice...)
fmt.Printf("append(%T, %T...) = %T\n", recvSlice, bidiSlice, rb2)
}