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 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.