Found a bug when using keypath as function feature of Swift.
OriTheElf opened this issue · comments
Short description of the issue:
I wrote en extension of Reactive, here is the code:
extension UITableView {
var numberOfRows: Int {
(0..<numberOfSections).reduce(0) { rowCount, section in
rowCount + numberOfRows(inSection: section)
}
}
}
extension ObservableConvertibleType where Element: Collection {
var ifEmptyEmitNil: Observable<Element?> {
asObservable()
.map { collection in
if collection.isEmpty { return nil }
return collection
}
}
}
extension Reactive where Base: UITableView {
var isAllRowsSelected: Observable<Bool> {
didReloadData
.flatMapLatest(\.rx.latestSelectedIndexPaths)
.ifEmptyEmitNil
.withUnretained(base)
.map { table, selectedIndexPaths in
guard let selectedIndexPaths else { return false }
return selectedIndexPaths.count == table.numberOfRows
}
}
var selectedIndexPaths: Observable<[IndexPath]> {
willReloadData.flatMapLatest(\.rx.latestSelectedIndexPaths)
}
var didReloadData: Observable<Base> {
methodInvoked(#selector(UITableView.reloadData))
.withUnretained(base)
.map(\.0)
}
var willReloadData: Observable<Base> {
sentMessage(#selector(UITableView.reloadData))
.withUnretained(base)
.map(\.0)
}
fileprivate var latestSelectedIndexPaths: Observable<[IndexPath]> {
rowSelectionChanged
.withUnretained(base)
.map { tableview, _ in
tableview.indexPathsForSelectedRows ?? []
}
.startWith(base.indexPathsForSelectedRows ?? [])
}
private var rowSelectionChanged: Observable<IndexPath> {
Observable.of(selectRowAt, itemSelected.asObservable(), itemDeselected.asObservable()).merge()
}
private var selectRowAt: Observable<IndexPath> {
base.rx.methodInvoked(#selector(UITableView.selectRow(at:animated:scrollPosition:)))
.map(\.first)
.compactMap { $0 }
.as(IndexPath.self)
}
}
the code above buit with error:
- While evaluating request IRGenRequest(IR Generation for file "/Users/choi/Developer/zeniko/zeniko/Source/Vendors/Playground/RxPlayground/RxExtensions/UITableView+Rx.swift")
- While emitting IR SIL function "@$s7RxSwift8ReactiveV6zenikoSo11UITableViewCRbzlE17isAllRowsSelectedAA10ObservableCySbGvg".
for getter for isAllRowsSelected (at /Users/choi/Developer/zeniko/zeniko/Source/Vendors/Playground/RxPlayground/RxExtensions/UITableView+Rx.swift:20:9)
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment varLLVM_SYMBOLIZER_PATH
to point to it):
0 swift-frontend 0x00000001058567f7 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 39
1 swift-frontend 0x0000000105855828 llvm::sys::RunSignalHandlers() + 248
2 swift-frontend 0x0000000105856e10 SignalHandler(int) + 288
3 libsystem_platform.dylib 0x00007ff8055a6dfd _sigtramp + 29
4 libsystem_platform.dylib 0x0000000000010101 _sigtramp + 18446603370491188001
5 libsystem_c.dylib 0x00007ff8054dcd24 abort + 123
6 swift-frontend 0x0000000101995a4f swift::rewriting::RequirementMachine::getConformanceAccessPath(swift::Type, swift::ProtocolDecl*) + 2975
7 swift-frontend 0x000000010172f3de swift::Mangle::ASTMangler::appendAnyProtocolConformance(swift::GenericSignature, swift::CanType, swift::ProtocolConformanceRef) + 222
8 swift-frontend 0x0000000100887fda swift::irgen::IRGenMangler::mangleSymbolNameForMangledConformanceAccessorString(char const*, swift::CanGenericSignature, swift::CanType, swift::ProtocolConformanceRef) + 202
9 swift-frontend 0x000000010081af69 swift::irgen::IRGenModule::emitWitnessTableRefString(swift::CanType, swift::ProtocolConformanceRef, swift::GenericSignature, bool) + 553
10 swift-frontend 0x00000001007cf10e void llvm::function_ref<void (swift::irgen::GenericRequirement)>::callback_fn<emitKeyPathComponent(swift::irgen::IRGenModule&, swift::irgen::ConstantStructBuilder&, swift::KeyPathPatternComponent const&, bool, swift::GenericEnvironment*, llvm::ArrayRefswift::irgen::GenericRequirement, swift::CanType, llvm::ArrayRef, bool)::$_5>(long, swift::irgen::GenericRequirement) + 382
11 swift-frontend 0x000000010080a86f swift::irgen::enumerateGenericSignatureRequirements(swift::CanGenericSignature, llvm::function_ref<void (swift::irgen::GenericRequirement)> const&) + 415
12 swift-frontend 0x00000001007c8e8e emitKeyPathComponent(swift::irgen::IRGenModule&, swift::irgen::ConstantStructBuilder&, swift::KeyPathPatternComponent const&, bool, swift::GenericEnvironment*, llvm::ArrayRefswift::irgen::GenericRequirement, swift::CanType, llvm::ArrayRef, bool) + 1358
13 swift-frontend 0x00000001007c8329 swift::irgen::IRGenModule::getAddrOfKeyPathPattern(swift::KeyPathPattern*, swift::SILLocation) + 2201
14 swift-frontend 0x000000010089be83 swift::SILInstructionVisitor<(anonymous namespace)::IRGenSILFunction, void>::visit(swift::SILInstruction*) + 7587
15 swift-frontend 0x00000001008950e2 swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 10706
16 swift-frontend 0x000000010073c257 swift::irgen::IRGenerator::emitGlobalTopLevel(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > > > const&) + 1623
17 swift-frontend 0x00000001008618a0 swift::IRGenRequest::evaluate(swift::Evaluator&, swift::IRGenDescriptor) const + 10272
18 swift-frontend 0x00000001008923ec swift::SimpleRequest<swift::IRGenRequest, swift::GeneratedModule (swift::IRGenDescriptor), (swift::RequestFlags)9>::evaluateRequest(swift::IRGenRequest const&, swift::Evaluator&) + 204
19 swift-frontend 0x000000010086c740 llvm::Expectedswift::IRGenRequest::OutputType swift::Evaluator::getResultUncachedswift::IRGenRequest(swift::IRGenRequest const&) + 832
20 swift-frontend 0x0000000100865fcc swift::performIRGeneration(swift::FileUnit*, swift::IRGenOptions const&, swift::TBDGenOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_deleteswift::SILModule >, llvm::StringRef, swift::PrimarySpecificPaths const&, llvm::StringRef, llvm::GlobalVariable**) + 348
21 swift-frontend 0x0000000100413c5b performCompileStepsPostSILGen(swift::CompilerInstance&, std::__1::unique_ptr<swift::SILModule, std::__1::default_deleteswift::SILModule >, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 2539
22 swift-frontend 0x00000001004159b5 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 5701
23 swift-frontend 0x00000001003ab8ea swift::mainEntry(int, char const**) + 3082
24 dyld 0x000000011273952e start + 462
I have to write another extension for UITableView:
extension UITableView {
var latestSelectedIndexPaths: Observable<[IndexPath]> {
rx.latestSelectedIndexPaths
}
}
and remove the .rx part in the computed properties:
var isAllRowsSelected: Observable<Bool> {
didReloadData
.flatMapLatest(\.latestSelectedIndexPaths)
.ifEmptyEmitNil
.withUnretained(base)
.map { table, selectedIndexPaths in
guard let selectedIndexPaths else { return false }
return selectedIndexPaths.count == table.numberOfRows
}
}
var selectedIndexPaths: Observable<[IndexPath]> {
willReloadData.flatMapLatest(\.latestSelectedIndexPaths)
}
then the code builds.
Expected outcome:
Code build without error.
What actually happens:
Code build with error.
RxSwift/RxCocoa/RxBlocking/RxTest version/commit
RxCocoa (6.5.0):
- RxRelay (= 6.5.0)
- RxSwift (= 6.5.0)
- RxRelay (6.5.0):
- RxSwift (= 6.5.0)
- RxSwift (6.5.0)
Platform/Environment
- iOS
- macOS
- tvOS
- watchOS
- playgrounds
How easy is to reproduce? (chances of successful reproduce after running the self contained code)
- easy, 100% repro
- sometimes, 10%-100%
- hard, 2% - 10%
- extremely hard, %0 - 2%
Xcode version:
Xcode 14.0.1
I'm not sure if it is a RxSwift bug, maybe it has something to do with the compiler, hoping to get some help.😊
Hey, based on the failure it seems like a Swift compiler issue which isn't something we can help with unfortunately :(