Skip to content

Commit e16da4a

Browse files
committed
Improved error messages of the inhabitable type guards.
1 parent ccf8f47 commit e16da4a

File tree

2 files changed

+43
-36
lines changed

2 files changed

+43
-36
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# master
22
*Please add new entries at the top.*
33

4+
1. When composing `Signal` and `SignalProducer` of inhabitable types, e.g. `Never` or `NoError`, ReactiveSwift now warns about operators that are illogical to use, and traps at runtime when such operators attempt to instantiate an instance. (#429, kudos to @andersio)
5+
46
1. N-ary `SignalProducer` operators are now generic and accept any type that can be expressed as `SignalProducer`. (#410, kudos to @andersio)
57
Types may conform to `SignalProducerConvertible` to be an eligible operand.
68

Sources/InhabitableTypeGuards.swift

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,100 +3,105 @@ import Result
33
// Observation
44
extension SignalProducer where Value == Never {
55
@discardableResult
6-
@available(*, deprecated, message:"`success` event is never delivered.")
7-
public func startWithResult(_ action: @escaping (Result<Value, Error>) -> Void) -> Disposable { fatalError() }
6+
@available(*, deprecated, message:"`Result.success` is never delivered - `Value` is inhabitable (Instantiation at runtime would trap)")
7+
public func startWithResult(_ action: @escaping (Result<Value, Error>) -> Void) -> Disposable { observingInhabitableTypeError() }
88

99
@discardableResult
10-
@available(*, deprecated, message:"The observer is never invoked.")
11-
public func startWithValues(_ action: @escaping (Value) -> Void) -> Disposable { fatalError() }
10+
@available(*, deprecated, message:"Observer is never called - `Value` is inhabitable (Instantiation at runtime would trap)")
11+
public func startWithValues(_ action: @escaping (Value) -> Void) -> Disposable { observingInhabitableTypeError() }
1212
}
1313

1414
extension SignalProducer where Value == Never, Error == NoError {
1515
@discardableResult
16-
@available(*, deprecated, message:"The observer is never invoked.")
17-
public func startWithResult(_ action: @escaping (Result<Value, Error>) -> Void) -> Disposable { fatalError() }
16+
@available(*, deprecated, message:"Observer is never called - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)")
17+
public func startWithResult(_ action: @escaping (Result<Value, Error>) -> Void) -> Disposable { observingInhabitableTypeError() }
1818
}
1919

2020
extension SignalProducer where Error == NoError {
2121
@discardableResult
22-
@available(*, deprecated, message:"The observer is never invoked.")
23-
public func startWithFailed(_ action: @escaping (Error) -> Void) -> Disposable { fatalError() }
22+
@available(*, deprecated, message:"`Error` is inhabitable so the observer is never called (Instantiation at runtime would trap)")
23+
public func startWithFailed(_ action: @escaping (Error) -> Void) -> Disposable { observingInhabitableTypeError() }
2424
}
2525

2626
extension Signal where Value == Never {
2727
@discardableResult
28-
@available(*, deprecated, message:"`success` event is never delivered.")
29-
public func observeResult(_ action: @escaping (Result<Value, Error>) -> Void) -> Disposable { fatalError() }
28+
@available(*, deprecated, message:"`Result.success` is never delivered - `Value` is inhabitable (Instantiation at runtime would trap)")
29+
public func observeResult(_ action: @escaping (Result<Value, Error>) -> Void) -> Disposable? { observingInhabitableTypeError() }
3030

3131
@discardableResult
32-
@available(*, deprecated, message:"The observer is never invoked.")
33-
public func observeValues(_ action: @escaping (Value) -> Void) -> Disposable { fatalError() }
32+
@available(*, deprecated, message:"Observer is never called - `Value` is inhabitable (Instantiation at runtime would trap)")
33+
public func observeValues(_ action: @escaping (Value) -> Void) -> Disposable? { observingInhabitableTypeError() }
3434
}
3535

3636
extension Signal where Value == Never, Error == NoError {
3737
@discardableResult
38-
@available(*, deprecated, message:"The observer is never invoked.")
39-
public func observeResult(_ action: @escaping (Result<Value, Error>) -> Void) -> Disposable { fatalError() }
38+
@available(*, deprecated, message:"Observer is never called - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)")
39+
public func observeResult(_ action: @escaping (Result<Value, Error>) -> Void) -> Disposable? { observingInhabitableTypeError() }
4040
}
4141

4242
extension Signal where Error == NoError {
4343
@discardableResult
44-
@available(*, deprecated, message:"The observer is never invoked.")
45-
public func observeFailed(_ action: @escaping (Error) -> Void) -> Disposable { fatalError() }
44+
@available(*, deprecated, message:"Observer is never invoked - `Error` is inhabitable (Instantiation at runtime would trap)")
45+
public func observeFailed(_ action: @escaping (Error) -> Void) -> Disposable? { observingInhabitableTypeError() }
4646
}
4747

4848
// flatMap
4949
extension SignalProducer where Value == Never {
5050
@discardableResult
51-
@available(*, deprecated, message:"Use `promoteValue` instead.")
52-
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer<Inner.Value, Error> where Inner.Error == Error { fatalError() }
51+
@available(*, deprecated, message:"Use `promoteValue` instead - `Value` is inhabitable (Instantiation at runtime would trap)")
52+
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer<Inner.Value, Error> where Inner.Error == Error { observingInhabitableTypeError() }
5353

5454
@discardableResult
55-
@available(*, deprecated, message:"Use `promoteValue` instead.")
56-
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer<Inner.Value, Error> where Inner.Error == NoError { fatalError() }
55+
@available(*, deprecated, message:"Use `promoteValue` instead - `Value` is inhabitable (Instantiation at runtime would trap)")
56+
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer<Inner.Value, Error> where Inner.Error == NoError { observingInhabitableTypeError() }
5757
}
5858

5959
extension SignalProducer where Value == Never, Error == NoError {
6060
@discardableResult
61-
@available(*, deprecated, message:"Use `promoteValue` instead.")
62-
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer<Inner.Value, Inner.Error> { fatalError() }
61+
@available(*, deprecated, message:"Use `promoteValue` instead - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)")
62+
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer<Inner.Value, Inner.Error> { observingInhabitableTypeError() }
6363

6464
@discardableResult
65-
@available(*, deprecated, message:"Use `promoteValue` instead.")
66-
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer<Inner.Value, Inner.Error> where Inner.Error == Error { fatalError() }
65+
@available(*, deprecated, message:"Use `promoteValue` instead - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)")
66+
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer<Inner.Value, Inner.Error> where Inner.Error == Error { observingInhabitableTypeError() }
6767
}
6868

6969
extension SignalProducer where Error == NoError {
7070
@discardableResult
71-
@available(*, deprecated, message:"Use `promoteError` instead.")
72-
public func flatMapError<NewError>(_ transform: @escaping (Error) -> SignalProducer<Value, NewError>) -> SignalProducer<Value, NewError> { fatalError() }
71+
@available(*, deprecated, message:"Use `promoteError` instead - `Error` is inhabitable (Instantiation at runtime would trap)")
72+
public func flatMapError<NewError>(_ transform: @escaping (Error) -> SignalProducer<Value, NewError>) -> SignalProducer<Value, NewError> { observingInhabitableTypeError() }
7373
}
7474

7575
extension Signal where Value == Never {
7676
@discardableResult
77-
@available(*, deprecated, message:"Use `promoteValue` instead.")
78-
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal<Inner.Value, Error> where Inner.Error == Error { fatalError() }
77+
@available(*, deprecated, message:"Use `promoteValue` instead - `Value` is inhabitable (Instantiation at runtime would trap)")
78+
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal<Inner.Value, Error> where Inner.Error == Error { observingInhabitableTypeError() }
7979

8080
@discardableResult
81-
@available(*, deprecated, message:"Use `promoteValue` instead.")
82-
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal<Inner.Value, Error> where Inner.Error == NoError { fatalError() }
81+
@available(*, deprecated, message:"Use `promoteValue` instead - `Value` is inhabitable (Instantiation at runtime would trap)")
82+
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal<Inner.Value, Error> where Inner.Error == NoError { observingInhabitableTypeError() }
8383

8484
}
8585

8686
extension Signal where Value == Never, Error == NoError {
8787
@discardableResult
88-
@available(*, deprecated, message:"Use `promoteValue` instead.")
89-
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal<Inner.Value, Inner.Error> { fatalError() }
88+
@available(*, deprecated, message:"Use `promoteValue` instead - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)")
89+
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal<Inner.Value, Inner.Error> { observingInhabitableTypeError() }
9090

9191
@discardableResult
92-
@available(*, deprecated, message:"Use `promoteValue` instead.")
93-
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal<Inner.Value, Inner.Error> where Inner.Error == Error { fatalError() }
92+
@available(*, deprecated, message:"Use `promoteValue` instead - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)")
93+
public func flatMap<Inner: SignalProducerConvertible>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal<Inner.Value, Inner.Error> where Inner.Error == Error { observingInhabitableTypeError() }
9494
}
9595

9696
extension Signal where Error == NoError {
9797
@discardableResult
98-
@available(*, deprecated, message:"Use `promoteError` instead.")
99-
public func flatMapError<NewError>(_ transform: @escaping (Error) -> SignalProducer<Value, NewError>) -> Signal<Value, NewError> { fatalError() }
98+
@available(*, deprecated, message:"Use `promoteError` instead - `Error` is inhabitable (Instantiation at runtime would trap)")
99+
public func flatMapError<NewError>(_ transform: @escaping (Error) -> SignalProducer<Value, NewError>) -> Signal<Value, NewError> { observingInhabitableTypeError() }
100+
}
101+
102+
@inline(never)
103+
private func observingInhabitableTypeError() -> Never {
104+
fatalError("Detected an attempt to instantiate a `Signal` or `SignalProducer` that observes an inhabitable type, e.g. `Never` or `NoError`. This is considered a logical error, and appropriate operators should be used instead. Please refer to the warnings raised by the compiler.")
100105
}
101106

102107
/*

0 commit comments

Comments
 (0)