Initializer for struct must use "self.init(...)" or "self = ..." because the struct was imported from C

Isn’t the compiler being a bit pedantic here, and perhaps generating less-performant code?

extension
SCNQuaternion
{
	public
	init(_ inQuat: CMQuaternion)
	{
		self.x = Float(inQuat.x)    //  Initializer for struct 'SCNVector4' must use "self.init(...)" or "self = ..." because the struct was imported from C
		self.y = Float(inQuat.y)
		self.z = Float(inQuat.z)
		self.w = Float(inQuat.w)
	}

SCNVector4 looks like:

public struct SCNVector4 {
    public var x: Float
    public var y: Float
    public var z: Float
    public var w: Float

    public init()
    public init(x: Float, y: Float, z: Float, w: Float)
}

Isn't my initializer complete? This struct can exist in some pretty tight loops (theoretically, probably not this specific instance), and zeroing out the struct first is a waste of time.

The optimizer might see that and remove that code, especially if it first inlines the call to super.init(), but it seems Swift is being a little aggressive here.

The rule here is based on SE-0189, which protects against initializing types defined in Swift that might add a new field in the future. Of course, C's changes are a little more limited, but it's also possible that the struct has a field that Swift can't represent, and so it's important to explicitly zero that field out just in case. And then making the rule behave differently for different C structs was deemed to be more complicated than just extending Swift's rule to everything.

The optimizer will definitely remove dead stores when compiling in an optimized build, and in an unoptimized build zeroing an extra field is not going to be what hurts your tight loop.

2 Likes

Can it always identify the dead stores? Is there a function call to self.init() that also gets optimized out?

Terms of Service

Privacy Policy

Cookie Policy