"Expression failed to parse, unknown error" only in Xcode 10.2.1 playgrounds

Hello!
I was experimenting with the VIPER architecture in a Xcode playground, and I encountered this error:
Expression failed to parse, unknown error

The strange thing is that the code builds successfully inside an Xcode project. Did I find a bug?
Here's the code (I tried on Xcode 10.2.1 only):


protocol VIPERVC: UIViewController {
    associatedtype Interactor: VIPERInteractor
        where Interactor.Presenter.ViewController == Self
    
    static var storyboardName: String { get }
    static var storyboardIdentifier: String { get }
    
    var interactor: Interactor! { get set }
}

extension VIPERVC {
    typealias Presenter = Interactor.Presenter
}

protocol VIPERInteractor {
    associatedtype Presenter: VIPERPresenter
        where Presenter.ViewController.Interactor == Self
    
    init(_ repo: VIPEREntityRepository)
    
    var presenter: Presenter! { get set }
}

extension VIPERInteractor {
    typealias ViewController = Presenter.ViewController
}

protocol VIPERPresenter {
    associatedtype ViewController: VIPERVC
        where ViewController.Interactor.Presenter == Self
    
    init(_ vc: ViewController)
    
    var vc: ViewController! { get set }
}

extension VIPERPresenter {
    typealias Interactor = ViewController.Interactor
}

class TestEntity {
    func provideString() -> String {
        return "TestString"
    }
}

struct VIPEREntityRepository {
    private let testEntity = TestEntity()
    
    init() { }
    
    func provideEntity<T>() -> T {
        let mirror = Mirror(reflecting: self)
        guard let entity = mirror.children.first(where: { $0.value is T })
            else {
                let message = "Dependency with type: \(T.self) not found.\nAvailable dependencies:\n"
                let dependencies = mirror.children.map { "\($0.label ?? "nil"): \(type(of: $0.value))" }
                fatalError(message + dependencies.joined(separator: "\n")) }
        return entity.value as! T
    }
}

class TestViewController: UIViewController, VIPERVC {
    class var storyboardName: String { return "TestStoryboard" }
    class var storyboardIdentifier: String { return "TestVC" }
    
    let mainLabel: UILabel = UILabel(frame: .init(origin: .zero, size: .init(width: 300, height: 60)))
    
    typealias Interactor = TestInteractor
    
    var interactor: TestInteractor! = nil
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(mainLabel)
    }
    
    func pressButton() {
        interactor.retrieveString()
    }
}

class TestInteractor: VIPERInteractor {
    typealias Presenter = TestPresenter
    
    var presenter: TestPresenter! = nil
    
    private let repo: VIPEREntityRepository
    private lazy var entity: TestEntity = repo.provideEntity()
    
    required init(_ repo: VIPEREntityRepository) {
        self.repo = repo
    }
    
    func retrieveString() {
        let string = entity.provideString()
        presenter.updateLabel(withString: string)
    }
}

class TestPresenter: VIPERPresenter {
    typealias ViewController = TestViewController
    
    required init(_ vc: ViewController) {
        self.vc = vc
    }
    
    unowned var vc: TestViewController!
    
    func updateLabel(withString str: String) {
        vc.mainLabel.text = str
    }
}

struct ModuleBuilder<VC: VIPERVC> {
    
    func build(_ repo: VIPEREntityRepository) -> VC {
        //        let storyboard = UIStoryboard(name: VC.storyboardName, bundle: .main)
        //        let vc = storyboard.instantiateViewController(withIdentifier: VC.storyboardIdentifier) as! VC
        let vc = VC.init()
        
        var interactor = VC.Interactor(repo)
        var presenter = VC.Presenter(vc)
        
        vc.interactor = interactor
        interactor.presenter = presenter
        presenter.vc = vc
        
        return vc
    }
}

Are you using a Swift 5.1 language feature? Playgrounds supports up to 5.0 at this point.

I'm not using any Swift 5.1 feature, nor even Swift 5.0.
This code compiles successfully in Xcode 10.2.1, set to both Swift 5 or Swift 4.2, it doesn't work just in the playground.

Does Playgrounds highlight where it is failing to parse?

No, it doesn't. The error message I posted above appears in the "console" area in the bottom, and also the "Errors" panel on the left sidebar doesn't show anything.

I created a demo project on Github to help find out what's wrong:

This project includes a working app that uses the code that triggers the playground error, and a playground file that misbehaves on the same code, producing the unknown error.

I pasted your code into a new Playground in the current shipping version of Playgrounds and (after adding import UIKit) it compiled without error. Are you using the beta?

