Conditional conformance of type to protocol does not imply conformance to inherited protocol

I'm getting the error Conditional conformance of type 'API.Page<T>' to protocol 'Unmarshaling' does not imply conformance to inherited protocol 'ValueType' when I add the type constraint on the extension, but not if I have the type constraint on the struct declaration. I don’t understand why they're different.

struct Page<T>
    where T : Unmarshaling      //  OK when here
{
    public let metadata: PageMetadata
    public let items: [T]
}

extension Page : Unmarshaling
    where T : Unmarshaling      //  Error when here
{
    public init(object inObj: MarshaledObject) throws
    {
        self.metadata = try inObj.value(for: "metadata")
        self.items = try inObj.value(for: "items")
    }
}

I've seen constrained conformances in extensions before, what am I doing wrong?

I’ve noticed that you don’t post minimal reproducible examples. That makes it too time-consuming to help you. It is more effective to take the time to whittle the problem down, than to post a portion of the problem that requires too much imagination, resulting in you not getting help often. It’s possible that this is a rubber ducking approach, but that’s kind of a noisy thing to do on a forum.

That’s not to say you’ll get help anyway. Most of my simple, compiling examples here result in people trying to tell me I have an XY problem, which adds its own sort of noise. But at least that’s not silence, until they get too fed up to continue! :smiley_cat:

when it’s attached to the original declaration, it's not a conditional conformance, it's an unconditional conformance. the where T:Unmarshalling is a constraint on the Page type constructor itself.

when you attach it to the extension with the restated where T:Unmarshalling, that becomes a conditional constraint that just happens to apply the conformance unconditionally, because the constraint is the same as the one on the type constructor.

you don't need the second constraint for the conformance, it is redundant if the same constraint is already present on the type constructor.

2 Likes

@JetForMe’s example is minimal enough. In ~6 lines of code, it illustrates the problem in a real-world context without distracting with unnecessary complexity.

It's not just the size, I'm afraid in this case the context could've been better and example could've been more self contained.

I see this guys for the first time: Unmarshaling, PageMetadata, MarshaledObject. Ok, no worries, I made some assumptions about those and created some reasonable surrogates for those - but gee, there's no error, so maybe I did wrong assumptions, or maybe my version of Xcode is different or maybe it's something else - no idea, but the end result is that I can't reproduce the issue and can't help. If that example was a self contained, minimal (ideally without any dependencies) example the pool of people who'd be able to help would be bigger.

1 Like