You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[CodeComplete] Show completions from constrained 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
0 commit comments