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
/
append3.go2
145 lines (119 loc) · 4.73 KB
/
append3.go2
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
134
135
136
137
138
139
140
141
142
143
144
145
// 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.
// 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"
"unsafe"
)
type sliceOf(type E) interface{ type []E }
// buggyAssignableTo simulates an “assignable to” type constraint using
// the closest available alternative (a 1-element type list, which works
// for a few defined types but not channel-directons or subinterfaces).
type buggyAssignableTo(type T) interface {
type T
}
func append(type S sliceOf(T), T interface{}, T2 buggyAssignableTo(T))(s S, t ...T2) S {
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 {
// This is why buggyAssignableTo is buggy. 🙂
p := unsafe.Pointer(&x)
s[lens+i] = *(*T)(p)
}
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() {
// cannot infer T (http://b/159049873)
ff := append([]func(), func(), func())(funcSlice, f)
fmt.Printf("append(%T, %T) = %T\n", funcSlice, f, ff)
// cannot infer T (http://b/159049873)
Ff := append(Funcs, func(), func())(funcs, f)
fmt.Printf("append(%T, %T) = %T\n", funcs, f, Ff)
// cannot infer T
fc := append([]func(), func(), context.CancelFunc)(funcSlice, cancel)
fmt.Printf("append(%T, %T) = %T\n", funcSlice, cancel, fc)
// cannot infer T
cf := append([]context.CancelFunc, context.CancelFunc, func())(cancelSlice, f)
fmt.Printf("append(%T, %T) = %T\n", cancelSlice, f, cf)
// cannot infer T
Fc := append(Funcs, func(), context.CancelFunc)(funcs, cancel)
fmt.Printf("append(%T, %T) = %T\n", funcs, cancel, Fc)
// cannot infer T
Cc := append(Cancels, context.CancelFunc, func())(cancels, f)
fmt.Printf("append(%T, %T) = %T\n", cancels, f, Cc)
// cannot infer T
ffc := append([]func(), func(), context.CancelFunc)(funcSlice, f, cancel)
fmt.Printf("append(%T, %T, %T) = %T\n", funcSlice, f, cancel, ffc)
// cannot infer T (http://b/159049873)
ff2 := append([]func(), func(), func())(funcSlice, funcSlice...)
fmt.Printf("append(%T, %T...) = %T\n", funcSlice, funcSlice, ff2)
// cannot infer T (http://b/159049873)
FF2 := append(Funcs, func(), func())(funcs, funcs...)
fmt.Printf("append(%T, %T...) = %T\n", funcs, funcs, FF2)
// cannot infer T (http://b/159049873)
Ff2 := append(Funcs, func(), func())(funcs, funcSlice...)
fmt.Printf("append(%T, %T...) = %T\n", funcs, funcSlice, Ff2)
// cannot infer T (http://b/159049873)
fc2 := append([]func(), func(), context.CancelFunc)(funcSlice, cancelSlice...)
fmt.Printf("append(%T, %T...) = %T\n", funcSlice, cancelSlice, fc2)
// cannot infer T
FC2 := append(Funcs, func(), context.CancelFunc)(funcs, cancels...)
fmt.Printf("append(%T, %T...) = %T\n", funcs, cancels, FC2)
// cannot infer T (http://b/159049873)
rr := append([]<-chan int, <-chan int, <-chan int)(recvSlice, r)
fmt.Printf("append(%T, %T) = %T\n", recvSlice, r, rr)
// cannot infer T
// chan int does not satisfy interface{type T} (chan int not found in <-chan int)
rb := append([]<-chan int, <-chan int, <-chan int)(recvSlice, b)
fmt.Printf("append(%T, %T) = %T\n", recvSlice, b, rb)
// cannot infer T (http://b/159049873)
RR := append([]Recv, Recv, Recv)(RecvSlice, R)
fmt.Printf("append(%T, %T) = %T\n", RecvSlice, R, RR)
// cannot infer T (http://b/159049873)
// Recv does not satisfy interface{type T} (<-chan int not found in Recv)
Rb := append([]Recv, Recv, Recv)(RecvSlice, b)
fmt.Printf("append(%T, %T) = %T\n", RecvSlice, b, Rb)
// cannot infer T
rrb := append([]<-chan int, <-chan int, <-chan int)(recvSlice, r, b)
fmt.Printf("append(%T, %T) = %T\n", recvSlice, b, rrb)
// cannot infer T (http://b/159049873)
rr2 := append([]<-chan int, <-chan int, <-chan int)(recvSlice, recvSlice...)
fmt.Printf("append(%T, %T...) = %T\n", recvSlice, recvSlice, rr2)
// cannot infer T (http://b/159049873)
// chan int does not satisfy interface{type T} (chan int not found in <-chan int)
// rb2 := append([]<-chan int, <-chan int, chan int)(recvSlice, bidiSlice...)
// fmt.Printf("append(%T, %T...) = %T\n", recvSlice, bidiSlice, rb2)
}