Home > Software design >  How to implement static variables of associated types in protocol extensions in Swift 5.6?
How to implement static variables of associated types in protocol extensions in Swift 5.6?

Time:03-22

The following code compiles in Xcode 13.1 / Swift 5.5, but does not in Xcode 13.3 / Swift 5.6

protocol Sized {
    associatedtype Size
    static var staticSize: Size? { get }
    var size: Size? { get }
    static var staticSizeString: String? { get }
}

extension Sized where Self: FloatSized {
    static var staticSize: CGFloat? {
        return 7
    }

    var size: CGFloat? {
        return 77
    }

    static var staticSizeString: String? {
        return "seven"
    }
}

extension Sized where Self: SizeSized {
    static var staticSize: CGSize? {
        return .init(width: 7, height: 11)
    }

    var size: CGSize? {
        return .init(width: 77, height: 1111)
    }

    static var staticSizeString: String? {
        return "seven eleven"
    }
}

class FloatSized: Sized {
}

class SizeSized: Sized {
}

The 5.6 compiler tells us

error: type 'FloatSized' does not conform to protocol 'Sized' (same for SizeSized)

and

note: ambiguous inference of associated type 'Size': 'CGFloat' vs. 'CGSize'

associatedtype Size.

^

The situation can be fixed by adding the implementation for the staticSize to the class implementations of FloatSized and SizeSized. Note that this only has to be done for the static variable staticSize, while the protocol extension works well for the non-static variable size.

Since I have a lot of different implementations of Float-Sized and Size-Sized classes in my real live project, I'd like to fix that with a similar approach like the current one instead of adding the same default implementation to each of the different classes.

Does anyone has any ideas, why Swift 5.6 handles things the new way and/or how to fix that, other than adding same default code to 50 class files?

CodePudding user response:

This should be fixed by telling the compiler what Size is for the conforming classes

class FloatSized: Sized {
    typealias Size = CGFloat
    //...
}

class SizeSized: Sized {
    typealias Size = CGSize
    //...
}
  • Related