无法转换具有匹配类型的类型的值 - 我遇到了编译器限制吗?

Cannot convert value of type with matching types - have I hit a compiler limitation?

背景:

我正在构建一个带有服务层的应用程序,该服务层应该 return 模型相似(例如,所有模型都有 text: String 属性,在协议 TextModel).该服务拥有一个存储库,用于查找 returns 符合 TextModel 的具体类型模型。存储库需要保留其内部工作的具体类型信息。我想让服务不受模型的具体类型影响,这样我就不必为每种模型类型重复它。编译器不允许我这样做...

问题:

我在 Playground 中简化的以下代码将无法编译:

enum Result<T> {

    case success(T)
    case error
}

// Model Layer

protocol TextModel {

    var text: String { get }
}

struct Person: TextModel {

    let text: String
}

// Service Layer

class TextModelService {

    let repository: TextModelRepositoryType

    init(repository: TextModelRepositoryType) {

        self.repository = repository
    }

    func find(completion: @escaping (Result<TextModel>) -> ()) {

        repository.find(completion: completion)
    }
}

// Repository Layer

protocol TextModelRepositoryType {

    func find(completion: @escaping (Result<TextModel>) -> ())
}

protocol PersonRepositoryType {

    func findPerson(completion: @escaping (Result<Person>) -> ())
}

class PersonRepository: PersonRepositoryType, TextModelRepositoryType {

    func find(completion: @escaping (Result<TextModel>) -> ()) {

        // ERROR HERE: "Cannot convert value of type '(Result<TextModel>) -> ()' to expected argument type '(Result<Person>) -> ()'"
        findPerson(completion: completion)
    }

    func findPerson(completion: @escaping (Result<Person>) -> ()) {

        let person = Person(text: "Adam")
        completion(.success(person))
    }
}

let repository = PersonRepository()
let service = TextModelService(repository: repository)
service.find { result in

    // result should be a Result<Person>
}

我不明白为什么编译器声明它 'Cannot convert value of type '(Result<TextModel>) -> ()' to expected argument type '(Result<Person>) -> ()'Person 绝对符合 TextModel...

同样有趣的是,当我删除 Result 类型并在完成时仅传递一个未包装的类型(例如 (TextModel?) -> ())时,编译器没有任何疑虑。

我是否遇到了 Swift 编译器的限制?或者我错过了什么?

因为Swift有不变的泛型类型,所以即使A可以转换成BT<A>也不能转换成T<B>

这种情况下的解决方法是自己创建转换方法:

enum Result<T> {

    case success(T)
    case error

    func cast<R>() -> Result<R>? {
        switch self {
        case .error: return .error
        case .success(let t) where t is R: return .success(t as! R)
        default: return nil
        }
    }
}

extension Result where T : TextModel {
    func convertToTextModel() -> Result<TextModel> {
        switch self {
        case .error: return .error
        case .success(let t): return .success(t)
        }
    }
}

然后在find中调用这些转换方法:

func find(completion: @escaping (Result<TextModel>) -> ()) {
    findPerson(completion: { completion([=11=].convertToTextModel()) })
}

在来电方:

let repository = PersonRepository()
let service = TextModelService(repository: repository)
service.find { result in
    if let person: Result<Person> = result.cast() {
        // ...
    }
}