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 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
|
package p
// both
import "io"
// old
type u1 int
// both
type u2 int
// old
const C5 = 3
type (
A1 [1]int
A2 [2]int
A3 [C5]int
)
// new
// i C5: value changed from 3 to 4
const C5 = 4
type (
A1 [1]int
// i A2: changed from [2]int to [2]bool
A2 [2]bool
// i A3: changed from [3]int to [4]int
A3 [C5]int
)
// old
type (
Sl []int
P1 *int
P2 *u1
)
// new
type (
// i Sl: changed from []int to []string
Sl []string
// i P1: changed from *int to **bool
P1 **bool
P2 *u2 // OK: u1 corresponds to u2
)
// old
type Bc1 int32
type Bc2 uint
type Bc3 float32
type Bc4 complex64
// new
// c Bc1: changed from int32 to int
type Bc1 int
// c Bc2: changed from uint to uint64
type Bc2 uint64
// c Bc3: changed from float32 to float64
type Bc3 float64
// c Bc4: changed from complex64 to complex128
type Bc4 complex128
// old
type Bi1 int32
type Bi2 uint
type Bi3 float64
type Bi4 complex128
// new
// i Bi1: changed from int32 to int16
type Bi1 int16
// i Bi2: changed from uint to uint32
type Bi2 uint32
// i Bi3: changed from float64 to float32
type Bi3 float32
// i Bi4: changed from complex128 to complex64
type Bi4 complex64
// old
type (
M1 map[string]int
M2 map[string]int
M3 map[string]int
)
// new
type (
M1 map[string]int
// i M2: changed from map[string]int to map[int]int
M2 map[int]int
// i M3: changed from map[string]int to map[string]string
M3 map[string]string
)
// old
type (
Ch1 chan int
Ch2 <-chan int
Ch3 chan int
Ch4 <-chan int
)
// new
type (
// i Ch1, element type: changed from int to bool
Ch1 chan bool
// i Ch2: changed direction
Ch2 chan<- int
// i Ch3: changed direction
Ch3 <-chan int
// c Ch4: removed direction
Ch4 chan int
)
// old
type I1 interface {
M1()
M2()
}
// new
type I1 interface {
// M1()
// i I1.M1: removed
M2(int)
// i I1.M2: changed from func() to func(int)
M3()
// i I1.M3: added
m()
// i I1.m: added unexported method
}
// old
type I2 interface {
M1()
m()
}
// new
type I2 interface {
M1()
// m() Removing an unexported method is OK.
m2() // OK, because old already had an unexported method
// c I2.M2: added
M2()
}
// old
type I3 interface {
io.Reader
M()
}
// new
// OK: what matters is the method set; the name of the embedded
// interface isn't important.
type I3 interface {
M()
Read([]byte) (int, error)
}
// old
type I4 io.Writer
// new
// OK: in both, I4 is a distinct type from io.Writer, and
// the old and new I4s have the same method set.
type I4 interface {
Write([]byte) (int, error)
}
// old
type I5 = io.Writer
// new
// i I5: changed from io.Writer to I5
// In old, I5 and io.Writer are the same type; in new,
// they are different. That can break something like:
//
// var _ func(io.Writer) = func(pkg.I6) {}
type I5 io.Writer
// old
type I6 interface{ Write([]byte) (int, error) }
// new
// i I6: changed from I6 to io.Writer
// Similar to the above.
type I6 = io.Writer
//// correspondence with a basic type
// Basic types are technically defined types, but they aren't
// represented that way in go/types, so the cases below are special.
// both
type T1 int
// old
var VT1 T1
// new
// i VT1: changed from T1 to int
// This fails because old T1 corresponds to both int and new T1.
var VT1 int
// old
type t2 int
var VT2 t2
// new
// OK: t2 corresponds to int. It's fine that old t2
// doesn't exist in new.
var VT2 int
// both
type t3 int
func (t3) M() {}
// old
var VT3 t3
// new
// i t3.M: removed
// Here the change from t3 to int is incompatible
// because old t3 has an exported method.
var VT3 int
// old
var VT4 int
// new
type t4 int
// i VT4: changed from int to t4
// This is incompatible because of code like
//
// VT4 + int(1)
//
// which works in old but fails in new.
// The difference from the above cases is that
// in those, we were merging two types into one;
// here, we are splitting int into t4 and int.
var VT4 t4
|