使用具有自定义错误类型

时间:2015-06-25 19:27:39

标签: swift generics reactive-cocoa

这可能是一个Swift问题,或者我不理解Swift中的泛型是如何工作的,但我使用下面的代码示例得到编译器错误/崩溃,我不明白为什么

import Foundation
import ReactiveCocoa

protocol MyErrorType {

}

enum MyCustomError: MyErrorType {
    case AnError
}

enum MyCustomReactiveError: ReactiveCocoa.ErrorType {

    case Foo
    case Bar

    var nsError: NSError {
        switch self {
        case .Foo:
            return NSError(domain: "", code: 0, userInfo: nil)
        case .Bar:
            return NSError(domain: "", code: 1, userInfo: nil)
        }
    }

}

class Container1<T> {

    let value: T

    init(value: T) {
        self.value = value
    }

}

class Container2<E: MyErrorType> {

    let error: E

    init(error: E) {
        self.error = error
    }

}

class TestClass1<T> {

    let defaultValue: T

    init(defaultValue: T) {
        self.defaultValue = defaultValue
    }

    func foo() -> Container1<T> {
        return Container1(value: defaultValue)
    }

}

class TestClass2<E: MyErrorType> {

    let defaultValue: E

    init(defaultValue: E) {
        self.defaultValue = defaultValue
    }

    func foo() -> Container2<E> {
        return Container2(error: defaultValue)
    }

}


class TestClass3: TestClass1<Int> {

    override func foo() -> Container1<Int> {
        return Container1(value: 20)
    }

}

class TestClass4: TestClass2<MyCustomError> {

    override func foo() -> Container2<MyCustomError> {
        return Container2(error: MyCustomError.AnError)
    }

}

class TestClass5<E: ReactiveCocoa.ErrorType> {

    func foo() -> SignalProducer<(), E> {
        return SignalProducer.empty
    }

}

class TestClass6: TestClass5<MyCustomReactiveError> {

    override func foo() -> SignalProducer<(), MyCustomReactiveError> {
        return SignalProducer(error: MyCustomReactiveError.Foo)
    }

}

我收到以下错误

SIL verification failed: vtable entry for #TestClass5.foo!1 must be ABI-compatible
  ABI-incompatible return values
  @convention(method) <τ_0_0 where τ_0_0 : ErrorType> (@guaranteed TestClass5<τ_0_0>) -> @owned SignalProducer<(), τ_0_0>
  @convention(method) (@guaranteed TestClass6) -> @owned SignalProducer<(), MyCustomReactiveError>
In function:
// WLXViewModel.TestClass6.foo (WLXViewModel.TestClass6)() -> ReactiveCocoa.SignalProducer<(), WLXViewModel.MyCustomReactiveError>
sil @_TFC12WLXViewModel10TestClass63foofS0_FT_GV13ReactiveCocoa14SignalProducerT_OS_21MyCustomReactiveError_ : $@convention(method) (@guaranteed TestClass6) -> @owned SignalProducer<(), MyCustomReactiveError> {
bb0(%0 : $TestClass6):
  debug_value %0 : $TestClass6  // let self       // id: %1
  // function_ref ReactiveCocoa.SignalProducer.init <A, B where B: ReactiveCocoa.ErrorType> (ReactiveCocoa.SignalProducer<A, B>.Type)(error : B) -> ReactiveCocoa.SignalProducer<A, B>
  %2 = function_ref @_TFV13ReactiveCocoa14SignalProducerCu0_Rq0_S_9ErrorType_fMGS0_q_q0__FT5errorq0__GS0_q_q0__ : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 : ErrorType> (@in τ_0_1, @thin SignalProducer<τ_0_0, τ_0_1>.Type) -> @owned SignalProducer<τ_0_0, τ_0_1> // user: %9
  %3 = metatype $@thin SignalProducer<(), MyCustomReactiveError>.Type // user: %9
  // function_ref WLXViewModel.MyCustomReactiveError.Foo (WLXViewModel.MyCustomReactiveError.Type) -> WLXViewModel.MyCustomReactiveError
  %4 = function_ref @_TFO12WLXViewModel21MyCustomReactiveError3FooFMS0_S0_ : $@convention(thin) (@thin MyCustomReactiveError.Type) -> MyCustomReactiveError // user: %6
  %5 = metatype $@thin MyCustomReactiveError.Type // user: %6
  %6 = apply %4(%5) : $@convention(thin) (@thin MyCustomReactiveError.Type) -> MyCustomReactiveError // user: %8
  %7 = alloc_stack $MyCustomReactiveError         // users: %8, %9, %10
  store %6 to %7#1 : $*MyCustomReactiveError      // id: %8
  %9 = apply %2<(), MyCustomReactiveError>(%7#1, %3) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 : ErrorType> (@in τ_0_1, @thin SignalProducer<τ_0_0, τ_0_1>.Type) -> @owned SignalProducer<τ_0_0, τ_0_1> // user: %11
  dealloc_stack %7#0 : $*@local_storage MyCustomReactiveError // id: %10
  return %9 : $SignalProducer<(), MyCustomReactiveError> // id: %11
}

0  swift                    0x000000010cba1e0b llvm::sys::PrintStackTrace(__sFILE*) + 43
1  swift                    0x000000010cba254b SignalHandler(int) + 379
2  libsystem_platform.dylib 0x00007fff9117ef1a _sigtramp + 26
3  swift                    0x000000010d19ba2e FirstTarget + 60550
4  swift                    0x000000010cba2346 abort + 22
5  swift                    0x000000010ad72c49 (anonymous namespace)::SILVerifier::_require(bool, llvm::Twine const&, std::__1::function<void ()> const&) + 425
6  swift                    0x000000010ad7182b (anonymous namespace)::SILVerifier::requireABICompatibleFunctionTypes(swift::CanTypeWrapper<swift::SILFunctionType>, swift::CanTypeWrapper<swift::SILFunctionType>, llvm::Twine const&) + 651
7  swift                    0x000000010ad713eb swift::SILVTable::verify(swift::SILModule const&) const + 795
8  swift                    0x000000010ad7223f swift::SILModule::verify() const + 447
9  swift                    0x000000010adac730 swift::Lowering::SILGenModule::~SILGenModule() + 32
10 swift                    0x000000010adb214b swift::SILModule::constructSIL(swift::ModuleDecl*, swift::SILOptions&, swift::FileUnit*, llvm::Optional<unsigned int>, bool, bool) + 923
11 swift                    0x000000010adb228b swift::performSILGeneration(swift::FileUnit&, swift::SILOptions&, llvm::Optional<unsigned int>, bool) + 123
12 swift                    0x000000010abbb691 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&) + 9153
13 swift                    0x000000010abb90b3 frontend_main(llvm::ArrayRef<char const*>, char const*, void*) + 2515
14 swift                    0x000000010abb528f main + 1983
15 libdyld.dylib            0x00007fff9b1685c9 start + 1
Stack dump:

我看不出TestClass6TestClass4之间有什么区别。为什么一个人编译而另一个人几乎不相同?

顺便说一下,我正在使用XCode 7.0 beta(7A120f)和ReactiveCocoa分支swift2提交1b7e41328d22902e5357d10c38c04606be4cd478

1 个答案:

答案 0 :(得分:0)

Apple在Swift 2中用ErrorType替换了NSError。

继续在您自己的代码中明确使用NSError在某些情况下有效但在其他情况下会导致一些奇怪的错误。

使用ErrorType替换您自己代码中NSError的所有显式用法。