-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Description
| Previous ID | SR-7064 |
| Radar | rdar://problem/37820485 |
| Original Reporter | @tcldr |
| Type | Bug |
| Status | Resolved |
| Resolution | Done |
Attachment: Download
Environment
Apple Swift version 4.1 (swiftlang-902.0.41 clang-902.0.31) – Xcode 9.3b3
Additional Detail from JIRA
| Votes | 0 |
| Component/s | Compiler |
| Labels | Bug, 4.1Regression, OptimizedOnly |
| Assignee | @eeckstein |
| Priority | Medium |
md5: d21e98eb0eac7f79557312a51c8fdd25
is duplicated by:
- SR-7585 Possible compiler bug when passing method reference to function
Issue Description:
I've noticed a runtime crash when running fairly typical code with the popular RxSwift library.
It only occurs on optimised (Release) builds and therefore appears to be an issue with the Swift compiler's optimisation process.
I've included a small project which demonstrates the issue. From what I can tell it looks as though the optimiser may be stripping away a getter somewhere in shouldn't be.
Steps to reproduce:
-
Open the 'BugWorkspace.xcworkspace' in Xcode 9.3b3
-
Ensure the 'BugApp-Optimised' scheme is selected
-
Run in the simulator (or device)
-
Tap anywhere on the screen
-
Crash
Backtrace:
* thread #​1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #​0: 0x000000010a593138 RxSwift`specialized TakeUntilSink._lock.getter(self=0x00006000000a94e0) at TakeUntil.swift:0 [opt]
frame #​1: 0x000000010a59268b RxSwift`TakeUntilSink._lock.getter at TakeUntil.swift:0 [opt]
frame #​2: 0x000000010a592d79 RxSwift`protocol witness for LockOwnerType._lock.getter in conformance TakeUntilSink<A, B> at TakeUntil.swift:0 [opt]
frame #​3: 0x000000010a5bed6d RxSwift`merged (extension in RxSwift):RxSwift.LockOwnerType.lock() -> () + 13
frame #​4: 0x000000010a5bed50 RxSwift`(extension in RxSwift):RxSwift.LockOwnerType.unlock() -> () + 16
frame #​5: 0x000000010a5bee07 RxSwift`protocol witness for Lock.unlock() in conformance TakeUntilSink<A, B> at LockOwnerType.swift:0 [opt]
* frame #​6: 0x000000010a5c1c16 RxSwift`SynchronizedOnType.synchronizedOn(_:) [inlined] $defer #​1 <A where A: RxSwift.SynchronizedOnType>(self=<unavailable>, self=0x00006000000a94e0) -> () in (extension in RxSwift):RxSwift.SynchronizedOnType.synchronizedOn(RxSwift.Event<A.E>) -> () at SynchronizedOnType.swift:15 [opt]
frame #​7: 0x000000010a5c1c03 RxSwift`SynchronizedOnType.synchronizedOn(event=<unavailable>, self=0xbadd8bdf32d8bead) at SynchronizedOnType.swift:15 [opt]
frame #​8: 0x000000010a592774 RxSwift`TakeUntilSink.on(event=<unavailable>, self=0x00006000000a94e0) at TakeUntil.swift:90 [opt]
frame #​9: 0x000000010a592d90 RxSwift`protocol witness for ObserverType.on(_:) in conformance TakeUntilSink<A, B> at TakeUntil.swift:0 [opt]
frame #​10: 0x000000010a5c74c2 RxSwift`Sink.forwardOn(event=<unavailable>, self=<unavailable>) at Sink.swift:35 [opt]
frame #​11: 0x000000010a5bcdd1 RxSwift`AnonymousObservableSink.on(event=<unavailable>, self=0x000060000008d890) at Create.swift:50 [opt]
frame #​12: 0x000000010a5bcf50 RxSwift`protocol witness for ObserverType.on(_:) in conformance AnonymousObservableSink<A> at Create.swift:0 [opt]
frame #​13: 0x000000010a62a00a RxSwift`partial apply at ObserverType.swift:0 [opt]
frame #​14: 0x000000010a598b1c RxSwift`AnyObserver.on(event=<unavailable>, self=<unavailable>) at AnyObserver.swift:39 [opt]
frame #​15: 0x000000010a3cf4c4 RxCocoa`partial apply for closure #​1 in closure #​1 in Reactive<A>.controlEvent(_:) [inlined] function signature specialization <Arg[0] = Dead> of closure #​1 (observer=<unavailable>) -> () in closure #​1 (RxSwift.AnyObserver<()>) -> RxSwift.Disposable in (extension in RxCocoa):RxSwift.Reactive<A where A: __ObjC.UIControl>.controlEvent(__C.UIControlEvents) -> RxCocoa.ControlEvent<()> at UIControl+Rx.swift:44 [opt]
frame #​16: 0x000000010a3cf4a4 RxCocoa`partial apply for closure #​1 in closure #​1 in Reactive<A>.controlEvent(_:) [inlined] closure #​1 (__ObjC.UIControl) -> () in closure #​1 (RxSwift.AnyObserver<()>) -> RxSwift.Disposable in (extension in RxCocoa):RxSwift.Reactive<A where A: __ObjC.UIControl>.controlEvent(__C.UIControlEvents) -> RxCocoa.ControlEvent<()> at UIControl+Rx.swift:42 [opt]
frame #​17: 0x000000010a3cf4a4 RxCocoa`partial apply for closure #​1 in closure #​1 in Reactive<A>.controlEvent(_:) at UIControl+Rx.swift:0 [opt]
frame #​18: 0x000000010a40f3a2 RxCocoa`@objc ControlTarget.eventHandler(_:) at ControlTarget.swift:73 [opt]
frame #​19: 0x000000010a40f374 RxCocoa`@objc ControlTarget.eventHandler(_:) at ControlTarget.swift:71 [opt]
frame #​20: 0x000000010b6e2d78 UIKit`-[UIApplication sendAction:to:from:forEvent:] + 83
frame #​21: 0x000000010b85dd9c UIKit`-[UIControl sendAction:to:forEvent:] + 67
frame #​22: 0x000000010b85e0b9 UIKit`-[UIControl _sendActionsForEvents:withEvent:] + 450
frame #​23: 0x000000010b85d001 UIKit`-[UIControl touchesEnded:withEvent:] + 580
frame #​24: 0x000000010b757a4f UIKit`-[UIWindow _sendTouchesForEvent:] + 2729
frame #​25: 0x000000010b759151 UIKit`-[UIWindow sendEvent:] + 4086
frame #​26: 0x000000010b6fcca0 UIKit`-[UIApplication sendEvent:] + 352
frame #​27: 0x000000010c03d4bb UIKit`__dispatchPreprocessedEventFromEventQueue + 2796
frame #​28: 0x000000010c0400d0 UIKit`__handleEventQueueInternal + 5949
frame #​29: 0x000000010e2abe41 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #​30: 0x000000010e29073f CoreFoundation`__CFRunLoopDoSources0 + 271
frame #​31: 0x000000010e28fcff CoreFoundation`__CFRunLoopRun + 1263
frame #​32: 0x000000010e28f59b CoreFoundation`CFRunLoopRunSpecific + 635
frame #​33: 0x0000000112a59a73 GraphicsServices`GSEventRunModal + 62
frame #​34: 0x000000010b6e19e7 UIKit`UIApplicationMain + 159
frame #​35: 0x000000010a0bbf40 BugApp`main at AppDelegate.swift:14 [opt]
frame #​36: 0x000000010fe43955 libdyld.dylib`start + 1
frame #​37: 0x000000010fe43955 libdyld.dylib`start + 1View Controller to reproduce issue:
// ENSURE BUILD OPTIMISATION IS ENABLED
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func loadView() {
let button = UIButton(frame: .zero)
button.backgroundColor = .red
self.view = button
}
override func viewDidLoad() {
super.viewDidLoad()
let button = view as! UIButton
let reductionSubject = ReplaySubject <Void>.create(bufferSize: 1)
let reducerStream = reductionSubject
.flatMapLatest{ _ in button.rx.tap }
.startWith(())
.do(onNext: { print("state: \($0)") })
reducerStream.subscribe(reductionSubject).disposed(by: disposeBag)
}
}