Aha!
That link was helpful, thanks. After prodding around some of the PRs, I realised that it doesn't actually depend on the size or complexity of the enum (at least, not necessarily). I'm actually able to force an "outlined init with take" with the following code (nightly, -O):
func test(_ input: HasAnEnum) -> Int {
input.readValue()
}
enum MyEnum {
case four
}
struct HasAnEnum {
var something: String
var somethingTwo: String
var value: MyEnum?
func readValue() -> Int {
let x = value!
if case .four = x { return 4 }
return -1
}
}
(Yes, the enum has one case)
This generates the following assembly (Godbolt):
output.test(output.HasAnEnum) -> Swift.Int:
push rbx
sub rsp, 16
add rdi, 32
lea rbx, [rsp + 8]
mov rsi, rbx
call (outlined init with take of output.MyEnum?)
mov rsi, rsp
mov rdi, rbx
call (outlined init with take of output.MyEnum?)
cmp byte ptr [rsp], 0
jne .LBB1_2
mov eax, 4
add rsp, 16
pop rbx
ret
.LBB1_2:
ud2
However, if you comment out the somethingTwo property from HasAnEnum, suddenly it becomes:
output.test(output.HasAnEnum) -> Swift.Int:
test dl, 1
jne .LBB1_2
mov eax, 4
ret
.LBB1_2:
ud2
So... it depends on the type which holds the enum, rather than the enum itself. That's very strange.
It's really costing a lot in terms of performance, so it would be great to have some way to opt out of this. Perhaps forcing some simpler layout on HasAnEnum so it becomes easier to access the property.