blob: dca94d03e616ddc0fde9926e823f62f0efec6815 [file] [log] [blame]
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