1 Like

I'm not using anything related to the latest Beta, I've installed them in the past weeks but had to remove everything from my current machine. I just double checked everything:
Xcode 10.2.1 (10E1001)
both Swift 4.2 and Swift 5

I looked into the DiagnosticReports folder and I found the following log with the correct timing of my last try, I'm not able to read it though.

Process:               lldb-rpc-server [7305]
Path:                  /Applications/Xcode.app/Contents/SharedFrameworks/LLDBRPC.framework/Versions/A/Resources/lldb-rpc-server
Identifier:            lldb-rpc-server
Version:               2
Code Type:             X86-64 (Native)
Parent Process:        Xcode [7279]
Responsible:           lldb-rpc-server [7305]
User ID:               502

Date/Time:             2019-07-01 14:04:47.674 +0200
OS Version:            Mac OS X 10.14.5 (18F132)
Report Version:        12
Bridge OS Version:     3.5 (16P5125)
Anonymous UUID:        EE5EBBB8-BD54-DF23-19B2-269F1C9CFF77


Time Awake Since Boot: 20000 seconds

System Integrity Protection: disabled

Crashed Thread:        7  <lldb.process.internal-state(pid=7421)>

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [7305]

VM Regions Near 0:
--> 
    __TEXT                 000000010499d000-0000000104a1f000 [  520K] r-x/rwx SM=COW  /Applications/Xcode.app/Contents/SharedFrameworks/LLDBRPC.framework/Versions/A/Resources/lldb-rpc-server

Thread 0:: Connection::RunLoop() packet reading thread  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x00007fff71c2cef2 read + 10
1   lldb-rpc-server               	0x00000001049a74b1 rpc_common::RPCConnectionSocket::Read(std::__1::basic_string<unsigned char, std::__1::char_traits<unsigned char>, std::__1::allocator<unsigned char> >&, bool) + 173
2   lldb-rpc-server               	0x00000001049adfba rpc_common::Connection::ReceivePacket(rpc_common::RPCPacket&) + 148
3   lldb-rpc-server               	0x00000001049adae7 rpc_common::Connection::RunLoop() + 203
4   lldb-rpc-server               	0x00000001049ea3f7 main + 471
5   libdyld.dylib                 	0x00007fff71af63d5 start + 1

Thread 1:
0   libsystem_pthread.dylib       	0x00007fff71ce93f0 start_wqthread + 0

Thread 2:
0   libsystem_kernel.dylib        	0x00007fff71c2b22a mach_msg_trap + 10
1   libsystem_kernel.dylib        	0x00007fff71c2b76c mach_msg + 60
2   com.apple.CoreFoundation      	0x00007fff45bc2bee __CFRunLoopServiceMachPort + 328
3   com.apple.CoreFoundation      	0x00007fff45bc215c __CFRunLoopRun + 1612
4   com.apple.CoreFoundation      	0x00007fff45bc18be CFRunLoopRunSpecific + 455
5   com.apple.CoreFoundation      	0x00007fff45bc16d2 CFRunLoopRun + 40
6   com.apple.DebugSymbols        	0x00007fff5a83bd2b SpotlightQueryThread(void*) + 475
7   libsystem_pthread.dylib       	0x00007fff71cea2eb _pthread_body + 126
8   libsystem_pthread.dylib       	0x00007fff71ced249 _pthread_start + 66
9   libsystem_pthread.dylib       	0x00007fff71ce940d thread_start + 13

Thread 3:: RPC packet thread for client tid 000512c4 (332484)
0   libsystem_kernel.dylib        	0x00007fff71c2e86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff71ced56e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6ed28a0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   lldb-rpc-server               	0x00000001049b1102 Packets::ReadThread() + 222
4   lldb-rpc-server               	0x00000001049b101f Packets::RunReadThread(void*) + 9
5   libsystem_pthread.dylib       	0x00007fff71cea2eb _pthread_body + 126
6   libsystem_pthread.dylib       	0x00007fff71ced249 _pthread_start + 66
7   libsystem_pthread.dylib       	0x00007fff71ce940d thread_start + 13

Thread 4:: RPC packet thread for client tid 00051049 (331849)
0   libsystem_kernel.dylib        	0x00007fff71c2e86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff71ced56e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6ed28a0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   lldb-rpc-server               	0x00000001049b1102 Packets::ReadThread() + 222
4   lldb-rpc-server               	0x00000001049b101f Packets::RunReadThread(void*) + 9
5   libsystem_pthread.dylib       	0x00007fff71cea2eb _pthread_body + 126
6   libsystem_pthread.dylib       	0x00007fff71ced249 _pthread_start + 66
7   libsystem_pthread.dylib       	0x00007fff71ce940d thread_start + 13

