@@ -2394,86 +2394,67 @@ func (c *completer) fakeObj(T types.Type) *types.Var {
2394
2394
return types .NewVar (token .NoPos , c .pkg .GetTypes (), "" , T )
2395
2395
}
2396
2396
2397
- // anyCandType reports whether f returns true for any candidate type
2398
- // derivable from c. For example, from "foo" we might derive "&foo",
2399
- // and "foo()".
2400
- func (c * candidate ) anyCandType (f func (t types.Type , addressable bool ) bool ) bool {
2401
- if c .obj == nil || c .obj .Type () == nil {
2402
- return false
2403
- }
2404
-
2405
- objType := c .obj .Type ()
2406
-
2407
- if f (objType , c .addressable ) {
2408
- return true
2409
- }
2410
-
2411
- // If c is a func type with a single result, offer the result type.
2412
- if sig , ok := objType .Underlying ().(* types.Signature ); ok {
2413
- if sig .Results ().Len () == 1 && f (sig .Results ().At (0 ).Type (), false ) {
2414
- // Mark the candidate so we know to append "()" when formatting.
2415
- c .mods = append (c .mods , invoke )
2397
+ // derivableTypes iterates types you can derive from t. For example,
2398
+ // from "foo" we might derive "&foo", and "foo()".
2399
+ func derivableTypes (t types.Type , addressable bool , f func (t types.Type , addressable bool , mod typeModKind ) bool ) bool {
2400
+ switch t := t .Underlying ().(type ) {
2401
+ case * types.Signature :
2402
+ // If t is a func type with a single result, offer the result type.
2403
+ if t .Results ().Len () == 1 && f (t .Results ().At (0 ).Type (), false , invoke ) {
2416
2404
return true
2417
2405
}
2418
- }
2419
-
2420
- var (
2421
- seenPtrTypes map [types.Type ]bool
2422
- ptrType = objType
2423
- ptrDepth int
2424
- )
2425
-
2426
- // Check if dereferencing c would match our type inference. We loop
2427
- // since c could have arbitrary levels of pointerness.
2428
- for {
2429
- ptr , ok := ptrType .Underlying ().(* types.Pointer )
2430
- if ! ok {
2431
- break
2432
- }
2433
-
2434
- ptrDepth ++
2435
-
2436
- // Avoid pointer type cycles.
2437
- if seenPtrTypes [ptrType ] {
2438
- break
2439
- }
2440
-
2441
- if _ , named := ptrType .(* types.Named ); named {
2442
- // Lazily allocate "seen" since it isn't used normally.
2443
- if seenPtrTypes == nil {
2444
- seenPtrTypes = make (map [types.Type ]bool )
2445
- }
2446
-
2447
- // Track named pointer types we have seen to detect cycles.
2448
- seenPtrTypes [ptrType ] = true
2406
+ case * types.Array :
2407
+ // Try converting array to slice.
2408
+ if f (types .NewSlice (t .Elem ()), false , takeSlice ) {
2409
+ return true
2449
2410
}
2450
-
2451
- if f (ptr .Elem (), false ) {
2452
- for i := 0 ; i < ptrDepth ; i ++ {
2453
- // Mark the candidate so we know to prepend "*" when formatting.
2454
- c .mods = append (c .mods , dereference )
2455
- }
2411
+ case * types.Pointer :
2412
+ if f (t .Elem (), false , dereference ) {
2456
2413
return true
2457
2414
}
2458
-
2459
- ptrType = ptr .Elem ()
2460
2415
}
2461
2416
2462
2417
// Check if c is addressable and a pointer to c matches our type inference.
2463
- if c .addressable && f (types .NewPointer (objType ), false ) {
2464
- // Mark the candidate so we know to prepend "&" when formatting.
2465
- c .mods = append (c .mods , reference )
2418
+ if addressable && f (types .NewPointer (t ), false , reference ) {
2466
2419
return true
2467
2420
}
2468
2421
2469
- if array , ok := objType .Underlying ().(* types.Array ); ok {
2470
- if f (types .NewSlice (array .Elem ()), false ) {
2471
- c .mods = append (c .mods , takeSlice )
2422
+ return false
2423
+ }
2424
+
2425
+ // anyCandType reports whether f returns true for any candidate type
2426
+ // derivable from c. It searches up to three levels of type
2427
+ // modification. For example, given "foo" we could discover "***foo"
2428
+ // or "*foo()".
2429
+ func (c * candidate ) anyCandType (f func (t types.Type , addressable bool ) bool ) bool {
2430
+ if c .obj == nil || c .obj .Type () == nil {
2431
+ return false
2432
+ }
2433
+
2434
+ const maxDepth = 3
2435
+
2436
+ var searchTypes func (t types.Type , addressable bool , mods []typeModKind ) bool
2437
+ searchTypes = func (t types.Type , addressable bool , mods []typeModKind ) bool {
2438
+ if f (t , addressable ) {
2439
+ if len (mods ) > 0 {
2440
+ newMods := make ([]typeModKind , len (mods )+ len (c .mods ))
2441
+ copy (newMods , mods )
2442
+ copy (newMods [len (mods ):], c .mods )
2443
+ c .mods = newMods
2444
+ }
2472
2445
return true
2473
2446
}
2447
+
2448
+ if len (mods ) == maxDepth {
2449
+ return false
2450
+ }
2451
+
2452
+ return derivableTypes (t , addressable , func (t types.Type , addressable bool , mod typeModKind ) bool {
2453
+ return searchTypes (t , addressable , append (mods , mod ))
2454
+ })
2474
2455
}
2475
2456
2476
- return false
2457
+ return searchTypes ( c . obj . Type (), c . addressable , make ([] typeModKind , 0 , maxDepth ))
2477
2458
}
2478
2459
2479
2460
// matchingCandidate reports whether cand matches our type inferences.
0 commit comments