# Enabling implicit member references with nested members

**URL:** <https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713>\
**Category:** Discussion\
**Created:** [January 17, 2020, 3:08pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713 "2020-01-17T15:08:22Z")\
**Posts on this page:** 17\
**Page:** 1

<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 17, 2020, 3:08pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/1 "2020-01-17T15:08:22Z")

</div>

I couldn't find any previous topics on this, so apologies if it has been discussed already.

Currently, the following code is invalid:

```swift
class C {
    static let zero = C(0)
    var x: Int

    init(_ x: Int) {
        self.x = x
    }

    var incremented: C {
        return C(x + 1)
    }
}

func f(_ c: C) {
    print(c.x)
}

f(.zero) // Prints '0'
f(.zero.incremented) // Error: Type of expression is ambiguous without more context

```

Is there anything technical that would keep this from working as expected? It seems like it would still be a simple syntactic transformation, but maybe I'm missing something...

If this were possible, I would expect the following as well:

```swift
f(.zero.x) // Error: Cannot convert value of type 'Int' to expected argument type 'C'
// (Currently, 'Type of expression is ambiguous without more context')

```

```swift
class C {
    static let b = B()

    var x = 0
}

class B {
    var c = C()
}

func f(_ c: C) {
    print(c.x)
}

f(.b.c) // Prints '0'
// (Currently, 'Error: Type of expression is ambiguous without more context')

```

This most commonly comes up for me when working with types like `UIColor` that provide transformation methods that return modified versions of the color, e.g.:

```swift
view.backgroundColor = .red.withAlphaComponent(0.5) // Not allowed!

```

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [January 17, 2020, 3:40pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/2 "2020-01-17T15:40:30Z")

</div>

I don‘t have any links for you but this was definitely discussed a lot of times.

---

<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 17, 2020, 3:47pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/3 "2020-01-17T15:47:10Z")

</div>

