In my opinion,
assertionFailure
will be ignored in release build. But when I run codes below in release mode, assertionFailure
can run and stop the program. Why?Codes:
enum MessageType: RawRepresentable {
case news
case unknownMessageType(value: String)
init?(rawValue: String) {
assertionFailure("Tihs assertionFailure will never stop execution")
switch rawValue {
case "A":
self = .news
case "B":
self = .news
case "C":
self = .news
case "D":
self = .news
case "E":
self = .news
case "F":
self = .news
case "G":
self = .news
case "H":
self = .news
case "I":
self = .news
case "J":
self = .news
case "K":
self = .news
case "L":
self = .news
case "M":
self = .news
case "N":
self = .news
case "O":
self = .news
case "P":
self = .news
case "Q":
self = .news
case "R":
self = .news
case "S":
self = .news
case "T":
self = .news
case "U":
self = .news
default:
assertionFailure("This assertionFailure will cause a fatal error and stop execution")
self = .unknownMessageType(value: rawValue)
}
}
var rawValue: String {
switch self {
case .news:
return "A"
case .unknownMessageType(value: let value):
return value
}
}
}
his statement will cause a crash
let message = MessageType(rawValue: "aaaa")
, caused by the second assertionFailure
, not the first one.nother weird thing is if I remove any two
case
(at least two case
) in function init?(rawValue: String)
, assertionFailure will be ignored, there will not be any crash. PS, I do not disable optimization for release build. All setting is default.
I’m going to label this as a compiler bug. If you disassemble the code for
MessageType.init?(rawValue:)
you’ll see that the compiler generates no code for the first call to
assertionFailure
, which is exactly what you’d expect, but generates a bunch of code for the second call. And then if you remove the last two cases in the
switch
statement it stops generating that code and the Release build runs as expected.
I suspect that this is a failure in the compiler’s mandatory optimisation phases. Swift is unusual in that some optimisations have to run for the code to be correct, and in this case it seems that the optimisations being done by the Release build are causing this mandatory optimisation to not run.
Still, I’m hardly a compiler expert, so this is all just speculation.
I don’t think there’s anything else you can do here. It seems that the latest compiler is working as expected, so there’s no point even filing a bug.
But hey, thanks for creating a thread about this. It’s a very interesting problem.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"