Declare trivial protocol conformance for struct in

2019-05-11 05:20发布

Is it possible to declare that struct a struct, defined in a framework, trivially conforms to a protocol, defined in my app?

Say, for example, I have an API that declares structs for a few widgets modelled in a framework:

public struct VagueWidget {
    public let temperature: Float
}

public struct SpecificWidget {
    public let calibratedTemperature: Float
    public let movingAverageTemperature: Float
}

public struct SuperSpecificWidget {
    public let surfaceTemperature: Float
    public let inferredCoreTemperature: Int?
}

And then in my application I want to generalise these by way of a protocol.

protocol Widget {
    var temperature: Float { get }
}

In my application I can declare structs similar to those in the API, and trivially declare them as conforming to the protocol.

struct MockWidget {
    let temperature: Float
}

extension MockWidget: Widget {}

And then I can declare protocol conformance for the structs in the framework.

extension SuperSpecificWidget: Widget {
    var temperature: Float {
        get {
            return surfaceTemperature
        }
    }
}

extension SpecificWidget: Widget {
    var temperature: Float {
        get {
            return calibratedTemperature
        }
    }
}

extension VagueWidget: Widget {}

This code compiles, but doesn't link. The trivially conforming VagueWidget in the framework which is equivalent to the MockWidget in the application results in a missing symbol:

Undefined symbols for architecture x86_64:
  "WidgetAPI.VagueWidget.temperature.getter : Swift.Float", referenced from:
   protocol witness for WidgetApp.Widget.temperature.getter : Swift.Float in conformance WidgetAPI.VagueWidget : WidgetApp.Widget in WidgetApp in AppModel.o

Commenting out the trivial protocol conformance for the VagueWidget produces code that compiles and runs, but obviously missing the desired protocol conformance. I've added an example project on github.

Update: This appears to be a known issue. I have filed a radar, and it was closed as a duplicate of 20648441.

2条回答
Anthone
2楼-- · 2019-05-11 05:32
extension WidgetAPI.VagueWidget: Widget {
    var temperature: Float {
        return self.temperature
    }
}

Fixes it. Seems to be some sort of conflict with the stored immutable property vs. the computed readonly property in the protocol.

Update: Nevermind, I just discovered infinite recursion. Still seems like something there

查看更多
闹够了就滚
3楼-- · 2019-05-11 05:36

Interesting bug you found. You and Scott H did all the work, but wanted to chime in with some workarounds:

  1. Change your models from struct to class. No idea why this works.

  2. Functions also work (i.e. func temperature() -> Float).

Both are less than ideal.

查看更多
登录 后发表回答