@@ -134,25 +134,28 @@ func (i *CompletionItem) Snippet() string {
134
134
return i .InsertText
135
135
}
136
136
137
- func (i * CompletionItem ) addPrefixSuffix (c * completer , prefix string , suffix string ) error {
138
- if prefix != "" {
137
+ // addConversion wraps the existing completionItem in a conversion expression.
138
+ // Only affects the receiver's InsertText and snippet fields, not the Label.
139
+ // An empty conv argument has no effect.
140
+ func (i * CompletionItem ) addConversion (c * completer , conv conversionEdits ) error {
141
+ if conv .prefix != "" {
139
142
// If we are in a selector, add an edit to place prefix before selector.
140
143
if sel := enclosingSelector (c .path , c .pos ); sel != nil {
141
- edits , err := c .editText (sel .Pos (), sel .Pos (), prefix )
144
+ edits , err := c .editText (sel .Pos (), sel .Pos (), conv . prefix )
142
145
if err != nil {
143
146
return err
144
147
}
145
148
i .AdditionalTextEdits = append (i .AdditionalTextEdits , edits ... )
146
149
} else {
147
150
// If there is no selector, just stick the prefix at the start.
148
- i .InsertText = prefix + i .InsertText
149
- i .snippet .PrependText (prefix )
151
+ i .InsertText = conv . prefix + i .InsertText
152
+ i .snippet .PrependText (conv . prefix )
150
153
}
151
154
}
152
155
153
- if suffix != "" {
154
- i .InsertText += suffix
155
- i .snippet .WriteText (suffix )
156
+ if conv . suffix != "" {
157
+ i .InsertText += conv . suffix
158
+ i .snippet .WriteText (conv . suffix )
156
159
}
157
160
158
161
return nil
@@ -2189,6 +2192,10 @@ type candidateInference struct {
2189
2192
// convertibleTo is a type our candidate type must be convertible to.
2190
2193
convertibleTo types.Type
2191
2194
2195
+ // needsExactType is true if the candidate type must be exactly the type of
2196
+ // the objType, e.g. an interface rather than it's implementors.
2197
+ needsExactType bool
2198
+
2192
2199
// typeName holds information about the expected type name at
2193
2200
// position, if any.
2194
2201
typeName typeNameInference
@@ -2324,26 +2331,32 @@ Nodes:
2324
2331
break Nodes
2325
2332
}
2326
2333
2327
- sig , _ := c .pkg .TypesInfo ().Types [node .Fun ].Type .(* types.Signature )
2334
+ if sig , ok := c .pkg .TypesInfo ().Types [node .Fun ].Type .(* types.Signature ); ok {
2335
+ // Out of bounds arguments get no inference completion.
2336
+ if ! sig .Variadic () && exprAtPos (c .pos , node .Args ) >= sig .Params ().Len () {
2337
+ return inf
2338
+ }
2328
2339
2329
- if sig != nil && sig .TypeParams ().Len () > 0 && len (c .path ) > i + 1 {
2330
- // infer an instantiation for the CallExpr from it's context
2331
- switch c .path [i + 1 ].(type ) {
2332
- case * ast.AssignStmt , * ast.ReturnStmt , * ast.SendStmt , * ast.ValueSpec :
2333
- // Defer call to reverseInferExpectedCallParamType so we can provide it the
2334
- // inferences about its parent node.
2335
- defer func (sig * types.Signature ) {
2340
+ // Call has uninstantiated type parameters.
2341
+ // Skips inference for partially instantiated calls until partially
2342
+ // instantiating signatures has stronger support.
2343
+ if sig .TypeParams ().Len () > 0 && c .numTypeArgs (node ) == 0 && len (c .path ) > i + 1 {
2344
+ // Use the CallExpr's surroundings to infer an instantiation from its return types.
2345
+ switch c .path [i + 1 ].(type ) {
2346
+ case * ast.AssignStmt , * ast.ReturnStmt , * ast.SendStmt , * ast.ValueSpec :
2347
+ // Defer call to reverseInferExpectedCallParamType so we can provide it the
2348
+ // inferences about its parent node.
2349
+ defer func (sig * types.Signature ) {
2350
+ inf = c .reverseInferExpectedCallParam (inf , node , sig )
2351
+ }(sig )
2352
+ continue Nodes
2353
+ case * ast.KeyValueExpr :
2354
+ c .enclosingCompositeLiteral = enclosingCompositeLiteral (c .path [i :], node .Pos (), c .pkg .TypesInfo ())
2336
2355
inf = c .reverseInferExpectedCallParam (inf , node , sig )
2337
- }(sig )
2338
- continue Nodes
2339
- case * ast.KeyValueExpr :
2340
- c .enclosingCompositeLiteral = enclosingCompositeLiteral (c .path [i :], node .Pos (), c .pkg .TypesInfo ())
2341
- inf = c .reverseInferExpectedCallParam (inf , node , sig )
2342
- break Nodes
2356
+ break Nodes
2357
+ }
2343
2358
}
2344
- }
2345
2359
2346
- if sig != nil {
2347
2360
inf = c .expectedCallParamType (inf , node , sig )
2348
2361
}
2349
2362
@@ -2531,79 +2544,82 @@ Nodes:
2531
2544
return inf
2532
2545
}
2533
2546
2534
- func reverseInferSignature (sig * types.Signature , targetType []types.Type ) []types.Type {
2535
- if sig .Results ().Len () != len (targetType ) {
2536
- return nil
2547
+ func (c * completer ) numTypeArgs (callExpr * ast.CallExpr ) int {
2548
+ switch fun := callExpr .Fun .(type ) {
2549
+ case * ast.IndexListExpr :
2550
+ return len (fun .Indices )
2551
+ case * ast.IndexExpr :
2552
+ if typ , ok := c .pkg .TypesInfo ().Types [fun .Index ]; ok && typeIsValid (typ .Type ) {
2553
+ return 1
2554
+ }
2555
+ }
2556
+ return 0
2557
+ }
2558
+
2559
+ // reverseInferSignature instantiates the call site of a generic function
2560
+ // based on the expected return types. Returns false if inference fails or is invalid.
2561
+ func reverseInferSignature (sig * types.Signature , targetType []types.Type ) ([]types.Type , bool ) {
2562
+ if sig .Results ().Len () != len (targetType ) || len (targetType ) == 0 {
2563
+ return nil , false
2537
2564
}
2538
2565
2539
- tparams := []* types.TypeParam {}
2540
- targs := []types.Type {}
2566
+ tparams := make ([]* types.TypeParam , sig .TypeParams ().Len ())
2541
2567
for i := range sig .TypeParams ().Len () {
2542
- tparams = append (tparams , sig .TypeParams ().At (i ))
2543
- targs = append (targs , nil )
2568
+ tparams [i ] = sig .TypeParams ().At (i )
2544
2569
}
2545
2570
2546
- u := newUnifier (tparams , targs )
2571
+ u := newUnifier (tparams , make ([]types. Type , sig . TypeParams (). Len ()) )
2547
2572
for i , assignee := range targetType {
2548
- // reverseInferSignature instantiates the call site of a generic function
2549
- // based on the expected return types. Returns nil if inference fails or is invalid.
2550
- //
2551
- // targetType is the expected return types of the function after instantiation.
2573
+ // This unification does not check the constraints of the type parameters.
2552
2574
if ! u .unify (sig .Results ().At (i ).Type (), assignee , unifyMode (unifyModeExact )) {
2553
- return nil
2575
+ return nil , false
2554
2576
}
2555
2577
}
2556
2578
2557
- substs := []types.Type {}
2579
+ substs := make ( []types.Type , sig . TypeParams (). Len ())
2558
2580
for i := 0 ; i < sig .TypeParams ().Len (); i ++ {
2559
- if v := u .handles [sig .TypeParams ().At (i )]; v != nil && * v != nil {
2560
- substs = append (substs , * v )
2561
- } else {
2562
- substs = append (substs , nil )
2581
+ if sub := u .handles [sig .TypeParams ().At (i )]; sub != nil && * sub != nil {
2582
+ // Ensure the inferred subst is assignable to the type parameter's constraint.
2583
+ if ! assignableTo (* sub , sig .TypeParams ().At (i ).Constraint ()) {
2584
+ return nil , false
2585
+ }
2586
+ substs [i ] = * sub
2563
2587
}
2564
2588
}
2565
2589
2566
- return substs
2590
+ return substs , true
2567
2591
}
2568
2592
2569
- func (c * completer ) reverseInferredSubstitions (inf candidateInference , sig * types.Signature ) []types.Type {
2570
- targetType := []types.Type {}
2593
+ // resetExpectedType resets the inference and returns the previous
2594
+ // expected inference type.
2595
+ func (c * completer ) resetExpectedType (inf * candidateInference ) []types.Type {
2596
+ var targetType []types.Type
2571
2597
if inf .assignees != nil {
2572
2598
targetType = inf .assignees
2573
2599
inf .assignees = nil
2574
2600
} else if c .enclosingCompositeLiteral != nil && ! c .wantStructFieldCompletions () {
2575
2601
targetType = append (targetType , c .expectedCompositeLiteralType ())
2576
2602
} else if t := inf .objType ; t != nil {
2577
- inf .objType = nil
2578
2603
targetType = append (targetType , t )
2579
- } else {
2580
- return nil
2604
+ inf .objType = nil
2581
2605
}
2582
- return reverseInferSignature ( sig , targetType )
2606
+ return targetType
2583
2607
}
2584
2608
2585
2609
// reverseInferExpectedTypeParam uses inferences and completion parameters from the parent scope
2586
2610
// to instantiate the generalized signature of the call node.
2587
2611
//
2588
2612
// inf is expected to contain inferences based on the parent of the CallExpr node.
2589
2613
func (c * completer ) reverseInferExpectedTypeParam (inf candidateInference , expectedConstraint types.Type , typeParamIdx int , sig * types.Signature ) candidateInference {
2590
- if typeParamIdx >= sig .TypeParams ().Len () {
2591
- inf .objType = nil
2592
- inf .assignees = nil
2593
- return inf
2594
- }
2595
-
2596
- substs := c .reverseInferredSubstitions (inf , sig )
2597
- if substs != nil && len (substs ) > 0 {
2598
- if substs [typeParamIdx ] != nil {
2599
- inf .objType = substs [typeParamIdx ]
2600
- } else {
2601
- // default to the constraint if no viable substition
2602
- inf .objType = expectedConstraint
2603
- }
2604
- inf .typeName .wantTypeName = true
2605
- inf .typeName .isTypeParam = true
2614
+ substs , ok := reverseInferSignature (sig , c .resetExpectedType (& inf ))
2615
+ if ok && len (substs ) > 0 && substs [typeParamIdx ] != nil {
2616
+ inf .objType = substs [typeParamIdx ]
2617
+ } else {
2618
+ // Default to the constraint if no viable substition.
2619
+ inf .objType = expectedConstraint
2606
2620
}
2621
+ inf .typeName .wantTypeName = true
2622
+ inf .typeName .isTypeParam = true
2607
2623
return inf
2608
2624
}
2609
2625
@@ -2612,9 +2628,9 @@ func (c *completer) reverseInferExpectedTypeParam(inf candidateInference, expect
2612
2628
//
2613
2629
// inf is expected to contain inferences based on the parent of the CallExpr node.
2614
2630
func (c * completer ) reverseInferExpectedCallParam (inf candidateInference , node * ast.CallExpr , sig * types.Signature ) candidateInference {
2615
- substs := c . reverseInferredSubstitions ( inf , sig )
2616
- if substs == nil {
2617
- return inf
2631
+ substs , ok := reverseInferSignature ( sig , c . resetExpectedType ( & inf ) )
2632
+ if ! ok {
2633
+ return c . expectedCallParamType ( inf , node , sig )
2618
2634
}
2619
2635
2620
2636
for i := range substs {
@@ -2627,17 +2643,15 @@ func (c *completer) reverseInferExpectedCallParam(inf candidateInference, node *
2627
2643
if inst , ok := inst .(* types.Signature ); ok {
2628
2644
inf = c .expectedCallParamType (inf , node , inst )
2629
2645
2630
- // Interface type variants shouldn 't be candidates as arguments if the caller isn't
2631
- // explicitly instantiated
2646
+ // Interface variants can 't be passed if the caller isn't
2647
+ // explicitly instantiated. Completions must be exactly the interface type.
2632
2648
//
2633
2649
// func generic[T any](x T) T { return x }
2634
2650
// var x someInterface = generic(someImplementor{})
2635
2651
// ^^ wanted generic[someInterface] but got generic[someImplementor]
2636
2652
// When offering completions, add a conversion if necessary.
2637
2653
// generic(someInterface(someImplementor{}))
2638
- if types .IsInterface (inf .objType ) {
2639
- inf .convertibleTo = inf .objType
2640
- }
2654
+ inf .needsExactType = true
2641
2655
}
2642
2656
}
2643
2657
return inf
@@ -3124,12 +3138,6 @@ func (ci *candidateInference) candTypeMatches(cand *candidate) bool {
3124
3138
}
3125
3139
3126
3140
if ci .convertibleTo != nil && convertibleTo (candType , ci .convertibleTo ) {
3127
- // Candidate implements an interface, but needs explicit conversion to the interface
3128
- // type. This happens when passing arguments to a generic function.
3129
- if ci .objType != nil && types .IsInterface (ci .objType ) && ! types .Identical (candType , ci .convertibleTo ) {
3130
- cand .score *= 0.95 // should rank barely lower if it needs a conversion, even though it's perfectly valid
3131
- cand .convertTo = ci .objType
3132
- }
3133
3141
return true
3134
3142
}
3135
3143
@@ -3164,6 +3172,14 @@ func (ci *candidateInference) candTypeMatches(cand *candidate) bool {
3164
3172
cand .mods = append (cand .mods , takeDotDotDot )
3165
3173
}
3166
3174
3175
+ // Candidate matches, but isn't exactly identical to the expected type.
3176
+ // Apply a conversion to allow it to match.
3177
+ if ci .needsExactType && ! types .Identical (candType , expType ) {
3178
+ cand .convertTo = expType
3179
+ // Ranks barely lower if it needs a conversion, even though it's perfectly valid.
3180
+ cand .score *= 0.95
3181
+ }
3182
+
3167
3183
// Lower candidate score for untyped conversions. This avoids
3168
3184
// ranking untyped constants above candidates with an exact type
3169
3185
// match. Don't lower score of builtin constants, e.g. "true".
0 commit comments