Compiler bug? Adding explicit `any` to a protocol compositon type breaks the callers

I reference some AppKit code to give a real motivating use-case, but I think the issue is in the Swift compiler that ships with the Xcode 14 beta.

Compiler version: Apple Swift version 5.7 (swiftlang- clang-1400.0.16.2)

I have an AppKit app with modular panels that can be switched by a left side bar. Each panel has a different view controller class (derived from NSViewController or one of its sub-classes like NSSplitViewController). I also have two protocols MainPanelVCUp and MainPanelVCDown which describe the communication "upward" (from the panel up to the window) and "downward" (from the window down to the panel).

I express the type of these panels using a protocol composition, like so:

typealias MainPanelVC = MainPanelVCUp & MainPanelVCDown & NSViewController

This allows me to have an array of these panel view controllers, and treat them uniformally without coupling to their concrete types. Great!

I have a call site in one area that looks like so (abridged to focus on the relevant parts):

class RootViewController: NSSplitViewController {
    var mainVC: any MainPanelVC { ... }

    func replaceMainPanelVC(with newMainPanelVC: MainPanelVC) {
        // ... 
        // ...

This works great. .view and .removeFromParent() are called on the mainVC, which are methods that come from NSViewController.

However, if I modify my type alias to make the existential type explicit with the any keyword like so:

typealias MainPanelVC = any (MainPanelVCUp & MainPanelVCDown & NSViewController)

Then my call site breaks:

/.../MainSplitVC.swift:66:20: error: type of expression is ambiguous without more context
/.../MainSplitVC.swift:67:15: error: type of expression is ambiguous without more context

Is this a compiler bug? Or am I doing something wrong?

Oh, here's another clue:

If I use any explicit any in my type alias:

typealias MainPanelVC = any (MainPanelVCUp & MainPanelVCDown & NSViewController)

But remove it from my property's type annotation:

var mainVC: /* any */ MainPanelVC

Then we're green again.

So it looks like there's a bug in the interaction between any and typealias, is that right?

I tried to make a minimal verifiable example. I wasn't able to replicate the ambiguous expression error, but I did find a runtime crasher. I've filed an issue:

1 Like