# SE-0299 Extending Static Member Lookup in Generic Contexts

**URL:** <https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958>\
**Category:** Proposal Reviews\
**Created:** [January 18, 2021, 5:26pm UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958 "2021-01-18T17:26:00Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![pyrtsa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/pyrtsa/32/740_2.png) [@pyrtsa](https://forums.swift.org/u/pyrtsa)\
**Post date:** [January 20, 2021, 7:47am UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/21 "2021-01-20T07:47:14Z")

</div>

I'm with @jrose that the static extensions propagating to unrelated types is not pretty.

But since protocols can be, and are, used similarly to the cases of an `enum` to offer alternatives for the programmer to choose from, it would be nice if the way to pick from those options would work the same way at the call site as it does for enums. And having autocompletion for the "cases" of different protocol conformances would be a big win in developer approachability I think.

> [@wowbagger](#):
>
> After reading @jrose's first comment, I wonder if something like this might be a better solution:
> 
> ```swift
> extension View {
> public func toggleStyle(_ style: any ToggleStyle) -> some View
> }
> 
> extension any ToggleStyle {
> public static let `switch` = SwitchToggleStyle()
> }
> 
> Toggle("Wi-Fi", isOn: $isWiFiEnabled)
> .toggleStyle(.switch)
> 
> ```
> 
> Perform lookup on an existential, for its static members declared in an extension.

I don't think we need to (or should) have existentials for solving the problem of this proposal which is to have `toggleStyle(_:)` work as a generic function:

```swift
extension View {
    public func toggleStyle<S: ToggleStyle>(_ style: S) -> some View
}

```

I wonder if we could instead borrow the `some` syntax for marking the extensions that the implicit member lookup would be (only) extended with? Like all of this:

```swift
extension some ToggleStyle {
    public static let `default` = DefaultToggleStyle()
    public static var `switch`: SwitchToggleStyle { SwitchToggleStyle() }
    public static func checkbox(_ checkMarkStyle: CheckMarkStyle = .tick) -> CheckboxToggleStyle { ... }
}

Toggle("Wi-Fi", isOn: $isWiFiEnabled)
    .toggleStyle(.checkbox(.power))

```

But I'm not very happy about adding syntax for one-off needs like this, and I can't think what else `extension some T { ... }` would be good for. Or maybe developer approachability indeed makes it a need big enough!

---

<div class="post-metadata">

**Author:** ![dlbuckley](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dlbuckley/32/14986_2.png) [@dlbuckley](https://forums.swift.org/u/dlbuckley)\
**Post date:** [January 20, 2021, 9:29am UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/22 "2021-01-20T09:29:03Z")

</div>

My initial thoughts were 'finally', but after further consideration and reading the discussion I have to agree with the others that allowing static members where they make zero sense on the concrete type is going to lead to undesirable side effects.

> [@jrose](#):
>
> A possible workaround would be to lift the restriction on fully-constrained protocol extensions `where Self == SwitchToggleStyle` . It’d still be a choice to add that constraint, though, and like StaticMembers it wouldn’t be immediately obvious.

I do like this solution and I sympathise with the un-obvious nature of it. But I think as long as the error message is clear and descriptive enough as to why this restriction is in place, it's a possible avenue to a solution.

I'm wondering if we could go further with this idea and make it implicit based on the static member type? So building on the SwiftUI example:

```
extension ToggleStyle {
    public static var `default`: DefaultToggleStyle { get }
    public static var `switch`: SwitchToggleStyle { get }
    public static var checkbox: CheckboxToggleStyle { get }

    public static var description: String { get }
}

```

If the type (e.g `SwitchToggleStyle`) conforms to `ToggleStyle` then a restriction is placed upon its access to only be accessed from the top level protocol and that specific concrete type. Placing this restriction on the access would prevent cross type access in a generic context. This also wouldn't effect other static members used for other legitimate reasons which type isn't restricted by the containing protocol.

This would still work:

```
ToggleStyle.switch
SwitchToggleStyle.switch
ToggleStyle.description
SwitchToggleStyle.description
CheckboxToggleStyle.description
// etc.

```

But an error would be thrown when a user tried to do this:

```
SwitchToggleStyle.checkbox
CheckboxToggleStyle.switch
DefaultToggleStyle.switch
// etc.

```

I'm not entirely sure on the possibility of doing this, but since we have the concrete type and protocol information available as part of the member it seems like a valid solution and handles some of the concerns expressed so far.

---

<div class="post-metadata">

**Author:** ![Jon\_Hull](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_hull/32/678_2.png) [@Jon\_Hull](https://forums.swift.org/u/Jon_Hull)\
**Post date:** [January 20, 2021, 9:37am UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/23 "2021-01-20T09:37:44Z")

</div>

Something like this is _really_ needed. It is one of the issues I run into most often when designing API.

In addition to this, I think the ideal solution would be to allow static members which exist ONLY on the metatype:

```swift
protocol extension ToggleStyle {
    public static let `default` = DefaultToggleStyle()
    public static var `switch`:SwitchToggleStyle() {SwitchToggleStyle()}
    public static func checkbox(_ checkMarkStyle: CheckMarkStyle = .tick) -> CheckmarkToggleStyle
} 

```

Right now, I end up having to do the following a lot:

```swift
protocol AProtocol {
    func foo()
}

struct A:AProtocol {
    var definition:AProtocol

    init(_ definition:AProtocol) {
        self.definition = definition
    }

    func foo() {
        definition.foo()
    }

   static let myConcreteA = A(MyConcreteA())
   static let anotherA = A(AnotherA())
   ///etc...
}

```

---

<div class="post-metadata">

**Author:** ![michelf](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michelf/32/1180_2.png) [@michelf](https://forums.swift.org/u/michelf)\
**Post date:** [January 20, 2021, 12:16pm UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/24 "2021-01-20T12:16:03Z")

</div>

I somewhat dread the complexity of the solution by @jrose to the namespace pollution problem. Spelled in full it looks like this:

```swift
extension ToggleStyle where Self = DefaultToggleStyle {
   public static let `default` = DefaultToggleStyle()
}
extension ToggleStyle where Self == SwitchToggleStyle {
   public static let `switch` = SwitchToggleStyle()
}

```

This API is complicated to decipher.

* * *

What happens if a static member refers to `Self`? For instance:

```swift
extension ToggleStyle {
    static func printMe() { print(Self.self) } 
}

ToggleStyle.printMe() // what does this do?

```

Edit: the answer is that this particular static member will not be made available on `ToggleStyle` because it does not have a return type conforming to `ToggleStyle` (which would be used as `Self`). I somewhat missed this implication when reading the proposal. I'm not sure I like the availability to be dependent on the return type.

* * *

There's been some talk before about the concept of a "factory initializer" for classes and protocols. The idea is the initializer would be called on the base but is allowed to return an instance of a subclass. I think the pattern we have here is similar: adding static members on the base to make initialization convenient, without polluting types conforming to the protocol.

It could be written like this:

```swift
extension ToggleStyle {
   public factory let `default` = DefaultToggleStyle()
   public factory let `switch` = SwitchToggleStyle()
}

```

and the `factory` keyword would confer them a different behavior from `static` members. The behavior should be to make them available only on `ToggleStyle` and not on concrete types conforming to the protocol. This would make `ToggleStyle.default` valid while `DefaultToggleStyle.default` would be invalid.

(If we later introduce factory initializers, they could share that same behavior of only be available on the base.)

---

<div class="post-metadata">

**Author:** ![bzamayo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bzamayo/32/764_2.png) [@bzamayo](https://forums.swift.org/u/bzamayo)\
**Post date:** [January 20, 2021, 2:45pm UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/25 "2021-01-20T14:45:58Z")

</div>

SwiftUI is a leading motivation here but it has already shipped with the suboptimal initialiser based API. So, I don't really see a need to rush a compromised solution rather than 'do it properly'. And what @jrose highlighted is a pretty big deal IMO.

Obviously, SwiftUI isn't the only beneficiary — but everyone else has been making do to date also. Echoing other comments in this thread, there prolly needs to be new syntax to specify 'only make this static member available on the protocol type itself and not anything that conforms to it'.

When we've discussed this on the forum before, I always found the idea of `extension Protocol.Type { ... }` to be a logical spelling of this. But I'm not personally wedded to it.

---

<div class="post-metadata">

**Author:** ![slazarus](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/slazarus/32/7912_2.png) [@slazarus](https://forums.swift.org/u/slazarus)\
**Post date:** [January 21, 2021, 12:21am UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/27 "2021-01-21T00:21:45Z")

</div>

> [@jrose](#):
>
> > [@anandabits](#):
> >
> > Would you feel better about it if it was limited to extensions that constrain `Self` to a concrete type?
> 
> Better, if not completely happy. It’s still a long spelling and still doesn’t quite match the intent. Generic adopters would also need the `where` clause on methods instead until we get parameterized extensions, making it just a little extra janky.

Regarding requiring extensions like this to constrain `Self` to a specific type, we believe that that issue is orthogonal to this proposal. Such extensions are already allowed in the language so it’s unclear how this behavior would be prohibited without being rather unintuitive. It seems strange that adding the constraint on `Self` would be required for leading dot syntax to function considering that the constraint and leading dot syntax are completely disconnected from one another conceptually.

---

<div class="post-metadata">

**Author:** ![ricketson](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ricketson/32/8365_2.png) [@ricketson](https://forums.swift.org/u/ricketson)\
**Post date:** [January 21, 2021, 12:34am UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/28 "2021-01-21T00:34:49Z")

</div>

> [@"bzamayo](#):
>
> SwiftUI is a leading motivation here but it has already shipped with the suboptimal initialiser based API. So, I don't really see a need to rush a compromised solution rather than 'do it properly'. And what @jrose highlighted is a pretty big deal IMO.

We agree on the ultimate goal to do it properly, but it sounds like we disagree on the tradeoffs of what is being proposed here.

Here is our thinking, beginning with the technical considerations:

- **It is already possible to declare static properties and methods on protocols today** , which is not inherently bad and should not be restricted (and cannot, for source compatibility reasons).
- **The specific change proposed here is narrowly-scoped** , only extending member lookup in certain generic contexts. This narrow scope was chosen, based on community feedback, to maintain maximum flexibility to explore better solutions in the future.

We have not seen much feedback yet arguing that this change, considered on its own, should be rejected because it would be harmful. On the contrary, several have noted that this feels like a natural extension of our existing lookup rules.

Most of the feedback is specifically about whether it is wise for a framework like SwiftUI to take advantage of this new change to solve problems like the style example. Our considerations related to that:

- **There is agreement in this thread that this is a problem worth solving** , and we have received enough real-world feedback to consider it a serious problem.
- **There is also agreement on how the solution should look _at the call site_.** It's important to note that the debate is solely centered around the declaration site, which is important, but to a lesser degree.
- **The declaration site can change in the future** , without impacting source compatibility or introducing warnings. Frameworks like SwiftUI have several tools available to handle this, including deprecation & replacement, emitting symbols into clients so they can be revised later, etc. In other words, we're not designing ourselves into a corner.

Finally, as noted earlier, we still plan to pursue a "proper" solution in the future. However, based on responses to this proposal, there also does not seem to be complete agreement on what that solution could be, so it will require more investigation. Some of those solutions, like protocol metatype extensions, also require much deeper thought into core aspects of the design of the language.

So putting that all together, our conclusions are:

- **We can fix a serious problem _today_** , with minimal language impact and with support for the ideal call-site syntax.
- **We can maintain flexibility to implement a proper solution in the future.**
- **Frameworks like SwiftUI can migrate to future solutions in a source-compatible way** , with minimal-to-zero long-term impact on its API.

We believe this is a beneficial, viable path forward.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [January 21, 2021, 12:57am UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/29 "2021-01-21T00:57:25Z")

</div>

The good is the enemy of the perfect, and the perfect is the enemy of the good. For me, this change means we'll see a proliferation of the "imperfect" idiom and the drawbacks that entails, and it may take longer to get the actual desired feature (which is related to features like nesting types inside protocols). It's a trade-off for sure.

---

<div class="post-metadata">

**Author:** ![xedin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xedin/32/309_2.png) [@xedin](https://forums.swift.org/u/xedin)\
**Post date:** [January 21, 2021, 2:07am UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/30 "2021-01-21T02:07:11Z")

</div>

Yes, this is definitely a trade-off. Our reasoning is that reward of more expressive/concise call site out-weights having to deal with extensions for the API authors because that's usually M-N relationship where M is significantly smaller than N in the number of authors and users.

---

<div class="post-metadata">

**Author:** ![michelf](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michelf/32/1180_2.png) [@michelf](https://forums.swift.org/u/michelf)\
**Post date:** [January 21, 2021, 3:04am UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/31 "2021-01-21T03:04:47Z")

</div>

> [@ricketson](#):
>
> **There is also agreement on how the solution should look _at the call site_ .** It's important to note that the debate is solely centered around the declaration site, which is important, but to a lesser degree.

I think library writers sometime have a tendency to downplay the importance of clean declarations. As long as the call site looks clean it's good right? But when something goes wrong people will refer to the declaration, and if the declaration is complex it makes troubleshooting more complex.

With a `where` clause, to understand how `.toggleStyle(.switch)` works you have to understand what a conditional declaration with `where` does, and then you what `Self` is referring to within a protocol, and then have some imagination to figure out what's the point of having this `where` in the first place. That's a mouthful of concepts to teach in one go. (Technically you don't have to understand it all, but you have to understand it enough to know you can ignore it.)

> [@ricketson](#):
>
> We have not seen much feedback yet arguing that this change, considered on its own, should be rejected because it would be harmful.

I'll bite. I think it's slightly harmful, but I had to think about what I wrote in my last post before realizing that. Let me know if I got something wrong in my examples; I'm extrapolating from what I understood in the proposal.

I find it very surprising that some static properties can be called on the protocol and others can't. Consider this:

```swift
protocol P {
   static var number { get }
}
struct S: P {
   static let number = 1
}
extension P {
   static var a: Int { 1 }
   static var b: Int { Self.number }
   static var c: S { S() }
   static let d = S()
}

let x = P.a // error, can't infer Self
let y = P.b // error, can't infer Self
let z = P.c // ok, Self inferred to be return type S
let w = P.d // ok, Self inferred to be return type S

```

Whether the static member is available on the protocol depends on its return type. I don't think that's very sound. What's actually preventing them from being called is the impossibility to infer a `Self`.

It's a funny thing is that you can make the `x` and `y` line above compile by adding this:

```swift
extension Int: P {
   var number: Int { 2 }
}
let x = P.a // ok, can infer Self to Int now
let y = P.b // ok, can infer Self to Int now

```

In practice that means that in contexts where a protocol conformance is visible members will be callable directly on `P` and in contexts where the conformance is not visible it won't.

And by conforming `Int` to `P`, the behaviour of `b` (which uses `Self`) becomes a bit surprising:

```swift
P.b // returns 2; Self inferred to Int
Int.b // returns 2; Self inferred to Int
S.b // returns 1; Self inferred to S

```

Here `Int` becomes the default `Self` when called on `P` simply because it's the return type, but the returned value varies depending on `Self` and makes little sense when called on the protocol itself. Think this is a far fetched scenario?

```swift
FixedWidthInteger.bitWidth // Self inferred to Int

```

That's the only concrete example I could find, but there might be others.

What would be a better rule for calling things on a protocol is that they don't use `Self` at all. We're only introducing this strange inference of `Self` because there's no syntax to make the declaration not require a `Self`. But I think a `@notUsingSelf` attribute would be better for that than the proposed inference of based on the return type.

---

<div class="post-metadata">

**Author:** ![xedin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xedin/32/309_2.png) [@xedin](https://forums.swift.org/u/xedin)\
**Post date:** [January 21, 2021, 3:32am UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/32 "2021-01-21T03:32:48Z")

</div>

The proposal intentionally doesn't allow for references with explicit protocol metatype base, because the behavior would be confusing (as determined during discussion in the pitch). We have restricted the inference to leading-dot syntax which, in our opinion, would get the most benefit and remove the confusion that same call site syntax has different behavior for concrete vs. generic functions.

---

<div class="post-metadata">

**Author:** ![michelf](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michelf/32/1180_2.png) [@michelf](https://forums.swift.org/u/michelf)\
**Post date:** [January 21, 2021, 3:59am UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/33 "2021-01-21T03:59:57Z")

</div>

Isn't this one more inconsistency then? Until now this syntax:

```swift
let x = Type.member

```

has been pretty much equivalent to this when the member returns a `Type`:

```swift
let x: Type = .member

```

But for some reason, for static members of a protocol type only the later will work.

You can change all my examples to use the second form and they still behave the same.

Except for the last one. That rule successfully scrubs the `FixedWidthInteger.bitWidth` example because of the protocol's `Self`-requirement. But what happens with this?

```swift
func squared<T: FixedWidthInteger>(_ x: T) -> T? { ... }
let squaredBitWidth = squared(.bitWidth)

```

---

<div class="post-metadata">

**Author:** ![xedin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xedin/32/309_2.png) [@xedin](https://forums.swift.org/u/xedin)\
**Post date:** [January 21, 2021, 4:11am UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/34 "2021-01-21T04:11:51Z")

</div>

> [@michelf](#):
>
> Isn't this one more inconsistency then?

Yes, (which I advocated) could be lifted, but people disagreed on that regard and we have decided to go with the most impactful situations only.

Edit: I realized that I didn't explain what it would take to lift this inconsistency within current rules - we'd have to require result type of a member to conform to a protocol and do an implicit transformation to replace protocol with its conforming type so `P.bar` becomes `Foo.bar`.

> [@michelf](#):
>
> But for some reason, for static members of a protocol type only the later will work.

This is outlined in the pitch too. The reason for this behavior is rooted in the language itself. To call something you'd need to have a witness, protocol requirements are witnessed by conforming types. that's why `let _: Foo = .member` syntax works, since the base is actually `Foo.member` (because base has to be equal to result), and `let _: Foo = P.member` doesn't because `P` doesn't have a witness to call. Fixing that requires re-thinking protocols and would be a much larger feature, but having this proposal accepted wouldn't impede that work in any way. The only thing that would need to happen is lifting conformance requirement from a result type of a member which is a completely transparent change.

> [@michelf](#):
>
> But what happens with this?

If the result of `.bitWidth` is a concrete type that conforms to `FixedWidthInteger` this should type-check. Edit: Note that member has to be static to be accessible through metatype, which `bitWidth` isn’t.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [January 21, 2021, 1:55pm UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/35 "2021-01-21T13:55:35Z")

</div>

> [@michelf](#):
>
> Isn't this one more inconsistency then? Until now this syntax:
> 
> ```swift
> let x = Type.member
> 
> ```
> 
> has been pretty much equivalent to this when the member returns a `Type` :
> 
> ```swift
> let x: Type = .member
> 
> ```

This proposal doesn't break that model. I think that the original pitch has possibly caused some confusion, since it _did_ allow for expressions of the form `P.member`, but IMO that's not the best way to think about this feature.

Under this proposal, when we write:

```swift
.toggleStyle(.switch)

```

the argument type is `SwitchToggleStyle`, meaning that the _explicit_ version of this (partial) expression is:

```swift
.toggleStyle(SwitchToggleStyle.switch)

```

There's _nothing new_ conceptually here with regards to how implicit member syntax works, we're just improving the compiler's ability to infer the base type through generic constraints\*. This is also why I object to the conforms-to requirement for the first member—I think it's much simpler to think about this feature just in terms of improving inference rules.

On that note, something else comes to mind: does the following work?

```swift
protocol P {}
extension P {
    static var someS: S { S() }
}

struct S: P {
    var r: R { R() }
}

struct R: P {}

func takesP<T: P>(_: T) {}

takesP(.someS.r)

```

If so, what is the actual base here, `S` or `R`?

\*: I suppose there's a _bit_ of nuance since, presumably, if `SwitchToggleStyle` declared its own `switch` member that shadowed the declaration the explicit version would use the `switch` from `SwitchToggleStyle` and not the `switch` from `ToggleStyle`.

---

<div class="post-metadata">

**Author:** ![xedin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xedin/32/309_2.png) [@xedin](https://forums.swift.org/u/xedin)\
**Post date:** [January 21, 2021, 4:11pm UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/36 "2021-01-21T16:11:59Z")

</div>

> [@Jumhyn](#):
>
> On that note, something else comes to mind: does the following work?

Everything works according to the rules of leading dot syntax so the result has to be equal to the base plus the conformance requirement, so switching base like that wouldn't be allowed.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [January 21, 2021, 4:38pm UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/37 "2021-01-21T16:38:22Z")

</div>

> [@xedin](#):
>
> Everything works according to the rules of leading dot syntax so the result has to be equal to the base plus the conformance requirement, so switching base like that wouldn't be allowed.

Hmm as far as I can tell, all of these are satisfied in the above example—am I missing something? My expectation would be that the base is `R`, result type of `someS` access is `S` which conforms to `P`, and result type of `r` access is `R`, which is equal to the base.

---

<div class="post-metadata">

**Author:** ![xedin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xedin/32/309_2.png) [@xedin](https://forums.swift.org/u/xedin)\
**Post date:** [January 21, 2021, 4:50pm UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/38 "2021-01-21T16:50:57Z")

</div>

> [@Jumhyn](#):
>
> Hmm as far as I can tell, all of these are satisfied in the above example—am I missing something?

The base is going to be `S` since that's the result of the member `.someS`, it's slightly different from leading dot syntax because it propagates types forward instead of backward because there is no contextual information besides conformance requirement.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [January 21, 2021, 5:14pm UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/39 "2021-01-21T17:14:22Z")

</div>

Ah, I see—so in addition to the first member conforming to the protocol, the base must be equal to _both_ the first member type and the final member type?

IMO, this proposal does not fulfill one of its stated goals, to "make leading dot syntax behave consistently for all possible base types."

I think the status quo of "leading dot syntax doesn't work in generic contexts" is a better resting place than "leading dot syntax works in generic contexts but only if the first member and the last member have the same type" until we can address this more holistically.

---

<div class="post-metadata">

**Author:** ![xedin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xedin/32/309_2.png) [@xedin](https://forums.swift.org/u/xedin)\
**Post date:** [January 21, 2021, 5:20pm UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/40 "2021-01-21T17:20:17Z")

</div>

I honestly don't know what is the argument here - the result type is effectively a hole in a generic context which supposed to conform a some protocol or protocol composition. It's a requirement of a leading dot syntax that base has to be equal to result type. In non-generic cases type is inferred from the context (e.g. parameter type of a current overload) and propagated to result and then down to the base and lookup is made from there; if result of the chain turns out to be different from contextually inferred one - expression doesn't type-check. The only difference here is that the base comes from the first member instead of from context because that's the only possible place where it be inferred from to make forward progress.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [January 21, 2021, 5:36pm UTC](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958/41 "2021-01-21T17:36:59Z")

</div>

> [@xedin](#):
>
> The only difference here is that the base comes from the first member instead of from context because that's the only possible place where it be inferred from to make forward progress.

But that's a limitation of the current implementation, not a logical limitation of the information available to the compiler. In the example above, when the compiler encounters:

```swift
takesP(.someS.r)

```

it knows the following:

- `takesP` will accept as an argument some concrete type conforming to `P`.
- Every concrete type conforming to `P` has a static member `someS` of type `S`.
- Every instance of `S` has a member `r` of type `R`.

Today, the compiler is unable to make forward progress because it cannot leave the base type partially unresolved while it works on later members in the chain, but as the programmer I can reason about that expression perfectly well:

1. There will eventually be _some_ type at the implicit base, equal to whatever we get at the end of the chain.
2. Let's skip over that for now and fill it in later if possible.
3. Even though we don't know the exact type, we know that, due to `P` conformance, `.someS` will produce a value of type `S`.
4. Now, `.r` will produce a value of type `R`.
5. That's the end of the chain, so try to go back and fill in `R` at the base.
6. `R` conforms to `P`, so everything works, and the expression type checks!

Is any logical step here _invalid_?

[Previous page](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958.md?page=1)

[Next page](https://forums.swift.org/t/se-0299-extending-static-member-lookup-in-generic-contexts/43958.md?page=3)
