@@ -106,10 +106,13 @@ func newUnifier(tparams []*TypeParam, targs []Type) *unifier {
106
106
return & unifier {handles , 0 }
107
107
}
108
108
109
+ // unifyMode controls the behavior of the unifier.
110
+ type unifyMode uint
111
+
109
112
// unify attempts to unify x and y and reports whether it succeeded.
110
113
// As a side-effect, types may be inferred for type parameters.
111
- func (u * unifier ) unify (x , y Type ) bool {
112
- return u .nify (x , y , nil )
114
+ func (u * unifier ) unify (x , y Type , mode unifyMode ) bool {
115
+ return u .nify (x , y , mode , nil )
113
116
}
114
117
115
118
func (u * unifier ) tracef (format string , args ... interface {}) {
@@ -241,10 +244,10 @@ func (u *unifier) inferred(tparams []*TypeParam) []Type {
241
244
// adapted version of Checker.identical. For changes to that
242
245
// code the corresponding changes should be made here.
243
246
// Must not be called directly from outside the unifier.
244
- func (u * unifier ) nify (x , y Type , p * ifacePair ) (result bool ) {
247
+ func (u * unifier ) nify (x , y Type , mode unifyMode , p * ifacePair ) (result bool ) {
245
248
u .depth ++
246
249
if traceInference {
247
- u .tracef ("%s ≡ %s" , x , y )
250
+ u .tracef ("%s ≡ %s (mode %d) " , x , y , mode )
248
251
}
249
252
defer func () {
250
253
if traceInference && ! result {
@@ -324,13 +327,13 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
324
327
return true
325
328
}
326
329
// both x and y have an inferred type - they must match
327
- return u .nify (u .at (px ), u .at (py ), p )
330
+ return u .nify (u .at (px ), u .at (py ), mode , p )
328
331
329
332
case px != nil :
330
333
// x is a type parameter, y is not
331
334
if x := u .at (px ); x != nil {
332
335
// x has an inferred type which must match y
333
- if u .nify (x , y , p ) {
336
+ if u .nify (x , y , mode , p ) {
334
337
// If we have a match, possibly through underlying types,
335
338
// and y is a defined type, make sure we record that type
336
339
// for type parameter x, which may have until now only
@@ -361,6 +364,9 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
361
364
x , y = y , x
362
365
}
363
366
367
+ // Type elements (array, slice, etc. elements) use emode for unification.
368
+ emode := mode
369
+
364
370
// If EnableInterfaceInference is set and both types are interfaces, one
365
371
// interface must have a subset of the methods of the other and corresponding
366
372
// method signatures must unify.
@@ -427,7 +433,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
427
433
}
428
434
// All xmethods must exist in ymethods and corresponding signatures must unify.
429
435
for _ , xm := range xmethods {
430
- if ym := ymap [xm .Id ()]; ym == nil || ! u .nify (xm .typ , ym .typ , p ) {
436
+ if ym := ymap [xm .Id ()]; ym == nil || ! u .nify (xm .typ , ym .typ , emode , p ) {
431
437
return false
432
438
}
433
439
}
@@ -448,7 +454,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
448
454
xmethods := xi .typeSet ().methods
449
455
for _ , xm := range xmethods {
450
456
obj , _ , _ := LookupFieldOrMethod (y , false , xm .pkg , xm .name )
451
- if ym , _ := obj .(* Func ); ym == nil || ! u .nify (xm .typ , ym .typ , p ) {
457
+ if ym , _ := obj .(* Func ); ym == nil || ! u .nify (xm .typ , ym .typ , emode , p ) {
452
458
return false
453
459
}
454
460
}
@@ -474,13 +480,13 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
474
480
if y , ok := y .(* Array ); ok {
475
481
// If one or both array lengths are unknown (< 0) due to some error,
476
482
// assume they are the same to avoid spurious follow-on errors.
477
- return (x .len < 0 || y .len < 0 || x .len == y .len ) && u .nify (x .elem , y .elem , p )
483
+ return (x .len < 0 || y .len < 0 || x .len == y .len ) && u .nify (x .elem , y .elem , emode , p )
478
484
}
479
485
480
486
case * Slice :
481
487
// Two slice types unify if their element types unify.
482
488
if y , ok := y .(* Slice ); ok {
483
- return u .nify (x .elem , y .elem , p )
489
+ return u .nify (x .elem , y .elem , emode , p )
484
490
}
485
491
486
492
case * Struct :
@@ -495,7 +501,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
495
501
if f .embedded != g .embedded ||
496
502
x .Tag (i ) != y .Tag (i ) ||
497
503
! f .sameId (g .pkg , g .name ) ||
498
- ! u .nify (f .typ , g .typ , p ) {
504
+ ! u .nify (f .typ , g .typ , emode , p ) {
499
505
return false
500
506
}
501
507
}
@@ -506,7 +512,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
506
512
case * Pointer :
507
513
// Two pointer types unify if their base types unify.
508
514
if y , ok := y .(* Pointer ); ok {
509
- return u .nify (x .base , y .base , p )
515
+ return u .nify (x .base , y .base , emode , p )
510
516
}
511
517
512
518
case * Tuple :
@@ -517,7 +523,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
517
523
if x != nil {
518
524
for i , v := range x .vars {
519
525
w := y .vars [i ]
520
- if ! u .nify (v .typ , w .typ , p ) {
526
+ if ! u .nify (v .typ , w .typ , mode , p ) {
521
527
return false
522
528
}
523
529
}
@@ -534,8 +540,8 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
534
540
// TODO(gri) handle type parameters or document why we can ignore them.
535
541
if y , ok := y .(* Signature ); ok {
536
542
return x .variadic == y .variadic &&
537
- u .nify (x .params , y .params , p ) &&
538
- u .nify (x .results , y .results , p )
543
+ u .nify (x .params , y .params , emode , p ) &&
544
+ u .nify (x .results , y .results , emode , p )
539
545
}
540
546
541
547
case * Interface :
@@ -592,7 +598,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
592
598
}
593
599
for i , f := range a {
594
600
g := b [i ]
595
- if f .Id () != g .Id () || ! u .nify (f .typ , g .typ , q ) {
601
+ if f .Id () != g .Id () || ! u .nify (f .typ , g .typ , emode , q ) {
596
602
return false
597
603
}
598
604
}
@@ -603,13 +609,13 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
603
609
case * Map :
604
610
// Two map types unify if their key and value types unify.
605
611
if y , ok := y .(* Map ); ok {
606
- return u .nify (x .key , y .key , p ) && u .nify (x .elem , y .elem , p )
612
+ return u .nify (x .key , y .key , emode , p ) && u .nify (x .elem , y .elem , emode , p )
607
613
}
608
614
609
615
case * Chan :
610
616
// Two channel types unify if their value types unify.
611
617
if y , ok := y .(* Chan ); ok {
612
- return u .nify (x .elem , y .elem , p )
618
+ return u .nify (x .elem , y .elem , emode , p )
613
619
}
614
620
615
621
case * Named :
@@ -625,11 +631,11 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
625
631
// If one or both of x and y are interfaces, use interface unification.
626
632
switch {
627
633
case xi != nil && yi != nil :
628
- return u .nify (xi , yi , p )
634
+ return u .nify (xi , yi , mode , p )
629
635
case xi != nil :
630
- return u .nify (xi , y , p )
636
+ return u .nify (xi , y , mode , p )
631
637
case yi != nil :
632
- return u .nify (x , yi , p )
638
+ return u .nify (x , yi , mode , p )
633
639
}
634
640
// In all other cases, the type arguments and origins must match.
635
641
}
@@ -643,7 +649,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
643
649
return false
644
650
}
645
651
for i , xarg := range xargs {
646
- if ! u .nify (xarg , yargs [i ], p ) {
652
+ if ! u .nify (xarg , yargs [i ], mode , p ) {
647
653
return false
648
654
}
649
655
}
@@ -678,7 +684,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
678
684
if traceInference {
679
685
u .tracef ("core %s ≡ %s" , x , y )
680
686
}
681
- return u .nify (cx , y , p )
687
+ return u .nify (cx , y , mode , p )
682
688
}
683
689
}
684
690
// x != y and there's nothing to do
@@ -687,7 +693,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
687
693
// avoid a crash in case of nil type
688
694
689
695
default :
690
- panic (sprintf (nil , true , "u.nify(%s, %s)" , x , y ))
696
+ panic (sprintf (nil , true , "u.nify(%s, %s, %d )" , x , y , mode ))
691
697
}
692
698
693
699
return false
0 commit comments