GoPLS Viewer

Home|gopls/internal/apidiff/testdata/tests.go
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
10package ignore
11
12// both
13import "io"
14
15//////////////// Basics
16
17//// Same type in both: OK.
18// both
19type A int
20
21//// Changing the type is an incompatible change.
22// old
23type B int
24
25// new
26// i B: changed from int to string
27type B string
28
29//// Adding a new type, whether alias or not, is a compatible change.
30// new
31// c AA: added
32type AA = A
33
34// c B1: added
35type B1 bool
36
37//// Change of type for an unexported name doesn't matter...
38// old
39type t int
40
41// new
42type t string // OK: t isn't part of the API
43
44//// ...unless it is exposed.
45// both
46var V2 u
47
48// old
49type u string
50
51// new
52// i u: changed from string to int
53type u int
54
55//// An exposed, unexported type can be renamed.
56// both
57type u2 int
58
59// old
60type u1 int
61
62var V5 u1
63
64// new
65var 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
69type u3 int
70
71// old
72type (
73    Split1 = u1
74    Split2 = u1
75)
76
77// new
78type (
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
88type (
89    GoodMerge1 = u2
90    GoodMerge2 = u3
91)
92
93// new
94type (
95    GoodMerge1 = u3
96    GoodMerge2 = u3
97)
98
99//// Merging isn't OK here because a method is lost.
100// both
101type u4 int
102
103func (u4M() {}
104
105// old
106type (
107    BadMerge1 = u3
108    BadMerge2 = u4
109)
110
111// new
112type (
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
121type Rem int
122
123// new
124// i Rem: removed
125
126//////////////// Constants
127
128//// type changes
129// old
130const (
131    C1     = 1
132    C2 int = 2
133    C3     = 3
134    C4 u1  = 4
135)
136
137var V8 int
138
139// new
140const (
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
154const (
155    Cr1 = 1
156    Cr2 = "2"
157    Cr3 = 3.5
158    Cr4 = complex(04.1)
159)
160
161// new
162const (
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.10)
171)
172
173//////////////// Variables
174
175//// simple type changes
176// old
177var (
178    V1 string
179    V3 A
180    V7 <-chan int
181)
182
183// new
184var (
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
194var (
195    V9  interface{ M() }
196    V10 interface{ M() }
197    V11 interface{ M() }
198)
199
200// new
201var (
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
215var (
216    VS1 struct{ AB int }
217    VS2 struct{ AB int }
218    VS3 struct{ AB int }
219    VS4 struct {
220        A int
221        u1
222    }
223)
224
225// new
226var (
227    // i VS1: changed from struct{A int; B int} to struct{B int; A int}
228    VS1 struct{ BA 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{ ABC int }
233    VS4 struct {
234        A int
235        u2
236    }
237)
238
239//////////////// Types
240
241// old
242const C5 = 3
243
244type (
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
252const C5 = 4
253
254type (
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
263type (
264    Sl []int
265    P1 *int
266    P2 *u1
267)
268
269// new
270type (
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
279type Bc1 int32
280type Bc2 uint
281type Bc3 float32
282type Bc4 complex64
283
284// new
285// c Bc1: changed from int32 to int
286type Bc1 int
287
288// c Bc2: changed from uint to uint64
289type Bc2 uint64
290
291// c Bc3: changed from float32 to float64
292type Bc3 float64
293
294// c Bc4: changed from complex64 to complex128
295type Bc4 complex128
296
297// old
298type Bi1 int32
299type Bi2 uint
300type Bi3 float64
301type Bi4 complex128
302
303// new
304// i Bi1: changed from int32 to int16
305type Bi1 int16
306
307// i Bi2: changed from uint to uint32
308type Bi2 uint32
309
310// i Bi3: changed from float64 to float32
311type Bi3 float32
312
313// i Bi4: changed from complex128 to complex64
314type Bi4 complex64
315
316// old
317type (
318    M1 map[string]int
319    M2 map[string]int
320    M3 map[string]int
321)
322
323// new
324type (
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
333type (
334    Ch1 chan int
335    Ch2 <-chan int
336    Ch3 chan int
337    Ch4 <-chan int
338)
339
340// new
341type (
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
353type I1 interface {
354    M1()
355    M2()
356}
357
358// new
359type 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
371type I2 interface {
372    M1()
373    m()
374}
375
376// new
377type 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
386type 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.
394type I3 interface {
395    M()
396    Read([]byte) (interror)
397}
398
399// old
400type 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.
405type I4 interface {
406    Write([]byte) (interror)
407}
408
409// old
410type 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) {}
417type I5 io.Writer
418
419// old
420type I6 interface{ Write([]byte) (interror) }
421
422// new
423// i I6: changed from I6 to io.Writer
424// Similar to the above.
425type 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
432type T1 int
433
434// old
435var 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.
440var VT1 int
441
442// old
443type t2 int
444
445var VT2 t2
446
447// new
448// OK: t2 corresponds to int. It's fine that old t2
449// doesn't exist in new.
450var VT2 int
451
452// both
453type t3 int
454
455func (t3M() {}
456
457// old
458var 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.
464var VT3 int
465
466// old
467var VT4 int
468
469// new
470type 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.
479var VT4 t4
480
481//////////////// Functions
482
483// old
484func F1(a intb string) map[u1]A { return nil }
485func F2(int)                      {}
486func F3(int)                      {}
487func F4(intint                  { return 0 }
488func F5(intint                  { return 0 }
489func F6(int)                      {}
490func F7(interface{})              {}
491
492// new
493func F1(c intd 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
496func F2(intbool { return true }
497
498// i F3: changed from func(int) to func(int, int)
499func F3(intint) {}
500
501// i F4: changed from func(int) int to func(bool) int
502func F4(boolint { return 0 }
503
504// i F5: changed from func(int) int to func(int) string
505func F5(intstring { return "" }
506
507// i F6: changed from func(int) to func(...int)
508func F6(...int) {}
509
510// i F7: changed from func(interface{}) to func(interface{x()})
511func F7(a interface{ x() }) {}
512
513// old
514func F8(bool) {}
515
516// new
517// c F8: changed from func to var
518var F8 func(bool)
519
520// old
521var F9 func(int)
522
523// new
524// i F9: changed from var to func
525func F9(int) {}
526
527// both
528// OK, even though new S1 is incompatible with old S1 (see below)
529func F10(S1) {}
530
531//////////////// Structs
532
533// old
534type S1 struct {
535    A int
536    B string
537    C bool
538    d float32
539}
540
541// new
542type S1 = s1
543
544type 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
557type embed struct {
558    E string
559}
560
561type S2 struct {
562    A int
563    embed
564}
565
566// new
567type embedx struct {
568    E string
569}
570
571type S2 struct {
572    embedx // OK: the unexported embedded field changed names, but the exported field didn't
573    A      int
574}
575
576// both
577type F int
578
579// old
580type S3 struct {
581    A int
582    embed
583}
584
585// new
586type embed struct{ F int }
587
588type S3 struct {
589    // i S3.E: removed
590    embed
591    // c S3.F: added
592    A int
593}
594
595// old
596type embed2 struct {
597    embed3
598    F // shadows embed3.F
599}
600
601type embed3 struct {
602    F bool
603}
604
605type alias = struct{ D bool }
606
607type S4 struct {
608    int
609    *embed2
610    embed
611    E int // shadows embed.E
612    alias
613    A1
614    *S4
615}
616
617// new
618type 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
632type S5 struct{ A int }
633
634// old
635// Exported immediate fields: A, S5
636// Exported selectable fields: A int, S5 S5
637type 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
647type S6 struct {
648    S5
649}
650
651//// Ambiguous fields can exist; they just can't be selected.
652// both
653type (
654    embed7a struct{ E int }
655    embed7b struct{ E bool }
656)
657
658// old
659type S7 struct { // legal, but no selectable fields
660    embed7a
661    embed7b
662}
663
664// new
665type S7 struct {
666    embed7a
667    embed7b
668    // c S7.E: added
669    E string
670}
671
672//////////////// Method sets
673
674// old
675type SM struct {
676    embedm
677    Embedm
678}
679
680func (SMV1() {}
681func (SMV2() {}
682func (SMV3() {}
683func (SMV4() {}
684func (SMv()  {}
685
686func (*SMP1() {}
687func (*SMP2() {}
688func (*SMP3() {}
689func (*SMP4() {}
690func (*SMp()  {}
691
692type embedm int
693
694func (embedmEV1()  {}
695func (embedmEV2()  {}
696func (embedmEV3()  {}
697func (*embedmEP1() {}
698func (*embedmEP2() {}
699func (*embedmEP3() {}
700
701type Embedm struct {
702    A int
703}
704
705func (EmbedmFV()  {}
706func (*EmbedmFP() {}
707
708type RepeatEmbedm struct {
709    Embedm
710}
711
712// new
713type SM struct {
714    embedm2
715    embedm3
716    Embedm
717    // i SM.A: changed from int to bool
718}
719
720// c SMa: added
721type SMa = SM
722
723func (SMV1() {} // OK: same
724
725// func (SM) V2() {}
726// i SM.V2: removed
727
728// i SM.V3: changed from func() to func(int)
729func (SMV3(int) {}
730
731// c SM.V5: added
732func (SMV5() {}
733
734func (SMv(int) {} // OK: unexported method change
735func (SMv2()   {} // OK: unexported method added
736
737func (*SMP1() {} // OK: same
738//func (*SM) P2() {}
739// i (*SM).P2: removed
740
741// i (*SM).P3: changed from func() to func(int)
742func (*SMaP3(int) {}
743
744// c (*SM).P5: added
745func (*SMP5() {}
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)
754func (*SMV4(int) {}
755
756// c SM.P4: added
757// P4 is not removed from (*SM) because value methods
758// are in the pointer method set.
759func (SMP4() {}
760
761type embedm2 int
762
763// i embedm.EV1: changed from func() to func(int)
764func (embedm2EV1(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
770func (*embedm2EP1() {}
771
772type embedm3 int
773
774func (embedm3EV3()  {} // OK: compatible with old embedm.EV3
775func (*embedm3EP3() {} // OK: compatible with old (*embedm).EP3
776
777type 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)
783func (EmbedmFV(int) {}
784func (*EmbedmFP()   {}
785
786type RepeatEmbedm struct {
787    // i RepeatEmbedm.A: changed from int to bool
788    Embedm
789}
790
791//////////////// Whole-package interface satisfaction
792
793// old
794type WI1 interface {
795    M1()
796    m1()
797}
798
799type WI2 interface {
800    M2()
801    m2()
802}
803
804type WS1 int
805
806func (WS1M1() {}
807func (WS1m1() {}
808
809type WS2 int
810
811func (WS2M2() {}
812func (WS2m2() {}
813
814// new
815type WI1 interface {
816    M1()
817    m()
818}
819
820type WS1 int
821
822func (WS1M1() {}
823
824// i WS1: no longer implements WI1
825//func (WS1) m1() {}
826
827type WI2 interface {
828    M2()
829    m2()
830    // i WS2: no longer implements WI2
831    m3()
832}
833
834type WS2 int
835
836func (WS2M2() {}
837func (WS2m2() {}
838
839//////////////// Miscellany
840
841// This verifies that the code works even through
842// multiple levels of unexported typed.
843
844// old
845var Z w
846
847type w []x
848type x []z
849type z int
850
851// new
852var Z w
853
854type w []x
855type x []z
856
857// i z: changed from int to bool
858type z bool
859
860// old
861type H struct{}
862
863func (HM() {}
864
865// new
866// i H: changed from struct{} to interface{M()}
867type 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
875type (
876    J1 = K1
877    K1 = L1
878    L1 int
879)
880
881// new
882type (
883    J1 = K1
884    K1 int
885    L1 = J1
886)
887
888//// Old has one type, K2; new has J2 and K2.
889// both
890type K2 int
891
892// old
893type J2 = K2
894
895// new
896// i K2: changed from K2 to K2
897type J2 K2 // old K2 corresponds with new J2
898// old K2 also corresponds with new K2: problem
899
900// both
901type k3 int
902
903var Vj3 j3 // expose j3
904
905// old
906type j3 = k3
907
908// new
909// OK: k3 isn't exposed
910type j3 k3
911
912// both
913type k4 int
914
915var Vj4 j4 // expose j4
916var VK4 k4 // expose k4
917
918// old
919type j4 = k4
920
921// new
922// i Vj4: changed from k4 to j4
923// e.g. p.Vj4 = p.Vk4
924type j4 k4
925
MembersX
S4.D
embed7b.E
SM.V2
Ch3
S3
Bi3
SM
io
T1
alias
S6.S5
embed7a
SM.v
SM.P1
embedm.EP1
u1
V8
WS2.m2
WS1
WS2.M2
S7
embedm2
VK4
A3
VT1
Bc4
I1
F1.c
F1.d
F9
S1
Cr1
Cr2
w
k4
s1.E
SM.V1
Embedm
M2
VT2
s1
embedm
x
VT4
F1.b
embedm2.EP1
L1
V1
I4
Ch4
embed2
embedm3.EP3
Rem
C3
F2
Embedm.A
SMa.P3
u
P2
embed
embedx.E
SM.V4
SMa
embedm3.EV3
VT3
S1.A
I3
F5
s1.d
embedx
SM.V3
V3
Sl
S3.A
Split1
Ch1
WS1.M1
k3
Vj4
Bc3
t3
S1.d
Embedm.FV
H
H.M
Bi4
Ch2
Bi2
t4
embedm.EP2
embedm2.EV1
WI2
J1
V2
C4
embedm.EP3
SM.v2
F
SM.P3
embed3.F
embed7a.E
t2
F3
S2.A
embed3
S6.A
embedm3
J2
B
F1
embedm.EV3
I5
s1.x
S1.B
Z
Bc1
t3.M
Bi1
I6
s1.A
S5.A
embed7b
SM.P4
GoodMerge1
C1
S4.F
j3
M1
s1.C
C2
A2
F7.a
embed.F
S7.E
SM.P2
V5
u3
WI1
K2
Vj3
GoodMerge2
I2
C5
A1
P1
F7
F8
embed.E
B1
Cr3
WS2
RepeatEmbedm
SM.P5
S4
z
t
S1.C
S4.E
S6
SM.p
embedm.EV2
WS1.m1
BadMerge2
F10
j4
AA
embedm.EV1
BadMerge1
M3
F4
F6
alias.D
S5
A
u2
K1
u4.M
Bc2
F1.a
S2
Embedm.FP
SM.V5
Split2
u4
Members
X