Commit Graph

1 Commits

Author SHA1 Message Date
Alex Hoppen
b99ca7cae9 [CodeComplete] Show completions from constraint protocol extension
Consider the following example.

```swift
protocol FontStyle {}
struct FontStyleOne: FontStyle {}

extension FontStyle where Self == FontStyleOne {
    static var one: FontStyleOne { FontStyleOne() }
}

func foo<T: FontStyle>(x: T) {}
func case1() {
    foo(x: .#^COMPLETE^#)
}
```

With SE-0299 accepted, we should be suggesting `.one`.

For that, we need to consider the extension applied when performing the unresolved dot code completion with a primary archetype that conforms to `FontStyle`.

However, in the following case, which performs an unresolved dot completion on the same base type, we don't want to suggest `.one` because that would require `T == FontStyleOne`, which we can’t assume.

```swift
func case2<T: FontStyle>(x: T) {
    x.#^COMPLETE_2^#
}
```

Since the constraint system cannot tell us how it came up with the archetype, we need to apply a heuristic to differentiate between the two cases.

What seems to work fine in most cases, is to determine if `T` referes to a generic parameter that is visible from the decl context we are completing in (i.e. the decl context we are completing in is a child context of the context that `T` is declared in). If it is not, then `T` cannot be the type of a variable we are completing on. Thus, we are in the first case and we should consider all extensions of `FontStyle` because we can further specialize `T` by picking a more concrete type.
Otherwise `T` may be the type of a variable we are completing on and we should be conservative and only suggest those extensions whose requirements are fulfilled by `T`.

Since this is just a heuristic, there are some corner cases, where we aren’t suggesting constrainted extensions although we should. For example, in the following example the call to `testRecursive` doesn’t use `T` and we should thus suggest `one`. But by the rules described above we detect that `T` is accessible at the call and thus don’t apply extension whose requirements aren’t satisfied.

```swift
func testRecursive<T: FontStyle>(_ style: T) {
  testRecursive(.#^COMPLETE_RECURSIVE_GENERIC^#)
}
```

Similar completion issues also occurred without SE-0299 in more complicated, generic scenarios.

Resolves rdar://74958497 and SR-12973
2021-04-26 20:03:07 +02:00