10
10
//
11
11
// THIS PACKAGE IS EXPERIMENTAL AND MAY CHANGE AT ANY TIME.
12
12
//
13
- // It is provided only for the gorename tool. Ideally this
14
- // functionality will become part of the type-checker in due course,
15
- // since it is computing it anyway, and it is robust for ill-typed
16
- // inputs, which this package is not.
13
+ // It is provided only for the gopls tool. It requires well-typed inputs.
14
+ //
17
15
package satisfy // import "golang.org/x/tools/refactor/satisfy"
18
16
19
17
// NOTES:
@@ -25,9 +23,6 @@ package satisfy // import "golang.org/x/tools/refactor/satisfy"
25
23
// ...
26
24
// }})
27
25
//
28
- // TODO(adonovan): make this robust against ill-typed input.
29
- // Or move it into the type-checker.
30
- //
31
26
// Assignability conversions are possible in the following places:
32
27
// - in assignments y = x, y := x, var y = x.
33
28
// - from call argument types to formal parameter types
@@ -51,11 +46,15 @@ import (
51
46
52
47
"golang.org/x/tools/go/ast/astutil"
53
48
"golang.org/x/tools/go/types/typeutil"
49
+ "golang.org/x/tools/internal/typeparams"
54
50
)
55
51
56
52
// A Constraint records the fact that the RHS type does and must
57
53
// satisfy the LHS type, which is an interface.
58
54
// The names are suggestive of an assignment statement LHS = RHS.
55
+ //
56
+ // The constraint is implicitly universally quantified over any type
57
+ // parameters appearing within the two types.
59
58
type Constraint struct {
60
59
LHS , RHS types.Type
61
60
}
@@ -129,13 +128,13 @@ func (f *Finder) exprN(e ast.Expr) types.Type {
129
128
130
129
case * ast.CallExpr :
131
130
// x, err := f(args)
132
- sig := f .expr (e .Fun ). Underlying ( ).(* types.Signature )
131
+ sig := coreType ( f .expr (e .Fun )).(* types.Signature )
133
132
f .call (sig , e .Args )
134
133
135
134
case * ast.IndexExpr :
136
135
// y, ok := x[i]
137
136
x := f .expr (e .X )
138
- f .assign (f .expr (e .Index ), x . Underlying ( ).(* types.Map ).Key ())
137
+ f .assign (f .expr (e .Index ), coreType ( x ).(* types.Map ).Key ())
139
138
140
139
case * ast.TypeAssertExpr :
141
140
// y, ok := x.(T)
@@ -215,7 +214,7 @@ func (f *Finder) builtin(obj *types.Builtin, sig *types.Signature, args []ast.Ex
215
214
f .expr (args [1 ])
216
215
} else {
217
216
// append(x, y, z)
218
- tElem := s . Underlying ( ).(* types.Slice ).Elem ()
217
+ tElem := coreType ( s ).(* types.Slice ).Elem ()
219
218
for _ , arg := range args [1 :] {
220
219
f .assign (tElem , f .expr (arg ))
221
220
}
@@ -224,7 +223,7 @@ func (f *Finder) builtin(obj *types.Builtin, sig *types.Signature, args []ast.Ex
224
223
case "delete" :
225
224
m := f .expr (args [0 ])
226
225
k := f .expr (args [1 ])
227
- f .assign (m . Underlying ( ).(* types.Map ).Key (), k )
226
+ f .assign (coreType ( m ).(* types.Map ).Key (), k )
228
227
229
228
default :
230
229
// ordinary call
@@ -358,6 +357,7 @@ func (f *Finder) expr(e ast.Expr) types.Type {
358
357
f .sig = saved
359
358
360
359
case * ast.CompositeLit :
360
+ // No need for coreType here: go1.18 disallows P{...} for type param P.
361
361
switch T := deref (tv .Type ).Underlying ().(type ) {
362
362
case * types.Struct :
363
363
for i , elem := range e .Elts {
@@ -403,12 +403,20 @@ func (f *Finder) expr(e ast.Expr) types.Type {
403
403
}
404
404
405
405
case * ast.IndexExpr :
406
- x := f .expr (e .X )
407
- i := f .expr (e .Index )
408
- if ux , ok := x .Underlying ().(* types.Map ); ok {
409
- f .assign (ux .Key (), i )
406
+ if instance (f .info , e .X ) {
407
+ // f[T] or C[T] -- generic instantiation
408
+ } else {
409
+ // x[i] or m[k] -- index or lookup operation
410
+ x := f .expr (e .X )
411
+ i := f .expr (e .Index )
412
+ if ux , ok := coreType (x ).(* types.Map ); ok {
413
+ f .assign (ux .Key (), i )
414
+ }
410
415
}
411
416
417
+ case * typeparams.IndexListExpr :
418
+ // f[X, Y] -- generic instantiation
419
+
412
420
case * ast.SliceExpr :
413
421
f .expr (e .X )
414
422
if e .Low != nil {
@@ -439,7 +447,7 @@ func (f *Finder) expr(e ast.Expr) types.Type {
439
447
}
440
448
}
441
449
// ordinary call
442
- f .call (f .expr (e .Fun ). Underlying ( ).(* types.Signature ), e .Args )
450
+ f .call (coreType ( f .expr (e .Fun )).(* types.Signature ), e .Args )
443
451
}
444
452
445
453
case * ast.StarExpr :
@@ -499,7 +507,7 @@ func (f *Finder) stmt(s ast.Stmt) {
499
507
case * ast.SendStmt :
500
508
ch := f .expr (s .Chan )
501
509
val := f .expr (s .Value )
502
- f .assign (ch . Underlying ( ).(* types.Chan ).Elem (), val )
510
+ f .assign (coreType ( ch ).(* types.Chan ).Elem (), val )
503
511
504
512
case * ast.IncDecStmt :
505
513
f .expr (s .X )
@@ -647,35 +655,35 @@ func (f *Finder) stmt(s ast.Stmt) {
647
655
if s .Key != nil {
648
656
k := f .expr (s .Key )
649
657
var xelem types.Type
650
- // keys of array, *array, slice, string aren't interesting
651
- switch ux := x .Underlying ().(type ) {
658
+ // Keys of array, *array, slice, string aren't interesting
659
+ // since the RHS key type is just an int.
660
+ switch ux := coreType (x ).(type ) {
652
661
case * types.Chan :
653
662
xelem = ux .Elem ()
654
663
case * types.Map :
655
664
xelem = ux .Key ()
656
665
}
657
666
if xelem != nil {
658
- f .assign (xelem , k )
667
+ f .assign (k , xelem )
659
668
}
660
669
}
661
670
if s .Value != nil {
662
671
val := f .expr (s .Value )
663
672
var xelem types.Type
664
- // values of strings aren't interesting
665
- switch ux := x .Underlying ().(type ) {
673
+ // Values of type strings aren't interesting because
674
+ // the RHS value type is just a rune.
675
+ switch ux := coreType (x ).(type ) {
666
676
case * types.Array :
667
677
xelem = ux .Elem ()
668
- case * types.Chan :
669
- xelem = ux .Elem ()
670
678
case * types.Map :
671
679
xelem = ux .Elem ()
672
680
case * types.Pointer : // *array
673
- xelem = deref (ux ).(* types.Array ).Elem ()
681
+ xelem = coreType ( deref (ux ) ).(* types.Array ).Elem ()
674
682
case * types.Slice :
675
683
xelem = ux .Elem ()
676
684
}
677
685
if xelem != nil {
678
- f .assign (xelem , val )
686
+ f .assign (val , xelem )
679
687
}
680
688
}
681
689
}
@@ -690,7 +698,7 @@ func (f *Finder) stmt(s ast.Stmt) {
690
698
691
699
// deref returns a pointer's element type; otherwise it returns typ.
692
700
func deref (typ types.Type ) types.Type {
693
- if p , ok := typ . Underlying ( ).(* types.Pointer ); ok {
701
+ if p , ok := coreType ( typ ).(* types.Pointer ); ok {
694
702
return p .Elem ()
695
703
}
696
704
return typ
@@ -699,3 +707,19 @@ func deref(typ types.Type) types.Type {
699
707
func unparen (e ast.Expr ) ast.Expr { return astutil .Unparen (e ) }
700
708
701
709
func isInterface (T types.Type ) bool { return types .IsInterface (T ) }
710
+
711
+ func coreType (T types.Type ) types.Type { return typeparams .CoreType (T ) }
712
+
713
+ func instance (info * types.Info , expr ast.Expr ) bool {
714
+ var id * ast.Ident
715
+ switch x := expr .(type ) {
716
+ case * ast.Ident :
717
+ id = x
718
+ case * ast.SelectorExpr :
719
+ id = x .Sel
720
+ default :
721
+ return false
722
+ }
723
+ _ , ok := typeparams .GetInstances (info )[id ]
724
+ return ok
725
+ }
0 commit comments