Thread 5:: RPC packet thread for client tid 000512c3 (332483)
0   libsystem_kernel.dylib        	0x00007fff71c2e86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff71ced56e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6ed28a0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   lldb-rpc-server               	0x00000001049b1102 Packets::ReadThread() + 222
4   lldb-rpc-server               	0x00000001049b101f Packets::RunReadThread(void*) + 9
5   libsystem_pthread.dylib       	0x00007fff71cea2eb _pthread_body + 126
6   libsystem_pthread.dylib       	0x00007fff71ced249 _pthread_start + 66
7   libsystem_pthread.dylib       	0x00007fff71ce940d thread_start + 13

Thread 6:: <lldb.process.gdb-remote.async>
0   libsystem_kernel.dylib        	0x00007fff71c2e86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff71ced56e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6ed28a0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   com.apple.LLDB.framework      	0x000000010c0401ab lldb_private::Listener::GetEventInternal(lldb_private::Timeout<std::__1::ratio<1l, 1000000l> > const&, lldb_private::Broadcaster*, lldb_private::ConstString const*, unsigned int, unsigned int, std::__1::shared_ptr<lldb_private::Event>&) + 235
4   com.apple.LLDB.framework      	0x000000010c0404c3 lldb_private::Listener::GetEvent(std::__1::shared_ptr<lldb_private::Event>&, lldb_private::Timeout<std::__1::ratio<1l, 1000000l> > const&) + 33
5   com.apple.LLDB.framework      	0x000000010c1bcd46 lldb_private::process_gdb_remote::ProcessGDBRemote::AsyncThread(void*) + 262
6   com.apple.LLDB.framework      	0x000000010c26f93b lldb_private::HostNativeThreadBase::ThreadCreateTrampoline(void*) + 105
7   libsystem_pthread.dylib       	0x00007fff71cea2eb _pthread_body + 126
8   libsystem_pthread.dylib       	0x00007fff71ced249 _pthread_start + 66
9   libsystem_pthread.dylib       	0x00007fff71ce940d thread_start + 13

Thread 7 Crashed:: <lldb.process.internal-state(pid=7421)>
0   com.apple.LLDB.framework      	0x000000010c2e5e13 lldb_private::ThreadList::WillResume() + 177
1   com.apple.LLDB.framework      	0x000000010c2963be lldb_private::Process::PrivateResume() + 252
2   com.apple.LLDB.framework      	0x000000010c29c91f lldb_private::Process::ShouldBroadcastEvent(lldb_private::Event*) + 849
3   com.apple.LLDB.framework      	0x000000010c2992d0 lldb_private::Process::HandlePrivateEvent(std::__1::shared_ptr<lldb_private::Event>&) + 210
4   com.apple.LLDB.framework      	0x000000010c29d209 lldb_private::Process::RunPrivateStateThread(bool) + 865
5   com.apple.LLDB.framework      	0x000000010c29c9b2 lldb_private::Process::PrivateStateThread(void*) + 22
6   com.apple.LLDB.framework      	0x000000010c26f93b lldb_private::HostNativeThreadBase::ThreadCreateTrampoline(void*) + 105
7   libsystem_pthread.dylib       	0x00007fff71cea2eb _pthread_body + 126
8   libsystem_pthread.dylib       	0x00007fff71ced249 _pthread_start + 66
9   libsystem_pthread.dylib       	0x00007fff71ce940d thread_start + 13

