Uploaded image for project: 'Swift'
  1. Swift
  2. SR-10257

Inference of @objc from witnessed protocol requirement fails sometimes




      The short version: In certain cases, the Swift 5.0 compiler does not infer @objc correctly for a function. This only happens in wholemodule mode, which means that there's an observable behavior difference between incremental and whole-module compilation.


      There are three files involved:

      • BaseVC.swift
      • ChildVC.swift
      • UnrelatedClass.swift

      BaseVC declares conformance to UITableViewDelegate, but does not implement anything.

      ChildVC implements 'func tableView(_:didSelectRowAt:)'

      The app delegate checks whether ChildVC responds to -tableView:didSelectRowAtIndexPath:. Up to this point, it does.

      Now we add in a third file, "UnrelatedClass.swift"

      If all of the following hold true, then the ChildVC.respondsToSelector() check fails:

      1. The third file contains an 'AnyObject'-dispatched call to .selectionChanged()
      2. The order of the files passed to the compiler is [BaseVC, UnrelatedClass, ChildVC].
      3. ChildVC.tableView(_:didSelectRowAt:) is not tagged @objc
      4. The compiler is running in 'wholemodule' mode.

      In that case, the ObjC runtime does not see the implementation of -tableView:didSelectRowAtIndexPath:.

      Only under those four conditions does this bug appear.


      In Swift 4.2, @objc was inferred. In Swift 5.0 incremental mode, @objc is inferred.


      I'm attaching a sample Xcode project which reproduces the issue easily. Just look at the console output on launch.


          Issue Links



              • Assignee:
                slavapestov Slava Pestov
                bjhomer BJ Homer
              • Votes:
                8 Vote for this issue
                25 Start watching this issue


                • Created: