github.com/v2fly/tools@v0.100.0/internal/apidiff/testdata/tests.go (about)

     1  // This file is split into two packages, old and new.
     2  // It is syntactically valid Go so that gofmt can process it.
     3  //
     4  // If a comment begins with:   Then:
     5  //  old                        write subsequent lines to the "old" package
     6  //  new                        write subsequent lines to the "new" package
     7  //  both                       write subsequent lines to both packages
     8  //  c                          expect a compatible error with the following text
     9  //  i                          expect an incompatible error with the following text
    10  package ignore
    11  
    12  // both
    13  import "io"
    14  
    15  //////////////// Basics
    16  
    17  //// Same type in both: OK.
    18  // both
    19  type A int
    20  
    21  //// Changing the type is an incompatible change.
    22  // old
    23  type B int
    24  
    25  // new
    26  // i B: changed from int to string
    27  type B string
    28  
    29  //// Adding a new type, whether alias or not, is a compatible change.
    30  // new
    31  // c AA: added
    32  type AA = A
    33  
    34  // c B1: added
    35  type B1 bool
    36  
    37  //// Change of type for an unexported name doesn't matter...
    38  // old
    39  type t int
    40  
    41  // new
    42  type t string // OK: t isn't part of the API
    43  
    44  //// ...unless it is exposed.
    45  // both
    46  var V2 u
    47  
    48  // old
    49  type u string
    50  
    51  // new
    52  // i u: changed from string to int
    53  type u int
    54  
    55  //// An exposed, unexported type can be renamed.
    56  // both
    57  type u2 int
    58  
    59  // old
    60  type u1 int
    61  
    62  var V5 u1
    63  
    64  // new
    65  var V5 u2 // OK: V5 has changed type, but old u1 corresopnds to new u2
    66  
    67  //// Splitting a single type into two is an incompatible change.
    68  // both
    69  type u3 int
    70  
    71  // old
    72  type (
    73  	Split1 = u1
    74  	Split2 = u1
    75  )
    76  
    77  // new
    78  type (
    79  	Split1 = u2 // OK, since old u1 corresponds to new u2
    80  
    81  	// This tries to make u1 correspond to u3
    82  	// i Split2: changed from u1 to u3
    83  	Split2 = u3
    84  )
    85  
    86  //// Merging two types into one is OK.
    87  // old
    88  type (
    89  	GoodMerge1 = u2
    90  	GoodMerge2 = u3
    91  )
    92  
    93  // new
    94  type (
    95  	GoodMerge1 = u3
    96  	GoodMerge2 = u3
    97  )
    98  
    99  //// Merging isn't OK here because a method is lost.
   100  // both
   101  type u4 int
   102  
   103  func (u4) M() {}
   104  
   105  // old
   106  type (
   107  	BadMerge1 = u3
   108  	BadMerge2 = u4
   109  )
   110  
   111  // new
   112  type (
   113  	BadMerge1 = u3
   114  	// i u4.M: removed
   115  	// What's really happening here is that old u4 corresponds to new u3,
   116  	// and new u3's method set is not a superset of old u4's.
   117  	BadMerge2 = u3
   118  )
   119  
   120  // old
   121  type Rem int
   122  
   123  // new
   124  // i Rem: removed
   125  
   126  //////////////// Constants
   127  
   128  //// type changes
   129  // old
   130  const (
   131  	C1     = 1
   132  	C2 int = 2
   133  	C3     = 3
   134  	C4 u1  = 4
   135  )
   136  
   137  var V8 int
   138  
   139  // new
   140  const (
   141  	// i C1: changed from untyped int to untyped string
   142  	C1 = "1"
   143  	// i C2: changed from int to untyped int
   144  	C2 = -1
   145  	// i C3: changed from untyped int to int
   146  	C3 int = 3
   147  	// i V8: changed from var to const
   148  	V8 int = 1
   149  	C4 u2  = 4 // OK: u1 corresponds to u2
   150  )
   151  
   152  // value change
   153  // old
   154  const (
   155  	Cr1 = 1
   156  	Cr2 = "2"
   157  	Cr3 = 3.5
   158  	Cr4 = complex(0, 4.1)
   159  )
   160  
   161  // new
   162  const (
   163  	// i Cr1: value changed from 1 to -1
   164  	Cr1 = -1
   165  	// i Cr2: value changed from "2" to "3"
   166  	Cr2 = "3"
   167  	// i Cr3: value changed from 3.5 to 3.8
   168  	Cr3 = 3.8
   169  	// i Cr4: value changed from (0 + 4.1i) to (4.1 + 0i)
   170  	Cr4 = complex(4.1, 0)
   171  )
   172  
   173  //////////////// Variables
   174  
   175  //// simple type changes
   176  // old
   177  var (
   178  	V1 string
   179  	V3 A
   180  	V7 <-chan int
   181  )
   182  
   183  // new
   184  var (
   185  	// i V1: changed from string to []string
   186  	V1 []string
   187  	V3 A // OK: same
   188  	// i V7: changed from <-chan int to chan int
   189  	V7 chan int
   190  )
   191  
   192  //// interface type  changes
   193  // old
   194  var (
   195  	V9  interface{ M() }
   196  	V10 interface{ M() }
   197  	V11 interface{ M() }
   198  )
   199  
   200  // new
   201  var (
   202  	// i V9: changed from interface{M()} to interface{}
   203  	V9 interface{}
   204  	// i V10: changed from interface{M()} to interface{M(); M2()}
   205  	V10 interface {
   206  		M2()
   207  		M()
   208  	}
   209  	// i V11: changed from interface{M()} to interface{M(int)}
   210  	V11 interface{ M(int) }
   211  )
   212  
   213  //// struct type changes
   214  // old
   215  var (
   216  	VS1 struct{ A, B int }
   217  	VS2 struct{ A, B int }
   218  	VS3 struct{ A, B int }
   219  	VS4 struct {
   220  		A int
   221  		u1
   222  	}
   223  )
   224  
   225  // new
   226  var (
   227  	// i VS1: changed from struct{A int; B int} to struct{B int; A int}
   228  	VS1 struct{ B, A int }
   229  	// i VS2: changed from struct{A int; B int} to struct{A int}
   230  	VS2 struct{ A int }
   231  	// i VS3: changed from struct{A int; B int} to struct{A int; B int; C int}
   232  	VS3 struct{ A, B, C int }
   233  	VS4 struct {
   234  		A int
   235  		u2
   236  	}
   237  )
   238  
   239  //////////////// Types
   240  
   241  // old
   242  const C5 = 3
   243  
   244  type (
   245  	A1 [1]int
   246  	A2 [2]int
   247  	A3 [C5]int
   248  )
   249  
   250  // new
   251  // i C5: value changed from 3 to 4
   252  const C5 = 4
   253  
   254  type (
   255  	A1 [1]int
   256  	// i A2: changed from [2]int to [2]bool
   257  	A2 [2]bool
   258  	// i A3: changed from [3]int to [4]int
   259  	A3 [C5]int
   260  )
   261  
   262  // old
   263  type (
   264  	Sl []int
   265  	P1 *int
   266  	P2 *u1
   267  )
   268  
   269  // new
   270  type (
   271  	// i Sl: changed from []int to []string
   272  	Sl []string
   273  	// i P1: changed from *int to **bool
   274  	P1 **bool
   275  	P2 *u2 // OK: u1 corresponds to u2
   276  )
   277  
   278  // old
   279  type Bc1 int32
   280  type Bc2 uint
   281  type Bc3 float32
   282  type Bc4 complex64
   283  
   284  // new
   285  // c Bc1: changed from int32 to int
   286  type Bc1 int
   287  
   288  // c Bc2: changed from uint to uint64
   289  type Bc2 uint64
   290  
   291  // c Bc3: changed from float32 to float64
   292  type Bc3 float64
   293  
   294  // c Bc4: changed from complex64 to complex128
   295  type Bc4 complex128
   296  
   297  // old
   298  type Bi1 int32
   299  type Bi2 uint
   300  type Bi3 float64
   301  type Bi4 complex128
   302  
   303  // new
   304  // i Bi1: changed from int32 to int16
   305  type Bi1 int16
   306  
   307  // i Bi2: changed from uint to uint32
   308  type Bi2 uint32
   309  
   310  // i Bi3: changed from float64 to float32
   311  type Bi3 float32
   312  
   313  // i Bi4: changed from complex128 to complex64
   314  type Bi4 complex64
   315  
   316  // old
   317  type (
   318  	M1 map[string]int
   319  	M2 map[string]int
   320  	M3 map[string]int
   321  )
   322  
   323  // new
   324  type (
   325  	M1 map[string]int
   326  	// i M2: changed from map[string]int to map[int]int
   327  	M2 map[int]int
   328  	// i M3: changed from map[string]int to map[string]string
   329  	M3 map[string]string
   330  )
   331  
   332  // old
   333  type (
   334  	Ch1 chan int
   335  	Ch2 <-chan int
   336  	Ch3 chan int
   337  	Ch4 <-chan int
   338  )
   339  
   340  // new
   341  type (
   342  	// i Ch1, element type: changed from int to bool
   343  	Ch1 chan bool
   344  	// i Ch2: changed direction
   345  	Ch2 chan<- int
   346  	// i Ch3: changed direction
   347  	Ch3 <-chan int
   348  	// c Ch4: removed direction
   349  	Ch4 chan int
   350  )
   351  
   352  // old
   353  type I1 interface {
   354  	M1()
   355  	M2()
   356  }
   357  
   358  // new
   359  type I1 interface {
   360  	// M1()
   361  	// i I1.M1: removed
   362  	M2(int)
   363  	// i I1.M2: changed from func() to func(int)
   364  	M3()
   365  	// i I1.M3: added
   366  	m()
   367  	// i I1.m: added unexported method
   368  }
   369  
   370  // old
   371  type I2 interface {
   372  	M1()
   373  	m()
   374  }
   375  
   376  // new
   377  type I2 interface {
   378  	M1()
   379  	// m() Removing an unexported method is OK.
   380  	m2() // OK, because old already had an unexported method
   381  	// c I2.M2: added
   382  	M2()
   383  }
   384  
   385  // old
   386  type I3 interface {
   387  	io.Reader
   388  	M()
   389  }
   390  
   391  // new
   392  // OK: what matters is the method set; the name of the embedded
   393  // interface isn't important.
   394  type I3 interface {
   395  	M()
   396  	Read([]byte) (int, error)
   397  }
   398  
   399  // old
   400  type I4 io.Writer
   401  
   402  // new
   403  // OK: in both, I4 is a distinct type from io.Writer, and
   404  // the old and new I4s have the same method set.
   405  type I4 interface {
   406  	Write([]byte) (int, error)
   407  }
   408  
   409  // old
   410  type I5 = io.Writer
   411  
   412  // new
   413  // i I5: changed from io.Writer to I5
   414  // In old, I5 and io.Writer are the same type; in new,
   415  // they are different. That can break something like:
   416  //   var _ func(io.Writer) = func(pkg.I6) {}
   417  type I5 io.Writer
   418  
   419  // old
   420  type I6 interface{ Write([]byte) (int, error) }
   421  
   422  // new
   423  // i I6: changed from I6 to io.Writer
   424  // Similar to the above.
   425  type I6 = io.Writer
   426  
   427  //// correspondence with a basic type
   428  // Basic types are technically defined types, but they aren't
   429  // represented that way in go/types, so the cases below are special.
   430  
   431  // both
   432  type T1 int
   433  
   434  // old
   435  var VT1 T1
   436  
   437  // new
   438  // i VT1: changed from T1 to int
   439  // This fails because old T1 corresponds to both int and new T1.
   440  var VT1 int
   441  
   442  // old
   443  type t2 int
   444  
   445  var VT2 t2
   446  
   447  // new
   448  // OK: t2 corresponds to int. It's fine that old t2
   449  // doesn't exist in new.
   450  var VT2 int
   451  
   452  // both
   453  type t3 int
   454  
   455  func (t3) M() {}
   456  
   457  // old
   458  var VT3 t3
   459  
   460  // new
   461  // i t3.M: removed
   462  // Here the change from t3 to int is incompatible
   463  // because old t3 has an exported method.
   464  var VT3 int
   465  
   466  // old
   467  var VT4 int
   468  
   469  // new
   470  type t4 int
   471  
   472  // i VT4: changed from int to t4
   473  // This is incompatible because of code like
   474  //    VT4 + int(1)
   475  // which works in old but fails in new.
   476  // The difference from the above cases is that
   477  // in those, we were merging two types into one;
   478  // here, we are splitting int into t4 and int.
   479  var VT4 t4
   480  
   481  //////////////// Functions
   482  
   483  // old
   484  func F1(a int, b string) map[u1]A { return nil }
   485  func F2(int)                      {}
   486  func F3(int)                      {}
   487  func F4(int) int                  { return 0 }
   488  func F5(int) int                  { return 0 }
   489  func F6(int)                      {}
   490  func F7(interface{})              {}
   491  
   492  // new
   493  func F1(c int, d string) map[u2]AA { return nil } //OK: same (since u1 corresponds to u2)
   494  
   495  // i F2: changed from func(int) to func(int) bool
   496  func F2(int) bool { return true }
   497  
   498  // i F3: changed from func(int) to func(int, int)
   499  func F3(int, int) {}
   500  
   501  // i F4: changed from func(int) int to func(bool) int
   502  func F4(bool) int { return 0 }
   503  
   504  // i F5: changed from func(int) int to func(int) string
   505  func F5(int) string { return "" }
   506  
   507  // i F6: changed from func(int) to func(...int)
   508  func F6(...int) {}
   509  
   510  // i F7: changed from func(interface{}) to func(interface{x()})
   511  func F7(a interface{ x() }) {}
   512  
   513  // old
   514  func F8(bool) {}
   515  
   516  // new
   517  // c F8: changed from func to var
   518  var F8 func(bool)
   519  
   520  // old
   521  var F9 func(int)
   522  
   523  // new
   524  // i F9: changed from var to func
   525  func F9(int) {}
   526  
   527  // both
   528  // OK, even though new S1 is incompatible with old S1 (see below)
   529  func F10(S1) {}
   530  
   531  //////////////// Structs
   532  
   533  // old
   534  type S1 struct {
   535  	A int
   536  	B string
   537  	C bool
   538  	d float32
   539  }
   540  
   541  // new
   542  type S1 = s1
   543  
   544  type s1 struct {
   545  	C chan int
   546  	// i S1.C: changed from bool to chan int
   547  	A int
   548  	// i S1.B: removed
   549  	// i S1: old is comparable, new is not
   550  	x []int
   551  	d float32
   552  	E bool
   553  	// c S1.E: added
   554  }
   555  
   556  // old
   557  type embed struct {
   558  	E string
   559  }
   560  
   561  type S2 struct {
   562  	A int
   563  	embed
   564  }
   565  
   566  // new
   567  type embedx struct {
   568  	E string
   569  }
   570  
   571  type S2 struct {
   572  	embedx // OK: the unexported embedded field changed names, but the exported field didn't
   573  	A      int
   574  }
   575  
   576  // both
   577  type F int
   578  
   579  // old
   580  type S3 struct {
   581  	A int
   582  	embed
   583  }
   584  
   585  // new
   586  type embed struct{ F int }
   587  
   588  type S3 struct {
   589  	// i S3.E: removed
   590  	embed
   591  	// c S3.F: added
   592  	A int
   593  }
   594  
   595  // old
   596  type embed2 struct {
   597  	embed3
   598  	F // shadows embed3.F
   599  }
   600  
   601  type embed3 struct {
   602  	F bool
   603  }
   604  
   605  type alias = struct{ D bool }
   606  
   607  type S4 struct {
   608  	int
   609  	*embed2
   610  	embed
   611  	E int // shadows embed.E
   612  	alias
   613  	A1
   614  	*S4
   615  }
   616  
   617  // new
   618  type S4 struct {
   619  	// OK: removed unexported fields
   620  	// D and F marked as added because they are now part of the immediate fields
   621  	D bool
   622  	// c S4.D: added
   623  	E int // OK: same as in old
   624  	F F
   625  	// c S4.F: added
   626  	A1  // OK: same
   627  	*S4 // OK: same (recursive embedding)
   628  }
   629  
   630  //// Difference between exported selectable fields and exported immediate fields.
   631  // both
   632  type S5 struct{ A int }
   633  
   634  // old
   635  // Exported immediate fields: A, S5
   636  // Exported selectable fields: A int, S5 S5
   637  type S6 struct {
   638  	S5 S5
   639  	A  int
   640  }
   641  
   642  // new
   643  // Exported immediate fields: S5
   644  // Exported selectable fields: A int, S5 S5.
   645  
   646  // i S6.A: removed
   647  type S6 struct {
   648  	S5
   649  }
   650  
   651  //// Ambiguous fields can exist; they just can't be selected.
   652  // both
   653  type (
   654  	embed7a struct{ E int }
   655  	embed7b struct{ E bool }
   656  )
   657  
   658  // old
   659  type S7 struct { // legal, but no selectable fields
   660  	embed7a
   661  	embed7b
   662  }
   663  
   664  // new
   665  type S7 struct {
   666  	embed7a
   667  	embed7b
   668  	// c S7.E: added
   669  	E string
   670  }
   671  
   672  //////////////// Method sets
   673  
   674  // old
   675  type SM struct {
   676  	embedm
   677  	Embedm
   678  }
   679  
   680  func (SM) V1() {}
   681  func (SM) V2() {}
   682  func (SM) V3() {}
   683  func (SM) V4() {}
   684  func (SM) v()  {}
   685  
   686  func (*SM) P1() {}
   687  func (*SM) P2() {}
   688  func (*SM) P3() {}
   689  func (*SM) P4() {}
   690  func (*SM) p()  {}
   691  
   692  type embedm int
   693  
   694  func (embedm) EV1()  {}
   695  func (embedm) EV2()  {}
   696  func (embedm) EV3()  {}
   697  func (*embedm) EP1() {}
   698  func (*embedm) EP2() {}
   699  func (*embedm) EP3() {}
   700  
   701  type Embedm struct {
   702  	A int
   703  }
   704  
   705  func (Embedm) FV()  {}
   706  func (*Embedm) FP() {}
   707  
   708  type RepeatEmbedm struct {
   709  	Embedm
   710  }
   711  
   712  // new
   713  type SM struct {
   714  	embedm2
   715  	embedm3
   716  	Embedm
   717  	// i SM.A: changed from int to bool
   718  }
   719  
   720  // c SMa: added
   721  type SMa = SM
   722  
   723  func (SM) V1() {} // OK: same
   724  
   725  // func (SM) V2() {}
   726  // i SM.V2: removed
   727  
   728  // i SM.V3: changed from func() to func(int)
   729  func (SM) V3(int) {}
   730  
   731  // c SM.V5: added
   732  func (SM) V5() {}
   733  
   734  func (SM) v(int) {} // OK: unexported method change
   735  func (SM) v2()   {} // OK: unexported method added
   736  
   737  func (*SM) P1() {} // OK: same
   738  //func (*SM) P2() {}
   739  // i (*SM).P2: removed
   740  
   741  // i (*SM).P3: changed from func() to func(int)
   742  func (*SMa) P3(int) {}
   743  
   744  // c (*SM).P5: added
   745  func (*SM) P5() {}
   746  
   747  // func (*SM) p() {}  // OK: unexported method removed
   748  
   749  // Changing from a value to a pointer receiver or vice versa
   750  // just looks like adding and removing a method.
   751  
   752  // i SM.V4: removed
   753  // i (*SM).V4: changed from func() to func(int)
   754  func (*SM) V4(int) {}
   755  
   756  // c SM.P4: added
   757  // P4 is not removed from (*SM) because value methods
   758  // are in the pointer method set.
   759  func (SM) P4() {}
   760  
   761  type embedm2 int
   762  
   763  // i embedm.EV1: changed from func() to func(int)
   764  func (embedm2) EV1(int) {}
   765  
   766  // i embedm.EV2, method set of SM: removed
   767  // i embedm.EV2, method set of *SM: removed
   768  
   769  // i (*embedm).EP2, method set of *SM: removed
   770  func (*embedm2) EP1() {}
   771  
   772  type embedm3 int
   773  
   774  func (embedm3) EV3()  {} // OK: compatible with old embedm.EV3
   775  func (*embedm3) EP3() {} // OK: compatible with old (*embedm).EP3
   776  
   777  type Embedm struct {
   778  	// i Embedm.A: changed from int to bool
   779  	A bool
   780  }
   781  
   782  // i Embedm.FV: changed from func() to func(int)
   783  func (Embedm) FV(int) {}
   784  func (*Embedm) FP()   {}
   785  
   786  type RepeatEmbedm struct {
   787  	// i RepeatEmbedm.A: changed from int to bool
   788  	Embedm
   789  }
   790  
   791  //////////////// Whole-package interface satisfaction
   792  
   793  // old
   794  type WI1 interface {
   795  	M1()
   796  	m1()
   797  }
   798  
   799  type WI2 interface {
   800  	M2()
   801  	m2()
   802  }
   803  
   804  type WS1 int
   805  
   806  func (WS1) M1() {}
   807  func (WS1) m1() {}
   808  
   809  type WS2 int
   810  
   811  func (WS2) M2() {}
   812  func (WS2) m2() {}
   813  
   814  // new
   815  type WI1 interface {
   816  	M1()
   817  	m()
   818  }
   819  
   820  type WS1 int
   821  
   822  func (WS1) M1() {}
   823  
   824  // i WS1: no longer implements WI1
   825  //func (WS1) m1() {}
   826  
   827  type WI2 interface {
   828  	M2()
   829  	m2()
   830  	// i WS2: no longer implements WI2
   831  	m3()
   832  }
   833  
   834  type WS2 int
   835  
   836  func (WS2) M2() {}
   837  func (WS2) m2() {}
   838  
   839  //////////////// Miscellany
   840  
   841  // This verifies that the code works even through
   842  // multiple levels of unexported typed.
   843  
   844  // old
   845  var Z w
   846  
   847  type w []x
   848  type x []z
   849  type z int
   850  
   851  // new
   852  var Z w
   853  
   854  type w []x
   855  type x []z
   856  
   857  // i z: changed from int to bool
   858  type z bool
   859  
   860  // old
   861  type H struct{}
   862  
   863  func (H) M() {}
   864  
   865  // new
   866  // i H: changed from struct{} to interface{M()}
   867  type H interface {
   868  	M()
   869  }
   870  
   871  //// Splitting types
   872  
   873  //// OK: in both old and new, {J1, K1, L1} name the same type.
   874  // old
   875  type (
   876  	J1 = K1
   877  	K1 = L1
   878  	L1 int
   879  )
   880  
   881  // new
   882  type (
   883  	J1 = K1
   884  	K1 int
   885  	L1 = J1
   886  )
   887  
   888  //// Old has one type, K2; new has J2 and K2.
   889  // both
   890  type K2 int
   891  
   892  // old
   893  type J2 = K2
   894  
   895  // new
   896  // i K2: changed from K2 to K2
   897  type J2 K2 // old K2 corresponds with new J2
   898  // old K2 also corresponds with new K2: problem
   899  
   900  // both
   901  type k3 int
   902  
   903  var Vj3 j3 // expose j3
   904  
   905  // old
   906  type j3 = k3
   907  
   908  // new
   909  // OK: k3 isn't exposed
   910  type j3 k3
   911  
   912  // both
   913  type k4 int
   914  
   915  var Vj4 j4 // expose j4
   916  var VK4 k4 // expose k4
   917  
   918  // old
   919  type j4 = k4
   920  
   921  // new
   922  // i Vj4: changed from k4 to j4
   923  // e.g. p.Vj4 = p.Vk4
   924  type j4 k4