Thread 8:: RPC packet thread for client tid 00051b0e (334606)
0   libsystem_kernel.dylib        	0x00007fff71c3261a __select + 10
1   com.apple.LLDB.framework      	0x000000010c47a47b SelectHelper::Select() + 895
2   com.apple.LLDB.framework      	0x000000010bfa8685 lldb_private::ConnectionFileDescriptor::BytesAvailable(lldb_private::Timeout<std::__1::ratio<1l, 1000000l> > const&, lldb_private::Status*) + 253
3   com.apple.LLDB.framework      	0x000000010bfa8284 lldb_private::ConnectionFileDescriptor::Read(void*, unsigned long, lldb_private::Timeout<std::__1::ratio<1l, 1000000l> > const&, lldb::ConnectionStatus&, lldb_private::Status*) + 112
4   com.apple.LLDB.framework      	0x000000010c02972b lldb_private::Communication::ReadFromConnection(void*, unsigned long, lldb_private::Timeout<std::__1::ratio<1l, 1000000l> > const&, lldb::ConnectionStatus&, lldb_private::Status*) + 45
5   com.apple.LLDB.framework      	0x000000010c0292d8 lldb_private::Communication::Read(void*, unsigned long, lldb_private::Timeout<std::__1::ratio<1l, 1000000l> > const&, lldb::ConnectionStatus&, lldb_private::Status*) + 174
6   com.apple.LLDB.framework      	0x000000010c1a748f lldb_private::process_gdb_remote::GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote&, lldb_private::Timeout<std::__1::ratio<1l, 1000000l> >, bool) + 273
7   com.apple.LLDB.framework      	0x000000010c37308c lldb_private::process_gdb_remote::GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(llvm::StringRef, StringExtractorGDBRemote&) + 106
8   com.apple.LLDB.framework      	0x000000010c372f9c lldb_private::process_gdb_remote::GDBRemoteClientBase::SendPacketAndWaitForResponse(llvm::StringRef, StringExtractorGDBRemote&, bool) + 76
9   com.apple.LLDB.framework      	0x000000010c1b9b12 lldb_private::process_gdb_remote::ProcessGDBRemote::DoDestroy() + 598
10  com.apple.LLDB.framework      	0x000000010c292eba lldb_private::Process::Destroy(bool) + 238
11  com.apple.LLDB.framework      	0x0000000108e9a3c9 lldb::SBProcess::Kill() + 101
12  lldb-rpc-server               	0x00000001049a0e45 rpc_server::_ZN4lldb9SBProcess4KillEv::HandleRPCCall(rpc_common::Connection&, rpc_common::RPCStream&, rpc_common::RPCStream&) + 47
13  lldb-rpc-server               	0x00000001049accd3 rpc_common::Connection::PrivateHandleRPCPacket(rpc_common::RPCPacket&, rpc_common::RPCPacket&, bool&) + 469
14  lldb-rpc-server               	0x00000001049ad9d4 rpc_common::Connection::HandleRPCPacket(rpc_common::RPCPacket&) + 62
15  lldb-rpc-server               	0x00000001049b12ba Packets::ProcessPackets() + 254
16  lldb-rpc-server               	0x00000001049b10e2 Packets::ReadThread() + 190
17  lldb-rpc-server               	0x00000001049b101f Packets::RunReadThread(void*) + 9
18  libsystem_pthread.dylib       	0x00007fff71cea2eb _pthread_body + 126
19  libsystem_pthread.dylib       	0x00007fff71ced249 _pthread_start + 66
20  libsystem_pthread.dylib       	0x00007fff71ce940d thread_start + 13

Thread 9:: RPC packet thread for client tid 00051ae5 (334565)
0   libsystem_kernel.dylib        	0x00007fff71c2e86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff71ced56e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6ed28a0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   lldb-rpc-server               	0x00000001049b1102 Packets::ReadThread() + 222
4   lldb-rpc-server               	0x00000001049b101f Packets::RunReadThread(void*) + 9
5   libsystem_pthread.dylib       	0x00007fff71cea2eb _pthread_body + 126
6   libsystem_pthread.dylib       	0x00007fff71ced249 _pthread_start + 66
7   libsystem_pthread.dylib       	0x00007fff71ce940d thread_start + 13

Thread 7 crashed with X86 Thread State (64-bit):
  rax: 0x0000000000000000  rbx: 0x000000010c7e240a  rcx: 0x00007fff71c2ef4a  rdx: 0x0000000000000000
  rdi: 0x00007f7f2f0f4180  rsi: 0x000000010c7b13b9  rbp: 0x0000700005b65ca0  rsp: 0x0000700005b65b90
   r8: 0x0000700005b65708   r9: 0x0000000000000000  r10: 0x00007fff71c2ef4a  r11: 0x0000000000000296
  r12: 0x00007f7f2f7274c0  r13: 0x000000010c7e2582  r14: 0x000000010c7e253c  r15: 0x00007f7f2f727460
  rip: 0x000000010c2e5e13  rfl: 0x0000000000010246  cr2: 0x0000000108cb9000
  
Logical CPU:     0
Error Code:      0x0200005d
Trap Number:     133

...

Might be due to the associatedtype in your protocols. Does it work if you remove it?

1 Like

I’ve just realized you meant a Playground in XCode and not Swift Playgrounds in iOS (which is where I tried it successfully). Why did Apple name two different things the same name? :man_shrugging:

