Hmm, I get warning when defining the init: initializer for struct 'X' must use "self.init(...)" or "self = ..." because it is not in module 'REPL_0'
That’s an artifact of using the REPL. Try compiling that in one file
What exactly am I supposed to be looking for? This compiles and executes fine.
public struct X {
public var y: (Int) -> Int = { $0 }
}
extension X {
@inlinable init(y: Int) { print(y) }
}
_ = X()
_ = X(y: 6) // 6
I suppose the motivating example isn't a huge problem, but it's definitely something that you'll have to look out for when implementing this.
The place where this transformation is not valid is in @_fixed_layout
types in resilient modules, where a property initializer need to only reference public
or @usableFromInline
things.
@_fixed_layout
public struct X {
public var x: (Int) -> Int = { $0 }
public var y: (Int) -> Int = X.y_initialValue()
static func y_initialValue() -> (Int) -> Int {
return { $0 }
}
}
Here, x
is fine because the closure is directly written. But y
calls something that's not @usableFromInline
, meaning:
test.swift:4:34: error: static method 'y_initialValue()' is internal and cannot be referenced from a property initializer in a '@_fixed_layout' type
public var y: (Int) -> Int = X.y_initialValue()
^
test.swift:5:15: note: static method 'y_initialValue()' is not '@usableFromInline' or public
static func y_initialValue() -> (Int) -> Int {
Also, if the static function is going to be @inlinable
or @_transparent
, it may need to show up in parseable interface files, which would mean it would need a name other than "varName.initialValue"
I added a comment: [Sema] Synthesize default values for memberwise init by Azoy · Pull Request #19743 · apple/swift · GitHub
I suspect there's a better way of doing this, basically by sinking this down into the SILGen level.
Let's look at the SIL for a struct with a property that has an initial value:
struct S {
var x: Int = 0
}
sil hidden [transparent] @$S7initial1SV1xSivpfi : $@convention(thin) () -> Int {
bb0:
%0 = metatype $@thin Int.Type // user: %3
%1 = integer_literal $Builtin.Int2048, 0 // user: %3
// function_ref Int.init(_builtinIntegerLiteral:)
%2 = function_ref @$SSi22_builtinIntegerLiteralSiBi2048__tcfC : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int // user: %3
%3 = apply %2(%1, %0) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int // user: %4
return %3 : $Int // id: %4
} // end sil function '$S7initial1SV1xSivpfi'
Your helper function effectively already exists. What you need to do then is to have the default argument generator emitted by SIL call it.