How to provide parameter defaults like this: `func foo<S1: ShapeStyle, S2: ShapeStyle>(s1: S1 = .tint, s2: S2 = .primary) { }`

import SwiftUI

struct Foo<S1: ShapeStyle, S2: ShapeStyle> {
    init(s1: S1 = .tint, s2: S2 = .primary) { }
}

Error:

Member 'primary' in 'S2' produces result of type 'HierarchicalShapeStyle', but context expects 'S2'
Member 'tint' in 'S1' produces result of type 'TintShapeStyle', but context expects 'S1'
Static property 'primary' requires the types 'S2' and 'HierarchicalShapeStyle' be equivalent
Static property 'tint' requires the types 'S1' and 'TintShapeStyle' be equivalent

TintShapeStyle and HierarchicalShapeStyle both conform to ShapeStyle, so why doesn't it work? How to get this to work?

Calling this with the same parameter values work:

Foo(s1: .tint, s2: .primary)

Edit: I found this solution:

struct Foo<S1: ShapeStyle, S2: ShapeStyle> {
    init(s1: S1, s2: S2) { }
}

extension Foo where S1 == TintShapeStyle, S2 == HierarchicalShapeStyle {
    init() {
        self.init(s1: .tint, s2: .primary)
    }
}

extension Foo where S2 == HierarchicalShapeStyle {
    init(s1: S1) {
        self.init(s1: s1, s2: .primary)
    }
}

extension Foo where S1 == TintShapeStyle {
    init(s2: S2) {
        self.init(s1: .tint, s2: s2)
    }
}

This works but is quite verbose. Can this be simplify with SE-0335?

IIRC this should be possible in Swift 5.7 thanks to SE-0347.

2 Likes