I expected your suggestion to result in a working playground... but it didn't! :exploding_head:
I commented out the lines as following, but I still get the same error.
Here's the commented code:

import UIKit

protocol VIPERVC: UIViewController {
//    associatedtype Interactor: VIPERInteractor
//        where Interactor.Presenter.ViewController == Self
    
    static var storyboardName: String { get }
    static var storyboardIdentifier: String { get }
    
//    var interactor: Interactor! { get set }
}

extension VIPERVC {
//    typealias Presenter = Interactor.Presenter
}

protocol VIPERInteractor {
//    associatedtype Presenter: VIPERPresenter
//        where Presenter.ViewController.Interactor == Self
    
    init(_ repo: VIPEREntityRepository)
    
//    var presenter: Presenter! { get set }
}

extension VIPERInteractor {
//    typealias ViewController = Presenter.ViewController
}

protocol VIPERPresenter {
//    associatedtype ViewController: VIPERVC
//        where ViewController.Interactor.Presenter == Self
    
//    init(_ vc: ViewController)
//
//    var vc: ViewController! { get set }
}

extension VIPERPresenter {
//    typealias Interactor = ViewController.Interactor
}

class TestEntity {
    func provideString() -> String {
        return "TestString"
    }
}

struct VIPEREntityRepository {
    private let testEntity = TestEntity()
    
    init() { }
    
    func provideEntity<T>() -> T {
        let mirror = Mirror(reflecting: self)
        guard let entity = mirror.children.first(where: { $0.value is T })
            else {
                let message = "Dependency with type: \(T.self) not found.\nAvailable dependencies:\n"
                let dependencies = mirror.children.map { "\($0.label ?? "nil"): \(type(of: $0.value))" }
                fatalError(message + dependencies.joined(separator: "\n")) }
        return entity.value as! T
    }
}

class TestViewController: UIViewController, VIPERVC {
    class var storyboardName: String { return "Main" }
    class var storyboardIdentifier: String { return "TestVC" }
    
    @IBOutlet var mainLabel: UILabel!
    
    typealias Interactor = TestInteractor
    
    var interactor: TestInteractor! = nil
    
    @IBAction func pressButton() {
        interactor.retrieveString()
    }
}

class TestInteractor: VIPERInteractor {
    typealias Presenter = TestPresenter
    
    var presenter: TestPresenter! = nil
    
    private let repo: VIPEREntityRepository
    private lazy var entity: TestEntity = repo.provideEntity()
    
    required init(_ repo: VIPEREntityRepository) {
        self.repo = repo
    }
    
    func retrieveString() {
        let string = entity.provideString()
        presenter.updateLabel(withString: string)
    }
}

class TestPresenter: VIPERPresenter {
    typealias ViewController = TestViewController
    
    required init(_ vc: ViewController) {
        self.vc = vc
    }
    
    unowned var vc: TestViewController!
    
    func updateLabel(withString str: String) {
        vc.mainLabel.text = str
    }
}

struct ModuleBuilder<VC: VIPERVC> {
    
//    func build(_ repo: VIPEREntityRepository) -> VC {
//        let storyboard = UIStoryboard(name: VC.storyboardName, bundle: .main)
//        let vc = storyboard.instantiateViewController(withIdentifier: VC.storyboardIdentifier) as! VC
//
//        var interactor = VC.Interactor(repo)
//        var presenter = VC.Presenter(vc)
//
//        vc.interactor = interactor
//        interactor.presenter = presenter
//        presenter.vc = vc
//
//        return vc
//    }
}

@toph42 In defense of Apple's naming: "iPlaygrounds" sounds horrible :sweat_smile:

I've found the offending line:

func updateLabel(withString str: String) {
        vc.mainLabel.text = str // This triggers the parsing error
}

If I change it adding a question mark everything goes fine (also works with all the associatedtypes!):

func updateLabel(withString str: String) {
        vc.mainLabel?.text = str // This works just fine!
}

This totally looks like a Playground bug to me. Who can we @ at about playgrounds?

You can file a bug report on bugs.swift.org

I further simplified the error sample code and I submitted the bug: [SR-11054] “Expression failed to parse, unknown error” only in Xcode 10.2.1 playgrounds · Issue #53446 · apple/swift · GitHub

Now the offending code is reduced to this:

class TestViewController: UIViewController {
    var mainLabel: UILabel!
}

class TestPresenter {
    init(_ vc: TestViewController) {
        self.vc = vc
    }
    
    var vc: TestViewController!
    
    func updateLabel(withString str: String) {
        vc.mainLabel.text = str
    }
}
2 Likes