The only thread I could find that seemed relevant for a search on "'implicit member'" was [this one](https://forums.swift.org/t/ambiguous-type-incorrect/24616) which didn't really go anywhere other than raising the point that it should work through more than one level. Is there some other terminology under which this might have been discussed?

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [January 17, 2020, 3:56pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/4 "2020-01-17T15:56:58Z")

</div>

I think this is related: [My personal beef with leading-dot syntax](https://forums.swift.org/t/my-personal-beef-with-leading-dot-syntax/2055)

---

<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 17, 2020, 4:44pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/5 "2020-01-17T16:44:23Z")

</div>

"leading dot" does turn up some additional examples, thanks for that! That thread in particular, though, doesn't really seem to discuss the "multiple levels" at all. There is [this thread](https://forums.swift.org/t/referring-to-failable-initializer-with-leading-dot-syntax/13570) where @jrose offers a summary of the current rules around implicit member expressions:

> [@Referring to failable initializer with leading dot syntax](https://forums.swift.org/t/referring-to-failable-initializer-with-leading-dot-syntax/13570/2):
>
> The rule for leading dot syntax is that it will look in the _contextual type_ for a method/initializer/case whose result type is _identical_ to that type

However, I'm more interested in knowing whether there is a reason that that rule _can't_ be expanded to cover multiple levels of reference.

---

<div class="post-metadata">

**Author:** ![curt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/curt/32/1961_2.png) [@curt](https://forums.swift.org/u/curt)\
**Post date:** [January 17, 2020, 5:51pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/6 "2020-01-17T17:51:09Z")

</div>

> [@Jumhyn](#):
>
> However, I'm more interested in knowing whether there is a reason that that rule _can't_ be expanded to cover multiple levels of reference.

I'm afraid this is one of those things that seems straightforward but blows up in the general case.

What would be the scope in which to search for the chain of member references? The contextual type must be the type of the full expression. Is the root of the search also the contextual type?

If so, then the search is limited to chains starting and ending in that type. Unfortunately, the search space between those points is unbounded and grows exponentially. (In your second example, imagine that instead of mutual recursion from `C` → `B` → `C`, we had `C` → `B1` → `B2` → … `Bn` → `C`, and each `Bi` had a dozen properties.)

If the root of the search is not the contextual type, then the search space is substantially all of the global name space — static methods/properties, initializers, and all cases.

These problems can be avoided by limiting the length of the reference chains. The current implementation sets that limit at 1.

---

<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 17, 2020, 6:05pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/7 "2020-01-17T18:05:11Z")

</div>

What differentiates this from the case where I've written the contextual type explicitly, e.g., `print(C.b.c)`?

In other words, why does the compiler need to "search" at all, if we've written out the explicit chain of references, as opposed to just following the normal lookup rules _as though_ the contextual type had been written explicitly?

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [January 17, 2020, 6:05pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/8 "2020-01-17T18:05:34Z")

</div>

I think this is manageable, as long as the chain is required to begin and end with the same contextual type. There's a functional dependency implied by member lookup; we don't look up members until we have a type resolved to look into, so the search space shouldn't be expanded any more than it would normally be if we start from the contextual type of the entire expression.

---

<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 17, 2020, 7:26pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/9 "2020-01-17T19:26:56Z")

</div>

Good to know!

> [@Joe\_Groff](#):
>
> I think this is manageable, as long as the chain is required to begin and end with the same contextual type.

Does that imply that the proposed error in the original post is problematic? Or would we still be able to resolve the type of the member access as proposed and offer a more specific error than "type is ambiguous"?

> [@Jumhyn](#):
>
> ```swift
> f(.zero.x) // Error: Cannot convert value of type 'Int' to expected argument type
> 
> ```

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [January 17, 2020, 8:07pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/10 "2020-01-17T20:07:52Z")

</div>

@xedin might be able to comment on the diagnostic issue.

---

<div class="post-metadata">

**Author:** ![curt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/curt/32/1961_2.png) [@curt](https://forums.swift.org/u/curt)\
**Post date:** [January 17, 2020, 11:12pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/11 "2020-01-17T23:12:25Z")

</div>

Thanks for clarifying, @Joe_Groff.

---

<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, 2020, 12:45am UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/12 "2020-01-21T00:45:34Z")

</div>

> [@Jumhyn](#):
>
> f(.zero.incremented)

We have recently ported a diagnostic for this to the new diagnostic framework so if you try with master you'd get a following diagnostic:

```swift
error: cannot infer contextual base in reference to member 'zero'
f(.zero.incremented)
  ~^~~~

```

The problem is that result type of reference to `incremented` is disconnected from its base type because it's considered a regular member reference (references like `.zero` would connect base type and result type via equality constraint so it's possible to infer the base from result). That's why although result type of the chain could be inferred there is no way to propagate information in the opposite direction.

---

<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, 2020, 2:13am UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/13 "2020-01-21T02:13:04Z")

</div>

Would it be possible to look down through to the end of a chain of member accesses and impose the equality constraint between just the base type and the final result type, or is that infeasible?

---

<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, 2020, 8:42am UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/14 "2020-01-21T08:42:19Z")

</div>

I think it's possible and a right thing to do for chaining with contextual members. @Joe_Groff Do you think that this would require an evolution proposal or should we consider it a bug fix?

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [January 21, 2020, 6:43pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/15 "2020-01-21T18:43:43Z")

</div>

It seems appropriate for a (hopefully not very controversial) pitch and proposal. It'd be good to get attention to any possible technical or ergonomic issues with the feature.

---

<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, 2020, 6:58pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/16 "2020-01-21T18:58:01Z")

</div>

Sounds good, thanks @Joe_Groff. I can put together a pitch soon and see if the implementation seems like something I can take on.

---

<div class="post-metadata">

**Author:** ![joehodge3rd](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joehodge3rd/32/9848_2.png) [@joehodge3rd](https://forums.swift.org/u/joehodge3rd)\
**Post date:** [January 27, 2020, 10:59pm UTC](https://forums.swift.org/t/enabling-implicit-member-references-with-nested-members/32713/17 "2020-01-27T22:59:11Z")

</div>

Is this a problem requiring the prefix of the class be done explicitly? I’m all for explicit. Better readability, maintenance.... but how about a Modula 2 solution? The WITH bracketing?  
Example:

```
class C {
    static let zero = C(0)
    var x: Int

    init(_ x: Int) {
        self.x = x
    }

    var incremented: C {
        return C(x + 1)
    }
}

func f(_ c: C) {
    print(c.x)
}

```

**with** C  
f(.zero) // Prints '0'  
f(.zero.incremented) // Error: Type of expression is ambiguous without more context  
**end with**

———  
It’s a time saver without resorting to hard to maintain implicit usage, can be nested, and is explicit for readability. It also saves the compiler hunting for a match.  
Please excuse my inexperience with formatting in posts.
